]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge branch 'master' into Dev_1.1.0
authorsbh <sergey.belash@opencascade.com>
Mon, 9 Feb 2015 09:06:33 +0000 (12:06 +0300)
committersbh <sergey.belash@opencascade.com>
Mon, 9 Feb 2015 09:06:33 +0000 (12:06 +0300)
Conflicts:
src/PartSet/PartSet_WidgetSketchLabel.cpp

19 files changed:
CMakeLists.txt
doc/first_feature_help.doc [new file with mode: 0644]
doc/general_architecture.doc
doc/general_architecture_1.png
src/ConstructionPlugin/axis_widget.xml
src/Model/Model_AttributeSelection.cpp
src/Model/Model_ResultBody.cpp
src/ModelAPI/CMakeLists.txt
src/ModelAPI/ModelAPI_ShapeValidator.cpp [new file with mode: 0644]
src/ModelAPI/ModelAPI_ShapeValidator.h [new file with mode: 0644]
src/ModuleBase/ModuleBase_IModule.h
src/ModuleBase/ModuleBase_WidgetShapeSelector.cpp
src/NewGeom/resources/LightApp.xml
src/NewGeom/resources/SalomeApp.xml
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_WidgetSketchLabel.cpp
src/SketchSolver/SketchSolver_ConstraintGroup.cpp
src/XGUI/XGUI_ContextMenuMgr.cpp
src/XGUI/XGUI_Workshop.cpp

index c9f155394d7c93e59394d19792b4e653d3ec8a45..ea51439dfafdc64027a31c58cb1a4e4e09503e9f 100644 (file)
@@ -1,7 +1,7 @@
 CMAKE_MINIMUM_REQUIRED(VERSION 2.8.10)
 
 PROJECT (NewGEOM)
-SET (NewGeom_Version 0.7.1)
+SET (NewGeom_Version 1.0.0)
 
 SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeCommon" ${CMAKE_MODULE_PATH})
 
diff --git a/doc/first_feature_help.doc b/doc/first_feature_help.doc
new file mode 100644 (file)
index 0000000..c40f79d
--- /dev/null
@@ -0,0 +1,182 @@
+/*!
+\page first_feature_help How to create custom features or plugins
+
+A NewGeom module consists of one or several plug-ins which provide implementation of Module features. To extend the application functionality, developers are able to add their own features into existent plugins. Also, it is possible to create a custom plugin, if necessary. 
+\n
+This document describes the basic principles of plugin/feature system and shows how to use the API for writing a feature or plugin. Currently, the API is available for C++ and Python languages. Plugin, written in C++ is a shared object (dll); For Python, it is regular python module, with *.py extension. 
+\n
+<h3>XML configuration of the module</h3>
+By default, all application's plugins are stored in the `/plugins` folder. However, it is possible to change this path in preferences: "Preferences >> Module|Plugins >> Default Path".
+\n
+The plugins directory have to contain `plugins.xml` file, which declares plugins included in the module and describes their parameters, like this:
+\code
+<plugin library="FooPlugin" configuration="plugin-Foo.xml"/>
+\endcode
+or, for python plugin:
+\code
+<plugin script="PythonicPlugin" configuration="plugin-Pythonic.xml"/>
+\endcode
+First example declares FooPlugin, which is library (`FooPlugin.dll` or `FooPlugin.so`) with "plugin-Foo.xml" configuration file. The second - a Python module, `PythonicPlugin.py`. All the declared libraries, scripts and configuration files should be placed in the same directory as the `plugins.xml`. Note also, that `library` and `script` attributes should not contain any extensions (*.py, *.dll); However, the `configuration` attribute doesn't have any pattern and just have to match name of the plugin configuration file.
+\n
+<h3>XML configuration of a plugin</h3>
+The plugin configuration files contains description of features: 
+<ol>
+<li>Position in the main menu: workbench and group.</li>
+<li>Visual representation of feature's button: text, icon, tooltip</li>
+<li>Representation feature's in the property panel (widgets)</li>
+</ol>
+Here is example configuration for a feature for storing and editing a double value:
+\code
+<plugin>
+  <workbench id="FooTab">
+    <group "Counters">
+      <feature id="CppDoubleCounter" title="Counter">
+        <doublevalue id="DoubleCounterData" label="Value" default="0"/>
+      </feature>
+    </group>
+  </workbench>
+</plugin>
+\endcode
+Now we will show how to implement a plugin with this feature using the C++ and Python APIs.
+\n
+<h3>Creating a plugin</h3>
+First of all, you should create/modify all configuration files (*.xml) in your `plugin` directory, as shown in examples before. For `plugin-Pythonic.xml` you may use the same content as in the `plugin-Foo.xml`, just change the name of the feature, in example, to `PythonDoubleCounter`. In this case you will get two features in one workbench and group, despite the fact that they are from different plugins.
+\n
+Secondly, you should create a subclass of ModelAPI_Plugin. Constructor on the subclass should register itself in the application. In C++ it is:
+\code
+#include <ModelAPI_Plugin.h>
+//...
+class FooPlugin : public ModelAPI_Plugin {
+  
+  FooPlugin() // Constructor
+  {
+    ModelAPI_Session::get()->registerPlugin(this);
+  }
+  //...
+\endcode
+And in Python:
+\code
+import ModelAPI
+#...
+class PythonicPlugin(ModelAPI.ModelAPI_Plugin)
+  
+  def __init__(self): #constructor
+    ModelAPI.ModelAPI_Plugin.__init__(self) # call ancestor's constructor
+    aSession = ModelAPI.ModelAPI_Session.get()
+    aSession.registerPlugin(self) # register itself
+  #...
+\endcode
+Furthermore, your class must have implementation of the `createFeature(...)` method, which should create corresponding feature object by the given id:
+\code
+FeaturePtr FooPlugin::createFeature(std::string theFeatureID)
+{
+  if (theFeatureID == "CppDoubleCounter") {
+    return FeaturePtr(new CppDoubleCounter);
+  } else {
+    return FeaturePtr()
+  }
+}
+\endcode
+It is a bit more tricky for Python - you should pass the ownership of created object from Python to the application by calling the \_\_disown\_\_() method:
+\code
+    def createFeature(self, theFeatureID):
+      if theFeatureID == "PythonDoubleCounter":
+        return PythonDoubleCounter().__disown__() # passing the ownership
+      else:
+           return None
+\endcode
+Now your plugin is able to create features, declared in its configuration file. However, to register the plugin properly, its constructor must be called on loading of the library (script), like this:
+\code
+static FooPlugin* MY_FOOPLUGIN_INSTANCE = new FooPlugin();
+\endcode
+Please note, that some linux platforms required unique names for static variables.
+\n
+For Python, note that this code should be in the module's namespace (has no leading spaces):
+\code
+plugin = PythonicPlugin()
+plugin.__disown__()
+\endcode
+Plugin is created, lets pass over to the feature's implementation.
+\n
+<h3>Creating a feature</h3>
+Like a plugin, feature has its own base class - ModelAPI_Feature. 
+\code
+#include <ModelAPI_Feature.h>
+//...
+class CppDoubleCounter : public ModelAPI_Feature { //...
+\endcode
+Python:
+\code
+import ModelAPI
+#...
+class PythonDoubleCounter(ModelAPI.ModelAPI_Feature):
+
+  def __init__(self):
+    ModelAPI.ModelAPI_Feature.__init__(self) # default constructor;
+\endcode
+And like a plugin implements a functionality to create 'feature' objects by string id, feature defines which type of data should be stored in model and how this data should be processed. The `initAttributes(...)` method links feature's widget with data model:
+\code
+void ConstructionPlugin_Point::initAttributes()
+{
+  data()->addAttribute("DoubleCounterData", ModelAPI_AttributeDouble::type());
+}
+\endcode
+Python:
+\code
+  def initAttributes(self):
+    self.data().addAttribute("DoubleCounterData", ModelAPI.ModelAPI_AttributeDouble.type())
+\endcode
+As you may notice, this method defines that feature has a widget with "DoubleCounterData" id, which has Double type. Therefore, if your feature uses, in example, three widgets, the `initAttributes()` method should 'init' three attributes.
+\n
+Sometimes, it is not enough just to get data (ModelAPI_Data) from user input, and an internal logic (how to process the data) is required. The `execute()` method gives ability to implement it. In our example, we will just print the data from the input to console:
+\code
+void CppDoubleCounter::execute()
+{
+  double d = data()->real("DoubleCounterData")->value();
+  std::cout << "User input: " << d << std::endl;
+}
+\endcode
+Python:
+\code
+  def execute(self):
+    d = data().real("DoubleCounterData").value()
+       print "User input: ", d
+\endcode
+To sum everything up, we:
+<ol>
+<li>Declared two custom plugins in the plugins.xml</li>
+<li>Declared a feature for each plugin</li>
+<li>Created a custom plugin, by subclassing from ModelAPI_Plugin and implementation of `createFeature(...)` method</li>
+<li>Created a custom feature, by subclassing from ModelAPI_Feature and implementation of `initAttributes()` and `execute()` methods</li>
+</ol>
+If you writing a C++ plugin you should compile and link all sources in a dynamic link library (shared object). In Windows, do not forget to <a href="https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx">export</a> symbols.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+*/
\ No newline at end of file
index b7eaec9d6b431d5be2b15025a6e6bc8aebfbef55..e67ac88fea09b094bf12be29b60558db467c4fc6 100644 (file)
@@ -1,83 +1,61 @@
 /*!
 \page general_architecture General Architecture
 
-New GEOM is used either as a stand-alone application or as a Module integrated to the SALOME environment in order to, ultimately, replace the old GEOM.
-
-<h2>Stand-alone New GEOM</h2>
-
-When used outside SALOME, New GEOM must be hosted by an application window implementing the general ergonomics of New GEOM (the GUI), including the layout of the user interface, organization of menus, runtime help, etc.
-\n
-It is proposed that this application window can host several so-called Modules. Below, this main application window is named the Workshop.
-\n\n
-Each Module hosted by the Workshop deals with one type of document (ModelAPI_Document) only, saved in a format supported by the Module. One document type per Module. Also, in a Workshop window, only one document of a given type can be newed. So, when launching the Workshop, the user selects a type of document to be created. Then, from the application session, creating a new document will launch a new instance of the Workshop.
-\n\n
-The geometric model (i.e. the whole geometry produce by New GEOM) is created through operations, or features (ModelAPI_Feature), which define a meaningful piece of design (e.g. PartSetPlugin_Part, FeaturesPlugin_Extrusion, FeaturesPlugin_Placement, etc.). In order to easily create dedicated variants of the modeler, also to gradually develop New GEOM, each feature is implemented in a <i>Plug-in</i> (ModelAPI_Plugin, a piece of application including its own GUI, built separately from the application. It is loaded dynamically to the application). In other words, a Module is made of a collection of Plug-ins.
-\n\n
-The Workshop structures the features by related functionality presented in a tabbed interface. Each tab displays a set of available actions. These sets of features are called below <i>Workbenches</i>.
-\n\n
-Additionally, a Module can either reference or include other Modules:
-<ul>
-<li>
-A Module references another one when the document it produces references a document created by the other Module.
-In this case, each document is edited from the corresponding Module running in separate instances of the Workshop. The Workbenches of each Module are presented into distinct windows.
-</li>
-<li>
-A Module include another Module when additionally, the Module of referenced document runs into the same Workshop.
-In this context, both documents can be edited from a single instance of the Workshop. The Workbenches of both Modules are presented into the same window.
-</li>
-</ul>
-
-
-
-<h2>Application to New GEOM</h2>
-
-New GEOM is made of one Module, Set of Parts (a Set of Parts is a flat list of Parts, on the contrary of an Assembly in which the Parts are structured), including two other Modules, <i>Part</i> and <i>Properties</i>. The Set of Parts Module produces a <i>PartSet</i> document which references a list of Parts (one document per Part), the PartSet document being referenced by a Properties document (one document per PartSet).
-\n\n
-The Set of Parts, its Properties and the Parts it references are all edited from the same Workshop window. The Properties and Part documents cannot be open independently of PartSet (the corresponding Modules being available only as included in Set of Parts).
+NewGeom is made of Workshop (see XGUI_Workshop) which loads a Module, connecting its features with GUI, providing it with services for launching of operations, tools for user inputs and visualisation of results. The Module can consist of one or several plug-ins which provide implementation of Module features. Each plug-in can implement one or several features. These features can be structured by Workbenches within Workshop. Workshop provides introducing of these Workbenches within main window in form of menus or/and tool bars.
 \n
-When creating a new PartSet, a Property document is automatically created. The Workbench of the Set of Parts Module includes a feature for creating a new Part. Once the first Part is created, the Workbenches of Part Module are activated. One Part of the ParSet being always active, the features of Part Module apply to this Part.
+Workshop interacts with a Module with help of specific interface defined in ModuleBase package. Each module for NewGeom application has to implement ModuleBase_IModile interface.
 \n
-When the user saves its session, all documents are saved: the PartSet, its Properties and each Part.
-\n\n
-\image html general_architecture_1.png
+A Module manages a one document (ModelAPI_Document). This document consists of a one root document and several, loaded by request, sub-documents. Each sub-document can be stored in a single file. 
 \n
 
-<b>Summary of the general architecture of New GEOM:</b>
+<b>Main features of the general architecture of New GEOM:</b>
 <ul>
-<li> New GEOM consists of several Modules running within a Workshop.</li>
-<li> Each Module produces one type of Document only.</li>
-<li> A Module is made of Plug-in implementing the Features supported by the Module.</li>
+<li> New GEOM consists of a one Module running within a Workshop.</li>
+<li> This Module produces one type of Document only.</li>
+<li> This Document consists of a main document and several sub-documents which can be stored and loaded as separated files.</li>
+<li> A Module is made of one or several Plug-ins implementing Features supported of the Module.</li>
 <li> These Features are structured by Workbenches.</li>
-<li> A Module can provide access to the Workbenches of other Modules by including these Modules.</li>
-<li> The Modules communicate with the Workshop through Interfaces.</li>
+<li> The Module communicates with the Workshop through Interfaces.</li>
 <li> The API of New GEOM consists of the Interface of the Workshop and of Modules.</li>
-<li> A configuration file describes the composition of the Workshop where the Modules and the Plug-in are referenced by their Global Unique Identifier (GUID).</li>
+<li> A configuration file describes the composition of the Workshop where the Module and Plug-ins are referenced by their unique names.</li>
 </ul>
+\n\n
+\image html general_architecture_1.png
+\n\n
+For today there is a one implementation of NewGeom module which implements Part Set functionality (PartSet_Module).
+The geometric model (i.e. the whole geometry produce by New GEOM) is created through operations, or features (ModelAPI_Feature), which define a meaningful piece of design (see \ref Plugins group). In order to easily create dedicated variants of the modeler, also to gradually develop New GEOM, each feature is implemented in a <i>Plug-in</i> (ModelAPI_Plugin, a piece of application including its own GUI, built separately from the application. It is loaded dynamically to the application). In other words, a Module is made of a collection of Plug-ins.
+Each sub-document contains a data of a one Part. When the user saves its session, all documents are saved: the PartSet and each Part.
+\n
+New GEOM is used either as a stand-alone application or as a Module integrated to the SALOME environment in order to, ultimately, replace the old GEOM.
 
+<h2>Stand-alone New GEOM</h2>
 
+In case of using as a standalone application, Workshop uses an application main window implementing the general ergonomics of New GEOM (see \ref Desktop group), including the layout of the user interface, organization of menus, runtime help, etc.
+\n
+The Workshop structures the features by related functionality presented in a tabbed panels Workbenches. Each tab displays a set of available actions. These sets of features are called below <i>Workbenches</i>.
+\n\n
 
-<h2>New GEOM as SALOME module</h2>
 
-The NewGeom package allows to launch the application as one of the module of SALOME platform. In that case all user interface elements are integrated into SALOME platform: the \b NewGeom package is used for this connection.
+<h2>New GEOM as SALOME module</h2>
 
-Initially the New GEOM application is defined as a Light SALOME module, later it may be changed in order to manage the communication with other SALOME modules correctly.
+The NewGeom package allows to launch the application as one of the module of SALOME platform. In that case all user interface elements are integrated into SALOME platform: the \ref Salome package is used for this connection.
 \n
 To integrate New GEOM into SALOME the next steps are done:
 <ol>
-<li> LightApp_Module class from SALOME GUI LightApp package is redefined. This redefined class provides a connection between LightApp_Module interface and Workshop object of the application.</li>
-<li>Provide Workshop with a <i>module</i> mode of launching in SALOME environment. In this case it is launched without its own main window, 3d viewer and main menu.</li>
-<li>In <i>module</i> mode workshop uses:
+<li> LightApp_Module class from SALOME GUI LightApp package is redefined (see NewGeom_Module). This redefined class provides a connection between LightApp_Module interface and Workshop object of the application.</li>
+<li>Provide Workshop with a <i>SALOME</i> mode of launching in SALOME environment. In this case it is launched without its own main window, 3d viewer and main menu.</li>
+<li>In <i>SALOME</i> mode workshop uses:
   <ol>
   <li>SALOME desktop as a main window.</li>
   <li>OCC viewer from SALOME platform instead of its own 3d viewer.</li>
-  <li>SALOME main menu and toolbars for creation of workbenches commands.</li>
+  <li>SALOME main menu and tool bars for creation of workbenches commands.</li>
   <li>Object Browser of New GEOM application is used instead of SALOME Object Browser.</li>
   <li>Creation of a New GEOM property panel as a docking window of SALOME desktop.</li>
-  <li>Use SALOME Python console instead of console in main window. Since 3 packages from SALOME GUI module become shared between this project and SALOME mod-ules and they are independed from other SALOME parts, it is proposed in the future to detach it from SALOME platform into separated prerequisite product to avoid code duplication.</li>
+  <li>Use SALOME Python console instead of console in main window. Since 3 packages from SALOME GUI module become shared between this project and SALOME modules and they are independent from other SALOME parts, it is proposed in the future to detach it from SALOME platform into separated prerequisite product to avoid code duplication.</li>
   </ol>
 </li>
-<li>Each workbench will be defined as a menu in main menu bar of SALOME desktop and as a toolbar with corresponded title.</li>
-<li>Each feature in the workbench will be defined as a menu item in the corresponded menu and a button in the corresponded toolbar.</li>
+<li>Each workbench is defined as a menu in main menu bar of SALOME desktop and as a tool bar with corresponded title.</li>
+<li>Each feature in the workbench is defined as a menu item in the corresponded menu and a button in the corresponded tool bar.</li>
 <li>Object Browser of SALOME is hidden on activation of NewGEOM and restored on its deactivation.</li>
 <li>Object Browser and Property panel of NewGEOM is shown on activation of the module and hidden on its deactivation.</li>
 <li>Persistent of NewGEOM is compatible with persistent of SALOME. On saving of SALOME study the content of NewGEOM data structure is saved into study also and restored on restoring of study.</li>
index 3465128f9468567795aaf18e4a22970d279cc8f7..cde8202249a31fa9fb5a39790032f68d7cffad49 100644 (file)
Binary files a/doc/general_architecture_1.png and b/doc/general_architecture_1.png differ
index f612a83d08e470a660ae85390bfd57f6d2badecc..a3424e3f1b1d5acb8a0b43f68b91684142b7da1d 100644 (file)
@@ -14,6 +14,6 @@
     tooltip="Select a second point"
     shape_types="vertex">
     <selection_filter id="NoConstructionSubShapesFilter"/>
-    <validator id="PartSet_DifferentObjects"/>
+    <validator id="PartSet_DifferentShapes"/>
   </shape_selector>
 </source>
index 00111809ff5b962302a2faa9b69b8c15c8ee8b5a..53c04b6863ad4cb7fd7eb1dea4ce00907a292e21 100644 (file)
@@ -192,7 +192,7 @@ bool Model_AttributeSelection::update()
   if (aContext->groupName() == ModelAPI_ResultBody::group()) {
     // body: just a named shape, use selection mechanism from OCCT
     TNaming_Selector aSelector(aSelLab);
-    bool aResult = true;//aSelector.Solve(scope()) == Standard_True;
+    bool aResult = aSelector.Solve(scope()) == Standard_True;
     owner()->data()->sendAttributeUpdated(this);
     return aResult;
   } else if (aContext->groupName() == ModelAPI_ResultConstruction::group()) {
index 1351c260e9febc2b81081eafeb6d0ed91b308ecc..44b4bdbec6fc1be206bf079efa2be6214be1560a 100644 (file)
@@ -652,4 +652,4 @@ void Model_ResultBody::loadDisconnectedVertexes(std::shared_ptr<GeomAPI_Shape> t
                theTag++;
        }
   }
-}
\ No newline at end of file
+}
index 738664c17187339a52195be27b47ecc5491339b3..e8ef2bad290e75210907cb1e53a7561f1cdaad95 100644 (file)
@@ -37,6 +37,7 @@ SET(PROJECT_HEADERS
     ModelAPI_ResultValidator.h
     ModelAPI_Session.h
     ModelAPI_Tools.h
+    ModelAPI_ShapeValidator.h
     ModelAPI_Validator.h
 )
 
@@ -65,6 +66,7 @@ SET(PROJECT_SOURCES
     ModelAPI_ResultGroup.cpp
     ModelAPI_ResultPart.cpp
     ModelAPI_Session.cpp
+    ModelAPI_ShapeValidator.cpp
     ModelAPI_Tools.cpp
 )
 
diff --git a/src/ModelAPI/ModelAPI_ShapeValidator.cpp b/src/ModelAPI/ModelAPI_ShapeValidator.cpp
new file mode 100644 (file)
index 0000000..b451ed1
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        ModelAPI_ShapeValidator.cpp
+// Created:     2 Feb 2015
+// Author:      Natalia ERMOLAEVA
+
+#include "ModelAPI_ShapeValidator.h"
+
+#include <ModelAPI_AttributeSelection.h>
+#include "ModelAPI_Object.h"
+
+bool ModelAPI_ShapeValidator::isValid(const FeaturePtr& theFeature,
+                                      const AttributePtr& theAttribute,
+                                      const GeomShapePtr& theShape) const
+{
+  std::string aCurrentAttributeId = theAttribute->id();
+  // get all feature attributes
+  std::list<AttributePtr> anAttrs = 
+                   theFeature->data()->attributes(ModelAPI_AttributeSelection::type());
+  if (anAttrs.size() > 0 && theShape.get() != NULL) {
+    std::list<AttributePtr>::iterator anAttr = anAttrs.begin();
+    for(; anAttr != anAttrs.end(); anAttr++) {
+      AttributePtr anAttribute = *anAttr;
+      // take into concideration only other attributes
+      if (anAttribute.get() != NULL && anAttribute->id() != aCurrentAttributeId) {
+        AttributeSelectionPtr aSelectionAttribute = 
+          std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(anAttribute);
+        // the shape of the attribute should be not the same
+        if (aSelectionAttribute.get() != NULL && theShape->isEqual(aSelectionAttribute->value())) {
+          return false;
+        }
+      }
+    }
+  }
+  return true;
+}
diff --git a/src/ModelAPI/ModelAPI_ShapeValidator.h b/src/ModelAPI/ModelAPI_ShapeValidator.h
new file mode 100644 (file)
index 0000000..596e1c0
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        ModelAPI_ShapeValidator.h
+// Created:     2 Feb 2015
+// Author:      Natalia ERMOLAEVA
+
+#ifndef ModelAPI_ShapeValidator_H
+#define ModelAPI_ShapeValidator_H
+
+#include <ModelAPI.h>
+
+#include <ModelAPI_Validator.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Attribute.h>
+
+#include <GeomAPI_Shape.h>
+
+/**
+ * Generic validator for any attribute of a feature.
+ */
+class ModelAPI_ShapeValidator : public ModelAPI_Validator
+{
+public:
+  /// returns True if the attribute is valid. It checks whether the feature of the attribute
+  /// does not contain a selection attribute filled with the same shape
+  /// \param theFeature a feature to check
+  /// \param theAttribute an attribute to check
+  /// \param theShape a shape
+  MODELAPI_EXPORT bool isValid(const FeaturePtr& theFeature, const AttributePtr& theAttribute,
+                               const GeomShapePtr& theShape) const;
+};
+
+#endif
index 01896bb8fa3610406fe3e357df9130c9eeff5704..32c7cdcbfb7df17206a47373efb8f5b4d516ee3a 100644 (file)
@@ -127,6 +127,9 @@ protected slots:
 \r
   /// Register selection filters for this module\r
   virtual void registerFilters() {}\r
+
+  /// Register properties of this module
+  virtual void registerProperties() {}
 \r
   /// Register properties of this module\r
   virtual void registerProperties() {}\r
index 070cec76c88d88845c2fcb4b2bb20fe29d5ac6f2..81e45ef0a11c250d5709646e0dc210c9dd14acb5 100644 (file)
@@ -35,6 +35,7 @@
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_ResultValidator.h>
 #include <ModelAPI_RefAttrValidator.h>
+#include <ModelAPI_ShapeValidator.h>
 
 #include <Config_WidgetAPI.h>
 #include <Events_Error.h>
@@ -502,6 +503,17 @@ bool ModuleBase_WidgetShapeSelector::isValid(ObjectPtr theObj, std::shared_ptr<G
         return false;
       }
     }
+    else {
+      const ModelAPI_ShapeValidator* aShapeValidator = 
+                               dynamic_cast<const ModelAPI_ShapeValidator*>(*aValidator);
+      if (aShapeValidator) {
+        DataPtr aData = myFeature->data();
+        AttributeSelectionPtr aSelectAttr = aData->selection(attributeID());
+        if (!aShapeValidator->isValid(myFeature, aSelectAttr, theShape)) {
+          return false;
+        }
+      }
+    }
   }
   return true;
 }
\ No newline at end of file
index 8695fb272baeedad6e25515a687c5581503ca3c3..9ce081a007afb21f7c20b454d6b3b4307e7a75ef 100644 (file)
@@ -23,7 +23,7 @@
     <!-- Major module parameters -->
     <parameter name="name" value="NewGeom"/>
     <parameter name="icon" value="newgeom.png"/>
-    <parameter name="version" value="0.7.0"/>
+    <parameter name="version" value="1.0.0"/>
     <parameter name="documentation" value="newgeom_help"/>
   </section>
   <section name="newgeom_help" >
index 955f7c66985bb870bdb80f01268956c6e255b0b7..2bec8495515fdb6e2bb1fb7bf7a3d55dcce08062 100644 (file)
@@ -27,7 +27,7 @@
     <!-- Major module parameters -->
     <parameter name="name" value="NewGeom"/>
     <parameter name="icon" value="newgeom.png"/>
-    <parameter name="version" value="0.7.0"/>
+    <parameter name="version" value="1.0.0"/>
     <parameter name="documentation" value="newgeom_help"/>
   </section>
   <section name="newgeom_help" >
index cd0f44109e5537405f39ef6e23bef37f2e84b40a..c3b59579668d445b63acc6eff22d7ab3a6dac072 100644 (file)
@@ -26,6 +26,7 @@
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Session.h>
+#include <ModelAPI_ShapeValidator.h>
 
 #include <GeomDataAPI_Point2D.h>
 #include <GeomDataAPI_Point.h>
@@ -120,6 +121,7 @@ void PartSet_Module::registerValidators()
   aFactory->registerValidator("PartSet_RadiusValidator", new PartSet_RadiusValidator);
   aFactory->registerValidator("PartSet_RigidValidator", new PartSet_RigidValidator);
   aFactory->registerValidator("PartSet_DifferentObjects", new PartSet_DifferentObjectsValidator);
+  aFactory->registerValidator("PartSet_DifferentShapes", new ModelAPI_ShapeValidator);
   aFactory->registerValidator("PartSet_SketchValidator", new PartSet_SketchValidator);
 }
 
@@ -203,15 +205,28 @@ void PartSet_Module::operationStopped(ModuleBase_Operation* theOperation)
 bool PartSet_Module::canDisplayObject(const ObjectPtr& theObject) const
 {
   bool aCanDisplay = false;
-  if (mySketchMgr->activeSketch()) {
+  CompositeFeaturePtr aSketchFeature = mySketchMgr->activeSketch();
+  if (aSketchFeature.get() != NULL) {
     FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
 
-    if (aFeature.get() != NULL) {
-      if (aFeature == mySketchMgr->activeSketch()) {
+    // MPV: the second and third conditions to avoid crash on exit for application
+    if (aFeature.get() != NULL && aFeature->data().get() && aFeature->data()->isValid()) {
+      if (aFeature == aSketchFeature) {
         aCanDisplay = false;
       }
-      else {
-        aCanDisplay = mySketchMgr->sketchOperationIdList().contains(aFeature->getKind().c_str());
+      else if (aSketchFeature.get() && aSketchFeature->data().get() &&
+               aSketchFeature->data()->isValid()) {
+        for (int i = 0; i < aSketchFeature->numberOfSubs() && !aCanDisplay; i++) {
+          FeaturePtr aSubFeature = aSketchFeature->subFeature(i);
+          std::list<ResultPtr> aResults = aSubFeature->results();
+          std::list<ResultPtr>::const_iterator aIt;
+          for (aIt = aResults.begin(); aIt != aResults.end() && !aCanDisplay; ++aIt) {
+            if (theObject == (*aIt))
+              aCanDisplay = true;
+          }
+          if (aSubFeature == theObject)
+            aCanDisplay = true;
+        }
       }
     }
   }
index 159624efa7cd8309d092f426e3a7558f9427fc1b..1e9d79070eb5a41837512e6b5ede0469edba7144 100644 (file)
@@ -39,7 +39,6 @@
 #include <QApplication>
 
 
-
 PartSet_WidgetSketchLabel::PartSet_WidgetSketchLabel(QWidget* theParent,
                                                      const Config_WidgetAPI* theData,
                                                      const std::string& theParentId)
index 1b1a621c251d6a46d114c6a4baf646aa5b77ade7..3cb51724764bb3d49f163e25583e4cb04aa9a209 100644 (file)
@@ -904,7 +904,7 @@ bool SketchSolver_ConstraintGroup::resolveConstraints()
         updateRelatedConstraints(anEntIter->first);
     }
     // unblock all features then
-    for (; anEntIter != myEntityAttrMap.end(); anEntIter++) {
+    for (anEntIter = myEntityAttrMap.begin(); anEntIter != myEntityAttrMap.end(); anEntIter++) {
       if (anEntIter->first->owner().get() && anEntIter->first->owner()->data().get())
         anEntIter->first->owner()->data()->blockSendAttributeUpdated(false);
     }
index b4fa78dabe741599dcb8f55684cd1f7d26e25d28..8072aa81d21853732f448c98ff3ce121dd08e953 100644 (file)
@@ -147,7 +147,7 @@ QMenu* XGUI_ContextMenuMgr::objectBrowserMenu() const
             aMenu->addAction(action("DEACTIVATE_PART_CMD"));
           else
             aMenu->addAction(action("ACTIVATE_PART_CMD"));
-        } else if (hasFeature) {
+        } else if (hasFeature && aObject->document() == aMgr->activeDocument()) {
           aMenu->addAction(action("EDIT_CMD"));
         } else {
           if (aDisplayer->isVisible(aObject)) {
index fd63e89e812a8ad3d4f606530327e2e3140dabca..84d3d6a10354f5d6d8f7117f623b79823ff0cfb5 100644 (file)
@@ -593,7 +593,7 @@ void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation)
   setNestedFeatures(theOperation);
 
   if (theOperation->getDescription()->hasXmlRepresentation()) {  //!< No need for property panel
-    connectWithOperation(theOperation);
+    // connectWithOperation(theOperation); already connected
     setPropertyPanel(theOperation);
   }
   updateCommandStatus();