]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge branch 'master' into BR_PYTHON_PLUGIN
authorSergey BELASH <belash.sergey@opencascade.com>
Mon, 17 Nov 2014 14:43:52 +0000 (17:43 +0300)
committerSergey BELASH <belash.sergey@opencascade.com>
Mon, 17 Nov 2014 14:43:52 +0000 (17:43 +0300)
70 files changed:
src/Events/CMakeLists.txt
src/Events/Events_MessageGroup.cpp [new file with mode: 0644]
src/Events/Events_MessageGroup.h
src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp
src/ExchangePlugin/ExchangePlugin_ImportFeature.h
src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp
src/FeaturesPlugin/extrusion_widget.xml
src/GeomAlgoAPI/GeomAlgoAPI.i
src/Model/CMakeLists.txt
src/Model/Model_Application.cpp
src/Model/Model_Application.h
src/Model/Model_AttributeRefAttr.cpp
src/Model/Model_AttributeSelection.cpp
src/Model/Model_AttributeSelectionList.cpp
src/Model/Model_AttributeSelectionList.h
src/Model/Model_Document.cpp
src/Model/Model_Document.h
src/Model/Model_ResultGroup.cpp
src/Model/Model_Session.cpp
src/Model/Model_Session.h
src/Model/Model_Update.cpp
src/Model/Model_Validator.cpp
src/ModelAPI/ModelAPI_Document.h
src/ModelAPI/ModelAPI_Session.h
src/ModelAPI/ModelAPI_Tools.cpp
src/ModuleBase/ModuleBase_IViewer.h
src/ModuleBase/ModuleBase_Operation.cpp
src/ModuleBase/ModuleBase_Operation.h
src/ModuleBase/ModuleBase_ViewerFilters.cpp
src/ModuleBase/ModuleBase_ViewerFilters.h
src/ModuleBase/ModuleBase_WidgetChoice.cpp
src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp
src/ModuleBase/ModuleBase_WidgetFeature.cpp
src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp
src/ModuleBase/ModuleBase_WidgetShapeSelector.cpp
src/ModuleBase/ModuleBase_WidgetShapeSelector.h
src/NewGeom/NewGeom_Module.cpp
src/NewGeom/NewGeom_Module.h
src/NewGeom/NewGeom_SalomeViewer.cpp
src/NewGeom/NewGeom_SalomeViewer.h
src/PartSet/PartSet_OperationFeatureBase.cpp
src/PartSet/PartSet_OperationFeatureBase.h
src/PartSet/PartSet_OperationFeatureCreate.cpp
src/PartSet/PartSet_OperationFeatureCreate.h
src/PartSet/PartSet_OperationFeatureEdit.cpp
src/PartSet/PartSet_OperationFeatureEdit.h
src/PartSet/PartSet_OperationSketch.cpp
src/PartSet/PartSet_OperationSketch.h
src/PartSet/PartSet_Tools.cpp
src/PartSet/PartSet_Tools.h
src/PartSet/PartSet_WidgetSketchLabel.cpp
src/PartSet/PartSet_WidgetSketchLabel.h
src/SketchPlugin/SketchPlugin_Circle.cpp
src/SketchPlugin/SketchPlugin_ConstraintDistance.cpp
src/SketchPlugin/SketchPlugin_ConstraintDistance.h
src/SketchPlugin/SketchPlugin_Line.cpp
src/SketchPlugin/SketchPlugin_Sketch.cpp
src/SketchPlugin/Test/TestConstraintConcidence.py
src/SketchSolver/SketchSolver_ConstraintGroup.cpp
src/SketchSolver/SketchSolver_ConstraintManager.cpp
src/XGUI/XGUI_ContextMenuMgr.cpp
src/XGUI/XGUI_DocumentDataModel.cpp
src/XGUI/XGUI_PartDataModel.cpp
src/XGUI/XGUI_SalomeConnector.h
src/XGUI/XGUI_Selection.cpp
src/XGUI/XGUI_Viewer.cpp
src/XGUI/XGUI_Viewer.h
src/XGUI/XGUI_ViewerProxy.cpp
src/XGUI/XGUI_ViewerProxy.h
src/XGUI/XGUI_Workshop.cpp

index b33e8516623d2ae4080d88f0472f2d9277a12ec3..52369991ce4cf15a11cd77ccc8b05c559cc25731 100644 (file)
@@ -12,6 +12,7 @@ SET(PROJECT_HEADERS
 
 SET(PROJECT_SOURCES
     Events_Message.cpp
+    Events_MessageGroup.cpp
     Events_Listener.cpp
     Events_Loop.cpp
     Events_Error.cpp
diff --git a/src/Events/Events_MessageGroup.cpp b/src/Events/Events_MessageGroup.cpp
new file mode 100644 (file)
index 0000000..799f71e
--- /dev/null
@@ -0,0 +1,13 @@
+// File:       Events_MessageGroup.cpp
+// Created:    Thu Mar 13 2014
+// Author:     Mikhail PONIKAROV
+
+#include <Events_MessageGroup.h>
+
+Events_MessageGroup::Events_MessageGroup(const Events_ID theID, const void* theSender)
+: Events_Message(theID, theSender)
+{}
+
+Events_MessageGroup::~Events_MessageGroup()
+{}
+
index 46c765cce99a9aab7b870674fe0817ff46f6cccf..b41d4ffcb557d08fa0d2883cf9b55f2cfe5089e1 100644 (file)
@@ -21,14 +21,9 @@ class EVENTS_EXPORT Events_MessageGroup : public Events_Message
  public:
 
   //! Creates the message
-  Events_MessageGroup(const Events_ID theID, const void* theSender = 0)
-      : Events_Message(theID, theSender)
-  {
-  }
+  Events_MessageGroup(const Events_ID theID, const void* theSender = 0);
   //! do nothing in the destructor yet
-  virtual ~Events_MessageGroup()
-  {
-  }
+  virtual ~Events_MessageGroup();
 
   //! Creates a new empty group (to store it in the loop before flush)
   virtual boost::shared_ptr<Events_MessageGroup> newEmpty() = 0;
index a0c659805f2f72c7a7ad9441c91a3fad5107f316..13a61e5469ce0c4e152e4415f9c09f38b525976d 100644 (file)
@@ -15,7 +15,6 @@
 #include <ModelAPI_Document.h>
 #include <ModelAPI_Object.h>
 #include <ModelAPI_ResultBody.h>
-
 #include <TCollection_AsciiString.hxx>
 #include <TDF_Label.hxx>
 #include <TopoDS_Shape.hxx>
@@ -109,18 +108,35 @@ bool ExchangePlugin_ImportFeature::importFile(const std::string& theFileName)
  #endif
      return false;
    }
+  //
    // Pass the results into the model
    std::string anObjectName = aPath.Name().ToCString();
    data()->setName(anObjectName);
-   boost::shared_ptr<ModelAPI_ResultBody> aResult = document()->createBody(data());
+   boost::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data());
    boost::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
    aGeomShape->setImpl(new TopoDS_Shape(aShape));
-   aResult->store(aGeomShape);
-   setResult(aResult);
+
+   //LoadNamingDS of the imported shape
+   loadNamingDS(aGeomShape, aResultBody);
+
+   setResult(aResultBody);
 
    return true;
 }
 
+//============================================================================
+void ExchangePlugin_ImportFeature::loadNamingDS(
+                                   boost::shared_ptr<GeomAPI_Shape> theGeomShape, 
+                                            boost::shared_ptr<ModelAPI_ResultBody> theResultBody)
+{  
+  //load result
+  theResultBody->store(theGeomShape);
+  int aTag(1);
+  theResultBody->loadFirstLevel(theGeomShape, aTag);
+  theResultBody->loadDisconnectedEdges(theGeomShape, aTag);
+  theResultBody->loadDisconnectedVertexes(theGeomShape, aTag); 
+}
+
 LibHandle ExchangePlugin_ImportFeature::loadImportPlugin(const std::string& theFormatName)
 {
   std::string aLibName = library(theFormatName + ID());
index f5747807267792edae667eea97e399c0c32cc6b6..6a90bf0b9014b11c8c568113a9eac2c005a46270 100644 (file)
@@ -63,7 +63,11 @@ class ExchangePlugin_ImportFeature : public ModelAPI_Feature
  protected:
   EXCHANGEPLUGIN_EXPORT bool importFile(const std::string& theFileName);
   EXCHANGEPLUGIN_EXPORT LibHandle loadImportPlugin(const std::string& theFormatName);
-  
+
+private:
+  /// Loads Naming data structure to the document
+  void loadNamingDS(boost::shared_ptr<GeomAPI_Shape> theGeomShape, 
+                                       boost::shared_ptr<ModelAPI_ResultBody> theResultBody);
 };
 
 #endif /* IMPORT_IMPORTFEATURE_H_ */
index e582019b4839f3d18ee494cd9ff39c0f60860873..de5cdbf2204eaf94ad0be7e3a4c87ac07dbcaa36 100644 (file)
@@ -83,6 +83,13 @@ void FeaturesPlugin_Boolean::execute()
     Events_Error::send(aFeatureError, this);
     return;
   }  
+  // if result of Boolean operation is same as was before it means that Boolean operation has no sence
+  // and naming provides no result, so, generate an error in this case
+  if (anObject->isEqual(aFeature->shape())) {
+    std::string aFeatureError = "Boolean feature: operation was not performed";  
+    Events_Error::send(aFeatureError, this);
+    return;
+  }
   //LoadNamingDS
   LoadNamingDS(aFeature, aResultBody, anObject, aTool, aType);
 
index c7c5f4bdd90bebae461edbd3873fae7ace5471a5..da2d99d2dbed4c7f7856c7db807b3d1bb7515bbb 100644 (file)
@@ -5,6 +5,7 @@
     tooltip="Select a face for extrusion"
     activate="true"
     shape_types="face"
+       object_types="construction"
     use_subshapes="true"
   />
   <doublevalue id="extrusion_size" label="Size" min="0" step="1.0" default="1" icon=":icons/dimension_v.png" tooltip="Set size of extrusion">
index c43f350dc4bdb9e9d3471ae71ea82d293bd9cdb4..c2dbb80f02aea85a57e2eaae35826df36bf43faf 100644 (file)
@@ -6,6 +6,7 @@
   #include "GeomAlgoAPI_FaceBuilder.h"
   #include "GeomAlgoAPI_EdgeBuilder.h"
   #include "GeomAlgoAPI_PointBuilder.h"
+  #include "GeomAlgoAPI_SketchBuilder.h"
 %}
 
 // to avoid error on this
 // standard definitions
 %include "typemaps.i"
 %include "std_string.i"
+%include "std_list.i"
 //%include <std_shared_ptr.i>
 %include <boost_shared_ptr.i>
 
+%template(ShapeList) std::list<boost::shared_ptr<GeomAPI_Shape> >;
+
 // all supported interfaces
 %include "GeomAlgoAPI_FaceBuilder.h"
 %include "GeomAlgoAPI_EdgeBuilder.h"
 %include "GeomAlgoAPI_PointBuilder.h"
+%include "GeomAlgoAPI_SketchBuilder.h"
index 753fd7817bd14c5ae8a34540513e7a195f95a24a..3d7716827fd526888c7f9a57d31c866e9b176e7c 100644 (file)
@@ -67,7 +67,7 @@ SET(PROJECT_LIBRARIES
 
 
 ADD_DEFINITIONS(-DMODEL_EXPORTS ${CAS_DEFINITIONS} ${BOOST_DEFINITIONS})
-ADD_LIBRARY(Model SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS})
+ADD_LIBRARY(Model MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS})
 TARGET_LINK_LIBRARIES(Model ${PROJECT_LIBRARIES})
 
 INCLUDE_DIRECTORIES(
index 23ecf05ae7f2109317f435566ad88d2b17a63c2a..d53dc665c679dcd14f69eca5b2881a10655b910b 100644 (file)
@@ -40,7 +40,17 @@ const boost::shared_ptr<Model_Document>& Model_Application::getDocument(string t
 
 void Model_Application::deleteDocument(string theDocID)
 {
-  myDocs.erase(theDocID);
+  if (myDocs.find(theDocID) != myDocs.end()) {
+    myDocs[theDocID]->close(true);
+    myDocs.erase(theDocID);
+  }
+  myLoadedByDemand.clear();
+}
+
+void Model_Application::deleteAllDocuments()
+{
+  myDocs.clear();
+  myLoadedByDemand.clear();
 }
 
 //=======================================================================
index ae68024eec9443ce54dd8f0d12ccf87887f4752e..d9eb4bb200cc3b1ece948bda72524aed6d5707d7 100644 (file)
@@ -36,6 +36,8 @@ class Model_Application : public TDocStd_Application
   MODEL_EXPORT bool hasDocument(std::string theDocID);
   //! Deletes the document from the application
   MODEL_EXPORT void deleteDocument(std::string theDocID);
+  //! Deletes all documents existing in the application
+  MODEL_EXPORT void deleteAllDocuments();
 
   //! Set path for the loaded by demand documents
   void setLoadPath(std::string thePath);
index 85446ef248a618c2990e3120ea82de0bb38d2e02..4e8a52b0e195119681a8903e3ca0fcb84968d436 100644 (file)
@@ -39,7 +39,7 @@ boost::shared_ptr<ModelAPI_Attribute> Model_AttributeRefAttr::attr()
 
 void Model_AttributeRefAttr::setObject(ObjectPtr theObject)
 {
-  if (!myIsInitialized || myID->Get().Length() != 0 || object() != theObject) {
+  if (theObject && (!myIsInitialized || myID->Get().Length() != 0 || object() != theObject)) {
     boost::shared_ptr<Model_Data> aData = boost::dynamic_pointer_cast<Model_Data>(
         theObject->data());
     myRef->Set(aData->label().Father());
index c284b49eb48291e09625458a7ecaa732e20bb1d0..05888b5d73f1834fad0dd005dc7e8c65bf9a7e9f 100644 (file)
@@ -114,9 +114,7 @@ bool Model_AttributeSelection::update()
       boost::dynamic_pointer_cast<GeomAPI_PlanarEdges>(
       boost::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext)->shape());
     if (aWirePtr && aWirePtr->hasPlane()) {
-      boost::shared_ptr<Model_Data> aData = 
-        boost::dynamic_pointer_cast<Model_Data>(owner()->data());
-      TDF_Label aLab = aData->label();
+      TDF_Label aLab = myRef.myRef->Label();
       // getting a type of selected shape
       Handle(TDataStd_Integer) aTypeAttr;
       if (!aLab.FindAttribute(TDataStd_Integer::GetID(), aTypeAttr)) {
@@ -305,7 +303,7 @@ void Model_AttributeSelection::selectConstruction(
     return; // saving of context is enough: result construction contains exactly the needed shape
   }
   boost::shared_ptr<Model_Data> aData = boost::dynamic_pointer_cast<Model_Data>(owner()->data());
-  TDF_Label aLab = aData->label();
+  TDF_Label aLab = myRef.myRef->Label();
   // identify the reuslts of sub-object of the composite by edges
   const TopoDS_Shape& aSubShape = theSubShape->impl<TopoDS_Shape>();
   // save type of the selected shape in integer attribute
@@ -325,6 +323,7 @@ void Model_AttributeSelection::selectConstruction(
   }
   // iterate and store the result ids of sub-elements
   Handle(TDataStd_IntPackedMap) aRefs = TDataStd_IntPackedMap::Set(aLab);
+  aRefs->Clear();
   const int aSubNum = aComposite->numberOfSubs();
   for(int a = 0; a < aSubNum; a++) {
     FeaturePtr aSub = aComposite->subFeature(a);
index e1cb750aab27fc804b051e4c8539dc277be2c0f9..4a2012a3323ec367dcbdb404f54d706023ce442a 100644 (file)
@@ -23,7 +23,6 @@ void Model_AttributeSelectionList::append(
   if (owner()) {
     aNewAttr->setObject(owner());
   }
-  mySubs.push_back(aNewAttr);
   mySize->Set(aNewTag);
   aNewAttr->setValue(theContext, theSubShape);
   owner()->data()->sendAttributeUpdated(this);
@@ -47,14 +46,22 @@ void Model_AttributeSelectionList::setSelectionType(int theType)
 boost::shared_ptr<ModelAPI_AttributeSelection> 
   Model_AttributeSelectionList::value(const int theIndex)
 {
-  return mySubs[theIndex];
+  TDF_Label aLabel = mySize->Label().FindChild(theIndex + 1);
+  // create a new attribute each time, by demand
+  // supporting of old attributes is too slow (synch each time) and buggy on redo
+  // (if attribute is deleted and created, the abort updates attriute and makes the Attr invalid)
+  boost::shared_ptr<Model_AttributeSelection> aNewAttr = 
+    boost::shared_ptr<Model_AttributeSelection>(new Model_AttributeSelection(aLabel));
+  if (owner()) {
+    aNewAttr->setObject(owner());
+  }
+  return aNewAttr;
 }
 
 void Model_AttributeSelectionList::clear()
 {
-  if (!mySubs.empty()) {
+  if (mySize->Get() != 0) {
     mySize->Set(0);
-    mySubs.clear();
     TDF_ChildIterator aSubIter(mySize->Label());
     for(; aSubIter.More(); aSubIter.Next()) {
       aSubIter.Value().ForgetAllAttributes(Standard_True);
@@ -70,24 +77,6 @@ Model_AttributeSelectionList::Model_AttributeSelectionList(TDF_Label& theLabel)
     mySize = TDataStd_Integer::Set(theLabel, 0);
     mySelectionType = TDataStd_Real::Set(theLabel, 0);
   } else { // recollect mySubs
-    int aNum = mySize->Get();
-    TDF_ChildIterator aSubIter(theLabel);
-    for(; aSubIter.More(), aNum != 0; aSubIter.Next(), aNum--) {
-      TDF_Label aChildLab = aSubIter.Value();
-      boost::shared_ptr<Model_AttributeSelection> aNewAttr = 
-        boost::shared_ptr<Model_AttributeSelection>(new Model_AttributeSelection(aChildLab));
-      if (owner())
-        aNewAttr->setObject(owner());
-      mySubs.push_back(aNewAttr);
-    }
-  }
-}
-
-void Model_AttributeSelectionList::setObject(const boost::shared_ptr<ModelAPI_Object>& theObject)
-{
-  ModelAPI_AttributeSelectionList::setObject(theObject);
-  std::vector<boost::shared_ptr<Model_AttributeSelection> >::iterator aSubIter = mySubs.begin();
-  for(; aSubIter != mySubs.end(); aSubIter++) {
-    (*aSubIter)->setObject(theObject);
+    theLabel.FindAttribute(TDataStd_Real::GetID(), mySelectionType);
   }
 }
index f10d6d97fa0e21e35c0aa3e2cd5b6d28e71929b7..e52937e72e37dfc8af9fcdf031cba833f04e5a28 100644 (file)
@@ -22,7 +22,6 @@ class Model_AttributeSelectionList : public ModelAPI_AttributeSelectionList
 {
   Handle(TDataStd_Integer) mySize;  ///< Contains size of this list
   Handle(TDataStd_Real) mySelectionType;  ///< Contains current index, TODO: make it integer, not real
-  std::vector<boost::shared_ptr<Model_AttributeSelection> > mySubs; /// the selection attributes
 public:
   /// Adds the new reference to the end of the list
   MODEL_EXPORT virtual void append(
@@ -41,13 +40,9 @@ public:
   /// Returns all attributes
   MODEL_EXPORT virtual void clear();
 
-  /// Sets the feature object
-  MODEL_EXPORT virtual void setObject(const boost::shared_ptr<ModelAPI_Object>& theObject);
-
 protected:
   /// Objects are created for features automatically
   MODEL_EXPORT Model_AttributeSelectionList(TDF_Label& theLabel);
-    /// Performs the selection for the body result (TNaming Selection)
 
   friend class Model_Data;
 };
index 8bb7c7809bce575ab456c856da75880378202186..1c902856732f4aa9100a62885cc807cb1870db9d 100644 (file)
@@ -202,7 +202,7 @@ bool Model_Document::save(const char* theFileName, std::list<std::string>& theRe
   return isDone;
 }
 
-void Model_Document::close()
+void Model_Document::close(const bool theForever)
 {
   boost::shared_ptr<ModelAPI_Session> aPM = Model_Session::get();
   if (this != aPM->moduleDocument().get() && this == aPM->activeDocument().get()) {
@@ -211,14 +211,36 @@ void Model_Document::close()
   // close all subs
   std::set<std::string>::iterator aSubIter = mySubs.begin();
   for (; aSubIter != mySubs.end(); aSubIter++)
-    subDoc(*aSubIter)->close();
+    subDoc(*aSubIter)->close(theForever);
   mySubs.clear();
-  // close this only if it is module document, otherwise it can be undoed
-  if (this == aPM->moduleDocument().get()) {
+
+  // close for thid document needs no transaction in this document
+  boost::static_pointer_cast<Model_Session>(Model_Session::get())->setCheckTransactions(false);
+
+  // delete all features of this document
+  boost::shared_ptr<ModelAPI_Document> aThis = 
+    Model_Application::getApplication()->getDocument(myID);
+  Events_Loop* aLoop = Events_Loop::loop();
+  NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeaturesIter(myObjs);
+  for(; aFeaturesIter.More(); aFeaturesIter.Next()) {
+    FeaturePtr aFeature = aFeaturesIter.Value();
+    static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+    ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_Feature::group());
+    ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP);
+    aFeature->eraseResults();
+    aFeature->erase();
+  }
+  myObjs.Clear();
+  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
+  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+
+  // close all only if it is really asked, otherwise it can be undoed/redoed
+  if (theForever) {
     if (myDoc->CanClose() == CDM_CCS_OK)
       myDoc->Close();
-    Model_Application::getApplication()->deleteDocument(myID);
   }
+
+  boost::static_pointer_cast<Model_Session>(Model_Session::get())->setCheckTransactions(true);
 }
 
 void Model_Document::startOperation()
@@ -253,7 +275,13 @@ bool Model_Document::compactNested()
   }
   myIsEmptyTr[myTransactionsAfterSave] = allWasEmpty;
   myTransactionsAfterSave++;
-  myDoc->PerformDeltaCompaction();
+  if (allWasEmpty) {
+    // Issue 151: if everything is empty, it is a problem for OCCT to work with it, 
+    // just commit the empty that returns nothing
+    myDoc->CommitCommand();
+  } else {
+    myDoc->PerformDeltaCompaction();
+  }
   return !allWasEmpty;
 }
 
@@ -310,10 +338,8 @@ void Model_Document::abortOperation()
 {
   if (myNestedNum > 0 && !myDoc->HasOpenCommand()) {  // abort all what was done in nested
       // first compact all nested
-    if (compactNested()) {
-      // for nested it is undo and clear redos
-      myDoc->Undo();
-    }
+    compactNested();
+    myDoc->Undo();
     myDoc->ClearRedos();
     myTransactionsAfterSave--;
     myIsEmptyTr.erase(myTransactionsAfterSave);
@@ -496,18 +522,20 @@ void Model_Document::removeFeature(FeaturePtr theFeature, const bool theCheck)
   }
 
   boost::shared_ptr<Model_Data> aData = boost::static_pointer_cast<Model_Data>(theFeature->data());
-  TDF_Label aFeatureLabel = aData->label().Father();
-  if (myObjs.IsBound(aFeatureLabel))
-    myObjs.UnBind(aFeatureLabel);
-  else
-    return;  // not found feature => do not remove
-  // erase fields
-  theFeature->erase();
-  // erase all attributes under the label of feature
-  aFeatureLabel.ForgetAllAttributes();
-  // remove it from the references array
-  if (theFeature->isInHistory()) {
-    RemoveFromRefArray(featuresLabel(), aFeatureLabel);
+  if (aData) {
+    TDF_Label aFeatureLabel = aData->label().Father();
+    if (myObjs.IsBound(aFeatureLabel))
+      myObjs.UnBind(aFeatureLabel);
+    else
+      return;  // not found feature => do not remove
+    // erase fields
+    theFeature->erase();
+    // erase all attributes under the label of feature
+    aFeatureLabel.ForgetAllAttributes();
+    // remove it from the references array
+    if (theFeature->isInHistory()) {
+      RemoveFromRefArray(featuresLabel(), aFeatureLabel);
+    }
   }
   // event: feature is deleted
   ModelAPI_EventCreator::get()->sendDeleted(theFeature->document(), ModelAPI_Feature::group());
@@ -625,6 +653,8 @@ int Model_Document::size(const std::string& theGroupID, const bool theHidden)
     for (; aLabIter.More(); aLabIter.Next()) {
       TDF_Label aFLabel = aLabIter.Value()->Label();
       FeaturePtr aFeature = feature(aFLabel);
+      if (!aFeature) // may be on close
+        continue;
       const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
       std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
       for (; aRIter != aResults.cend(); aRIter++) {
@@ -737,9 +767,6 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool t
       // event: model is updated
       static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
       ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent);
-
-      // update results of the appeared feature
-      updateResults(aFeature);
     } else {  // nothing is changed, both iterators are incremented
       aFeature = myObjs.Find(aFeatureLabel);
       aKeptFeatures.insert(aFeature);
@@ -747,9 +774,18 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool t
         static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
         ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent);
       }
+    }
+  }
+  // update results of thefeatures (after features created because they may be connected, like sketch and sub elements)
+  TDF_ChildIDIterator aLabIter2(featuresLabel(), TDataStd_Comment::GetID());
+  for (; aLabIter2.More(); aLabIter2.Next()) {
+    TDF_Label aFeatureLabel = aLabIter2.Value()->Label();
+    if (myObjs.IsBound(aFeatureLabel)) {  // a new feature is inserted
+      FeaturePtr aFeature = myObjs.Find(aFeatureLabel);
       updateResults(aFeature);
     }
   }
+
   // check all features are checked: if not => it was removed
   NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myObjs);
   while (aFIter.More()) {
@@ -957,11 +993,11 @@ boost::shared_ptr<ModelAPI_Feature> Model_Document::feature(
 void Model_Document::updateResults(FeaturePtr theFeature)
 {
   // for not persistent is will be done by parametric updater automatically
-  if (!theFeature->isPersistentResult()) return;
+  //if (!theFeature->isPersistentResult()) return;
   // check the existing results and remove them if there is nothing on the label
   std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
   while(aResIter != theFeature->results().cend()) {
-    ResultBodyPtr aBody = boost::dynamic_pointer_cast<ModelAPI_ResultBody>(*aResIter);
+    ResultPtr aBody = boost::dynamic_pointer_cast<ModelAPI_Result>(*aResIter);
     if (aBody) {
       if (!aBody->data()->isValid()) { 
         // found a disappeared result => remove it
@@ -988,8 +1024,12 @@ void Model_Document::updateResults(FeaturePtr theFeature)
           aNewBody = createBody(theFeature->data(), aResIndex);
         } else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) {
           aNewBody = createPart(theFeature->data(), aResIndex);
-        } else if (aGroup->Get() != ModelAPI_ResultConstruction::group().c_str() &&
-          aGroup->Get() != ModelAPI_ResultGroup::group().c_str()) {
+        } else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) {
+          theFeature->execute(); // construction shapes are needed for sketch solver
+          break;
+        } else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) {
+          aNewBody = createGroup(theFeature->data(), aResIndex);
+        } else {
           Events_Error::send(std::string("Unknown type of result is found in the document:") +
             TCollection_AsciiString(aGroup->Get()).ToCString());
         }
index d8743f0994d03ffe707df3d26605251531c81f6f..05d7d76eb39afc65b01e095272fa50258e97e9fb 100644 (file)
@@ -49,7 +49,8 @@ class Model_Document : public ModelAPI_Document
   MODEL_EXPORT virtual bool save(const char* theFileName, std::list<std::string>& theResults);
 
   //! Removes document data
-  MODEL_EXPORT virtual void close();
+  //! \param theForever if it is false, document is just hiden (to keep possibility make it back on Undo/Redo)
+  MODEL_EXPORT virtual void close(const bool theForever = false);
 
   //! Starts a new operation (opens a tansaction)
   MODEL_EXPORT virtual void startOperation();
index 2fd1ead9d9caec79bc5472699d5c108bafd9a236..3e467395d827eded82e71d7e8ceb128c715bc4df 100644 (file)
@@ -19,7 +19,7 @@ boost::shared_ptr<GeomAPI_Shape> Model_ResultGroup::shape() const
     AttributeSelectionListPtr aList = myOwnerData->selectionList("group_list");
     if (aList) {
       std::list<boost::shared_ptr<GeomAPI_Shape> > aSubs;
-      for(int a = aList->size(); a >= 0; a--) {
+      for(int a = aList->size() - 1; a >= 0; a--) {
         boost::shared_ptr<GeomAPI_Shape> aSelection = aList->value(a)->value();
         if (aSelection && !aSelection->isNull()) {
           aSubs.push_back(aSelection);
index 16a4d07f0bc2d242ffd2b63de10d32fdc5e8978a..409e91cbf29380bbc9289cde5b68b71e208c7e28 100644 (file)
@@ -39,6 +39,12 @@ bool Model_Session::save(const char* theFileName, std::list<std::string>& theRes
   return ROOT_DOC->save(theFileName, theResults);
 }
 
+void Model_Session::closeAll()
+{
+  ROOT_DOC->close(true);
+  Model_Application::getApplication()->deleteAllDocuments();
+}
+
 void Model_Session::startOperation()
 {
   ROOT_DOC->startOperation();
@@ -96,6 +102,9 @@ FeaturePtr Model_Session::createFeature(string theFeatureID)
     return myImpl->createFeature(theFeatureID);
   }
 
+  // load all information about plugins, features and attributes
+  LoadPluginsInfo();
+
   if (myPlugins.find(theFeatureID) != myPlugins.end()) {
     std::pair<std::string, std::string>& aPlugin = myPlugins[theFeatureID]; // plugin and doc kind
     if (!aPlugin.second.empty() && aPlugin.second != activeDocument()->kind()) {
@@ -212,9 +221,6 @@ Model_Session::Model_Session()
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED), 0, true);
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED), 0, true);
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_VALIDATOR_LOADED));
-  
-  // load all information about plugins, features and attributes
-  LoadPluginsInfo();
 }
 
 void Model_Session::processEvent(const boost::shared_ptr<Events_Message>& theMessage)
index fd4f9c0b5ac3e35a1800082dbba8b67bf2036521..5186a2497f7da6ad3ccc9da9ea1b707089db7f44 100644 (file)
@@ -43,6 +43,9 @@ class Model_Session : public ModelAPI_Session, public Events_Listener
   //! \returns true if file was stored successfully
   MODEL_EXPORT virtual bool save(const char* theFileName, std::list<std::string>& theResults);
 
+  //! Closes all documents
+  MODEL_EXPORT virtual void closeAll();
+
   //! Starts a new operation (opens a tansaction)
   MODEL_EXPORT virtual void startOperation();
   //! Finishes the previously started operation (closes the transaction)
index b6a4a9553860f80e52cb95204d788390132c45a0..910527bb2702fdc4d93185b0fb557870d5c76b17 100644 (file)
@@ -38,6 +38,8 @@ Model_Update::Model_Update()
   aLoop->registerListener(this, kCreatedEvent);
   static const Events_ID kUpdatedEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED);
   aLoop->registerListener(this, kUpdatedEvent);
+  static const Events_ID kMovedEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED);
+  aLoop->registerListener(this, kMovedEvent);
   static const Events_ID kOpFinishEvent = aLoop->eventByName("FinishOperation");
   aLoop->registerListener(this, kOpFinishEvent);
   static const Events_ID kOpAbortEvent = aLoop->eventByName("AbortOperation");
@@ -45,7 +47,7 @@ Model_Update::Model_Update()
   static const Events_ID kOpStartEvent = aLoop->eventByName("StartOperation");
   aLoop->registerListener(this, kOpStartEvent);
 
-  Config_PropManager::registerProp("Model update", "automatic_rebuild", "Rebuild automatically",
+  Config_PropManager::registerProp("Model update", "automatic_rebuild", "Rebuild immediately",
                                    Config_Prop::Bool, "false");
   isAutomatic = Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true";
 }
@@ -57,6 +59,7 @@ void Model_Update::processEvent(const boost::shared_ptr<Events_Message>& theMess
   static const Events_ID kRebuildEvent = aLoop->eventByName("Rebuild");
   static const Events_ID kCreatedEvent = aLoop->eventByName(EVENT_OBJECT_CREATED);
   static const Events_ID kUpdatedEvent = aLoop->eventByName(EVENT_OBJECT_UPDATED);
+  static const Events_ID kMovedEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED);
   static const Events_ID kOpFinishEvent = aLoop->eventByName("FinishOperation");
   static const Events_ID kOpAbortEvent = aLoop->eventByName("AbortOperation");
   static const Events_ID kOpStartEvent = aLoop->eventByName("StartOperation");
@@ -69,7 +72,8 @@ void Model_Update::processEvent(const boost::shared_ptr<Events_Message>& theMess
       isAutomaticChanged = true;
       isAutomatic = true;
     }
-  } else if (theMessage->eventID() == kCreatedEvent || theMessage->eventID() == kUpdatedEvent) {
+  } else if (theMessage->eventID() == kCreatedEvent || theMessage->eventID() == kUpdatedEvent ||
+    theMessage->eventID() == kMovedEvent) {
     boost::shared_ptr<ModelAPI_ObjectUpdatedMessage> aMsg =
         boost::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
     const std::set<ObjectPtr>& anObjs = aMsg->objects();
@@ -77,6 +81,8 @@ void Model_Update::processEvent(const boost::shared_ptr<Events_Message>& theMess
     for(; anObjIter != anObjs.cend(); anObjIter++) {
       myJustCreatedOrUpdated.insert(*anObjIter);
     }
+    if (theMessage->eventID() == kMovedEvent)
+      return; // this event is for solver update, not here
   } else if (theMessage->eventID() == kOpStartEvent) {
     myJustCreatedOrUpdated.clear();
     return; // we don't need the update only on operation start (caused problems in PartSet_Listener::processEvent)
@@ -85,6 +91,23 @@ void Model_Update::processEvent(const boost::shared_ptr<Events_Message>& theMess
       isAutomaticChanged = true;
       isAutomatic = true;
     }
+    // the hardcode (DBC asked): hide the sketch referenced by extrusion on apply
+    if (theMessage->eventID() == kOpFinishEvent) {
+      std::set<boost::shared_ptr<ModelAPI_Object> >::iterator aFIter;
+      for(aFIter = myJustCreatedOrUpdated.begin(); aFIter != myJustCreatedOrUpdated.end(); aFIter++)
+      {
+        FeaturePtr aF = boost::dynamic_pointer_cast<ModelAPI_Feature>(*aFIter);
+        if (aF && aF->getKind() == "Extrusion") {
+          if (aF->selection("extrusion_face")) {
+            ResultPtr aSketchRes = aF->selection("extrusion_face")->context();
+            if (aSketchRes) {
+              static Events_ID HIDE_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TOHIDE);
+              ModelAPI_EventCreator::get()->sendUpdated(aSketchRes, HIDE_DISP);
+            }
+          }
+        }
+      }
+    }
   }
 
   if (isExecuted)
@@ -173,12 +196,6 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
         if (updateFeature(aComposite->subFeature(a)))
           aMustbeUpdated = true;
       }
-      if (aMustbeUpdated) {
-        for(int a = 0; a < aSubsNum; a++) {
-          if (aComposite->subFeature(a) && aFactory->validate(aComposite->subFeature(a)))
-            aComposite->subFeature(a)->execute();
-        }
-      }
     }
     // check all references: if referenced objects are updated, this object also must be updated
     std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
@@ -195,6 +212,7 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
       }
     }
 
+    //std::cout<<"Update feature "<<theFeature->getKind()<<" must be updated = "<<aMustbeUpdated<<std::endl;
     // execute feature if it must be updated
     if (aMustbeUpdated) {
       if (boost::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures() ||
@@ -203,6 +221,7 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
           if (isAutomatic || (myJustCreatedOrUpdated.find(theFeature) != myJustCreatedOrUpdated.end()) ||
             !theFeature->isPersistentResult() /* execute quick, not persistent results */) 
           {
+            //std::cout<<"Execute feature "<<theFeature->getKind()<<std::endl;
             // before execution update the selection attributes if any
             list<AttributePtr> aRefs = 
               theFeature->data()->attributes(ModelAPI_AttributeSelection::type());
@@ -220,6 +239,26 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
                   aSel->value(a)->update();
               }
             }
+            // for sketch after update of plane (by update of selection attribute)
+            // but before execute, all sub-elements also must be updated (due to the plane changes)
+            if (aComposite) {
+              int aSubsNum = aComposite->numberOfSubs();
+              for(int a = 0; a < aSubsNum; a++) {
+                FeaturePtr aSub = aComposite->subFeature(a);
+                bool aWasModified = myUpdated[aSub];
+                myUpdated.erase(myUpdated.find(aSub)); // erase to update for sure (plane may be changed)
+                myInitial.insert(aSub);
+                updateFeature(aSub);
+                myUpdated[aSub] = aWasModified; // restore value
+              }
+              // re-execute after update: solver may update the previous values, so, shapes must be
+              // updated
+              for(int a = 0; a < aSubsNum; a++) {
+                if (aComposite->subFeature(a) && aFactory->validate(aComposite->subFeature(a)))
+                  aComposite->subFeature(a)->execute();
+              }
+            }
+
             // execute in try-catch to avoid internal problems of the feature
             try {
               theFeature->execute();
index 9db3a3cba7593cc8f9629c51c2c3fbb31d1d1b0b..e7750131efbb85114cf02d19b6663c2fb963ee4e 100644 (file)
@@ -10,8 +10,6 @@
 #include <ModelAPI_AttributeValidator.h>
 #include <Events_Error.h>
 
-const static std::string kDefaultId = "Model_FeatureValidator";
-
 void Model_ValidatorsFactory::registerValidator(const std::string& theID,
   ModelAPI_Validator* theValidator)
 {
@@ -121,6 +119,7 @@ void Model_ValidatorsFactory::validators(const std::string& theFeatureID,
 Model_ValidatorsFactory::Model_ValidatorsFactory()
   : ModelAPI_ValidatorsFactory()
 {
+  const static std::string kDefaultId = "Model_FeatureValidator";
   registerValidator(kDefaultId, new Model_FeatureValidator);
 }
 
@@ -135,6 +134,7 @@ const ModelAPI_Validator* Model_ValidatorsFactory::validator(const std::string&
 
 void Model_ValidatorsFactory::addDefaultValidators(std::list<ModelAPI_Validator*>& theValidators) const
 {
+  const static std::string kDefaultId = "Model_FeatureValidator";
   std::map<std::string, ModelAPI_Validator*>::const_iterator it = myIDs.find(kDefaultId);
   if(it == myIDs.end())
     return;
@@ -143,6 +143,7 @@ void Model_ValidatorsFactory::addDefaultValidators(std::list<ModelAPI_Validator*
 
 bool Model_ValidatorsFactory::validate(const boost::shared_ptr<ModelAPI_Feature>& theFeature) const
 {
+  const static std::string kDefaultId = "Model_FeatureValidator";
   // check feature validators first
   std::map<std::string, AttrValidators>::const_iterator aFeature = 
     myFeatures.find(theFeature->getKind());
@@ -213,6 +214,7 @@ bool Model_ValidatorsFactory::validate(const boost::shared_ptr<ModelAPI_Feature>
 
 void Model_ValidatorsFactory::registerNotObligatory(std::string theFeature, std::string theAttribute)
 {
+  const static std::string kDefaultId = "Model_FeatureValidator";
   std::map<std::string, ModelAPI_Validator*>::const_iterator it = myIDs.find(kDefaultId);
   if (it != myIDs.end()) {
     Model_FeatureValidator* aValidator = dynamic_cast<Model_FeatureValidator*>(it->second);
index 703ab0f881cebeb997bbf62d9fe3b5d4747ec1f8..0b67c44f1b7e526ac6297b1c62850362cdbdf3a1 100644 (file)
@@ -35,7 +35,8 @@ public:
   virtual const std::string& kind() const = 0;
 
   //! Removes document data
-  virtual void close() = 0;
+  //! \param theForever if it is false, document is just hiden (to keep possibility make it back on Undo/Redo)
+  virtual void close(const bool theForever = false) = 0;
 
   //! Adds to the document the new feature of the given feature id
   //! \param creates feature and puts it in the document (if it is not action)
index 6160e8e237a785d9b7140e6c24a8e53fd8d7d015..9f30af65833bfaadc902a12921bf9794cbfa03b4 100644 (file)
@@ -40,6 +40,9 @@ class MODELAPI_EXPORT ModelAPI_Session
   //! \returns true if file was stored successfully
   virtual bool save(const char* theFileName, std::list<std::string>& theResults) = 0;
 
+  //! Closes all documents
+  virtual void closeAll() = 0;
+
   //! Starts a new operation (opens a tansaction)
   virtual void startOperation() = 0;
   //! Finishes the previously started operation (closes the transaction)
index 52b88b5b05aa4200a5d298039ed8bf6bbf34503a..8656f2fd7545adda30c425bc11eeeee263e04519 100644 (file)
@@ -5,19 +5,25 @@
 #include "ModelAPI_Tools.h"
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultGroup.h>
 
 namespace ModelAPI_Tools {
 
-boost::shared_ptr<GeomAPI_Shape> shape(const ResultPtr& theResult)
-{
-  ResultBodyPtr aBody = boost::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
-  if (aBody)
-    return aBody->shape();
-  ResultConstructionPtr aConstruct = boost::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+  boost::shared_ptr<GeomAPI_Shape> shape(const ResultPtr& theResult)
+  {
+
+    ResultBodyPtr aBody = boost::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
+    if (aBody)
+      return aBody->shape();
+
+    ResultConstructionPtr aConstruct = boost::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
       theResult);
-  if (aConstruct)
-    return aConstruct->shape();
-  return boost::shared_ptr<GeomAPI_Shape>();
-}
+    if (aConstruct)
+      return aConstruct->shape();
 
+    ResultGroupPtr aGroup = boost::dynamic_pointer_cast<ModelAPI_ResultGroup>(theResult);
+    if (aGroup)
+      return aGroup->shape();
+    return boost::shared_ptr<GeomAPI_Shape>();
+  }
 }
index 6858fbefc099ee1e140d62cf06b200cbbd828ac6..3e573d22379843ca8c1c6cd5c46f9030dc1b3f10 100644 (file)
@@ -53,6 +53,14 @@ Q_OBJECT
   /// \param theZ the Z projection value
   virtual void setViewProjection(double theX, double theY, double theZ) = 0;
 
+  /// Add selection filter to the viewer
+  virtual void addSelectionFilter(const Handle(SelectMgr_Filter)& theFilter) = 0;
+
+  /// Remove selection filter from the viewer
+  virtual void removeSelectionFilter(const Handle(SelectMgr_Filter)& theFilter) = 0;
+
+  /// Remove all selection filters from the viewer
+  virtual void clearSelectionFilters() = 0;
 
 signals:
   void lastViewClosed();
index b3bf0b07572308f26b62a2fc2c177a4ae2eb24dc..e906b93233b4d133af8559521507554c0cb887f4 100644 (file)
@@ -13,6 +13,7 @@
 #include "ModuleBase_ViewerPrs.h"
 #include "ModuleBase_IPropertyPanel.h"
 #include "ModuleBase_ISelection.h"
+#include "ModuleBase_IViewer.h"
 
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_Document.h>
@@ -29,9 +30,6 @@
 
 #include <Events_Loop.h>
 
-#include <TopoDS.hxx>
-#include <TopoDS_Vertex.hxx>
-
 #ifdef _DEBUG
 #include <QDebug>
 #endif
@@ -48,6 +46,7 @@ ModuleBase_Operation::ModuleBase_Operation(const QString& theId, QObject* thePar
 ModuleBase_Operation::~ModuleBase_Operation()
 {
   delete myDescription;
+  clearPreselection();
 }
 
 QString ModuleBase_Operation::id() const
@@ -114,7 +113,7 @@ void ModuleBase_Operation::afterCommitOperation()
 
 bool ModuleBase_Operation::canBeCommitted() const
 {
-  return true;
+  return isValid();
 }
 
 void ModuleBase_Operation::flushUpdated()
@@ -255,21 +254,15 @@ bool ModuleBase_Operation::activateByPreselection()
     return false;
   
   ModuleBase_ModelWidget* aWgt, *aFilledWgt = 0;
-  ModuleBase_ViewerPrs aPrs;
   QList<ModuleBase_ModelWidget*>::const_iterator aWIt;
-  QList<ModuleBase_ViewerPrs>::const_iterator aPIt;
+  QList<ModuleBase_WidgetValueFeature*>::const_iterator aPIt;
   bool isSet = false;
   for (aWIt = aWidgets.constBegin(), aPIt = myPreSelection.constBegin();
        (aWIt != aWidgets.constEnd()) && (aPIt != myPreSelection.constEnd());
        ++aWIt, ++aPIt) {
     aWgt = (*aWIt);
-    aPrs = (*aPIt);
-    ModuleBase_WidgetValueFeature aValue;
-    aValue.setObject(aPrs.object());
-    // Check if the selection has a selected point
-    // for today it is impossible to do because
-    // the selected point demands convertation to Sketch plane 2d
-    if (!aWgt->setValue(&aValue)) {
+    ModuleBase_WidgetValueFeature* aValue = (*aPIt);
+    if (!aWgt->setValue(aValue)) {
       isSet = false;
       break;
     } else {
@@ -305,14 +298,16 @@ bool ModuleBase_Operation::activateByPreselection()
 }
 
 void ModuleBase_Operation::initSelection(ModuleBase_ISelection* theSelection,
-                                         ModuleBase_IViewer* /*theViewer*/)
+                                         ModuleBase_IViewer* theViewer)
 {
-  myPreSelection.clear();
+  clearPreselection();
 
+  QList<ModuleBase_ViewerPrs> aPreSelected;
   // Check that the selected result are not results of operation feature
-  QList<ModuleBase_ViewerPrs> aSelected = theSelection->getSelected();
   FeaturePtr aFeature = feature();
   if (aFeature) {
+    QList<ModuleBase_ViewerPrs> aSelected = theSelection->getSelected();
+
     std::list<ResultPtr> aResults = aFeature->results();
     QList<ObjectPtr> aResList;
     std::list<ResultPtr>::const_iterator aIt;
@@ -321,10 +316,23 @@ void ModuleBase_Operation::initSelection(ModuleBase_ISelection* theSelection,
 
     foreach (ModuleBase_ViewerPrs aPrs, aSelected) {
       if ((!aResList.contains(aPrs.object())) && (aPrs.object() != aFeature))
-        myPreSelection.append(aPrs);
+        aPreSelected.append(aPrs);
     }
   } else
-    myPreSelection = aSelected;
+    aPreSelected = theSelection->getSelected();
+
+  // convert the selection values to the values, which are set to the operation widgets
+
+  Handle(V3d_View) aView = theViewer->activeView();
+  foreach (ModuleBase_ViewerPrs aPrs, aPreSelected) {
+    ModuleBase_WidgetValueFeature* aValue = new ModuleBase_WidgetValueFeature();
+    aValue->setObject(aPrs.object());
+
+    double aX, anY;
+    if (getViewerPoint(aPrs, theViewer, aX, anY))
+      aValue->setPoint(boost::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aX, anY)));
+    myPreSelection.append(aValue);
+  }
 }
 
 void ModuleBase_Operation::onWidgetActivated(ModuleBase_ModelWidget* theWidget)
@@ -351,6 +359,19 @@ bool ModuleBase_Operation::setWidgetValue(ObjectPtr theFeature, double theX, dou
   return isApplyed;
 }
 
+bool ModuleBase_Operation::getViewerPoint(ModuleBase_ViewerPrs thePrs,
+                                               ModuleBase_IViewer* theViewer,
+                                               double& theX, double& theY)
+{
+  return false;
+}
+
+void ModuleBase_Operation::clearPreselection()
+{
+  while (!myPreSelection.isEmpty()) {
+    delete myPreSelection.takeFirst();
+  }
+}
 
 void ModuleBase_Operation::setPropertyPanel(ModuleBase_IPropertyPanel* theProp) 
 { 
index 07b413218a832b294cee888c56e5553b58cbee02..cf92faa43ae2191e0419561c1bd3cba22089320d 100644 (file)
@@ -23,6 +23,7 @@ class ModuleBase_OperationDescription;
 class ModuleBase_IPropertyPanel;
 class ModuleBase_ISelection;
 class ModuleBase_IViewer;
+class ModuleBase_WidgetValueFeature;
 
 class QKeyEvent;
 
@@ -217,6 +218,20 @@ signals:
   /// \return true if the point is set
   virtual bool setWidgetValue(ObjectPtr theFeature, double theX, double theY);
 
+  /// Return a widget value point by the selection and the viewer position
+  /// The default realization returns false
+  /// \param thePrs the presentation
+  /// \param theViewer a viewer to have the viewer the eye position
+  /// \param theX the horizontal coordinate
+  /// \param theY the vertical coordinate
+  /// \return true if the point exits in the selection
+  virtual bool getViewerPoint(ModuleBase_ViewerPrs thePrs,
+                                   ModuleBase_IViewer* theViewer,
+                                   double& theX, double& theY);
+
+  // Removes the preselection information and clears the map of preselection
+  void clearPreselection();
+
  protected:
   FeaturePtr myFeature;  /// the operation feature to be handled
 
@@ -233,7 +248,7 @@ signals:
   QStringList myNestedFeatures;
 
   /// List of pre-selected object 
-  QList<ModuleBase_ViewerPrs> myPreSelection;
+  QList<ModuleBase_WidgetValueFeature*> myPreSelection;
 
   /// Access to property panel
   ModuleBase_IPropertyPanel* myPropertyPanel;
index b10437101a851b008480626dab1abd86a57e9dae..1d17c685915bf7e4e47b66f1270816345d4c21a0 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Document.h>
+#include <ModelAPI_ResultConstruction.h>
 
 #include <AIS_InteractiveObject.hxx>
 #include <AIS_Shape.hxx>
@@ -36,7 +37,7 @@ Standard_Boolean ModuleBase_ShapeDocumentFilter::IsOk(const Handle(SelectMgr_Ent
       if (aObj) {
         DocumentPtr aDoc = aObj->document();
         SessionPtr aMgr = ModelAPI_Session::get();
-        return (aDoc == aMgr->activeDocument()) || (aDoc == aMgr->moduleDocument());
+        return (aDoc == aMgr->activeDocument() /* MPV: for the current moment selection in other document is not possible || (aDoc == aMgr->moduleDocument()*/);
       }
     }
   }
@@ -81,3 +82,32 @@ Standard_Boolean ModuleBase_ShapeInPlaneFilter::IsOk(const Handle(SelectMgr_Enti
   }
   return Standard_False;
 }
+
+
+IMPLEMENT_STANDARD_HANDLE(ModuleBase_ObjectTypesFilter, SelectMgr_Filter);
+IMPLEMENT_STANDARD_RTTIEXT(ModuleBase_ObjectTypesFilter, SelectMgr_Filter);
+
+
+//TODO (VSV): Check bug in OCCT: Filter result is ignored (bug25340)
+Standard_Boolean ModuleBase_ObjectTypesFilter::IsOk(const Handle(SelectMgr_EntityOwner)& theOwner) const
+{
+  Standard_Boolean isOk = ModuleBase_ShapeDocumentFilter::IsOk(theOwner);
+  if (isOk && theOwner->HasSelectable()) {
+    Handle(AIS_InteractiveObject) aAisObj = 
+      Handle(AIS_InteractiveObject)::DownCast(theOwner->Selectable());
+    if (!aAisObj.IsNull()) {
+      boost::shared_ptr<GeomAPI_AISObject> aAISObj = AISObjectPtr(new GeomAPI_AISObject());
+      aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aAisObj));
+      ObjectPtr aObj = myWorkshop->findPresentedObject(aAISObj);
+
+      foreach (QString aType, myTypes) {
+        if (aType.toLower() == "construction") {
+          ResultConstructionPtr aConstr = 
+            boost::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aObj);
+          return (aConstr != NULL);
+        } // ToDo: Process other types of objects
+      }
+    }
+  }
+  return Standard_False;
+}
index d26d3db3ed617f5db6ab13a66eb4b4b47a5e048b..e4aa93ae29b299bc3713a20f0424f7d5f6f1f712 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef ModuleBase_ViewerFilters_H
 #define ModuleBase_ViewerFilters_H
 
+#include <QStringList>
+
 #include <SelectMgr_Filter.hxx>
 #include <SelectMgr_EntityOwner.hxx>
 #include <gp_Pln.hxx>
@@ -30,7 +32,7 @@ public:
 
   DEFINE_STANDARD_RTTI(ModuleBase_ShapeDocumentFilter)
 
-private:
+protected:
   ModuleBase_IWorkshop* myWorkshop;
 };
 
@@ -52,4 +54,23 @@ private:
   gp_Pln myPlane;
 };
 
+
+/**
+* A filter which provides filtering of selection in 3d viewer.
+* Installing of this filter lets to select only object of requested type
+*/
+DEFINE_STANDARD_HANDLE(ModuleBase_ObjectTypesFilter, SelectMgr_Filter);
+class ModuleBase_ObjectTypesFilter: public ModuleBase_ShapeDocumentFilter
+{
+public:
+  Standard_EXPORT ModuleBase_ObjectTypesFilter(ModuleBase_IWorkshop* theWorkshop, const QStringList& theTypes): 
+      ModuleBase_ShapeDocumentFilter(theWorkshop), myTypes(theTypes) {}
+
+  Standard_EXPORT virtual Standard_Boolean IsOk(const Handle(SelectMgr_EntityOwner)& theOwner) const;
+
+  DEFINE_STANDARD_RTTI(ModuleBase_ObjectTypesFilter)
+private:
+  QStringList myTypes;
+};
+
 #endif
\ No newline at end of file
index 3a3ed74593529adbb266e78327d359a3717ec81d..65c6c189077c27f97a42a1eeafac4bbfb49cddc3 100644 (file)
@@ -74,7 +74,6 @@ bool ModuleBase_WidgetChoice::focusTo()
 QList<QWidget*> ModuleBase_WidgetChoice::getControls() const
 {
   QList<QWidget*> aControls;
-  aControls.append(myLabel);
   aControls.append(myCombo);
   return aControls;
 }
index 922ab91519dde70b29a459e79aa762472c752bff..7400d7f7d48db95bc329456d6a75aa6c7a567282 100644 (file)
@@ -122,7 +122,6 @@ bool ModuleBase_WidgetDoubleValue::restoreValue()
 QList<QWidget*> ModuleBase_WidgetDoubleValue::getControls() const
 {
   QList<QWidget*> aList;
-  aList.append(myLabel);
   aList.append(mySpinBox);
   return aList;
 }
index faf664fe53e9d48180ac7323988e5be4e256808f..0b84e8444cedee1262f775e5a73fb10f68487c5d 100644 (file)
@@ -155,7 +155,6 @@ QWidget* ModuleBase_WidgetFeature::getControl() const
 QList<QWidget*> ModuleBase_WidgetFeature::getControls() const
 {
   QList<QWidget*> aList;
-  aList.append(myLabel);
   aList.append(myEditor);
   return aList;
 }
index 84b0feb65cd220af4a43a2e9f72727c785c10fdd..87c62ba3909e0eae55b51f2e95a294a36b0e733b 100644 (file)
@@ -61,6 +61,7 @@ ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParen
   myUseSubShapes = theData->getBooleanAttribute("use_subshapes", false);
   //TODO_END
   connect(myTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onSelectionTypeChanged()));
+
   activateSelection(true);
 }
 
@@ -139,13 +140,35 @@ QList<QWidget*> ModuleBase_WidgetMultiSelector::getControls() const
 //********************************************************************
 bool ModuleBase_WidgetMultiSelector::eventFilter(QObject* theObj, QEvent* theEvent)
 {
-  if (theObj == myListControl) {
-    if (theEvent->type() == QEvent::FocusIn)
-      activateSelection(true);
-  }
+  //TODO: Remove maybe?
   return ModuleBase_ModelWidget::eventFilter(theObj, theEvent);
 }
 
+//********************************************************************
+void ModuleBase_WidgetMultiSelector::activateSelection(bool toActivate)
+{
+  myIsActive = toActivate;
+  if (myIsActive) {
+    connect(myWorkshop, SIGNAL(selectionChanged()), 
+            this,       SLOT(onSelectionChanged()), 
+            Qt::UniqueConnection);
+    activateShapeSelection();
+  } else {
+    disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
+    myWorkshop->deactivateSubShapesSelection();
+  }
+}
+
+//********************************************************************
+void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
+{
+  activateShapeSelection();
+  QList<ObjectPtr> anEmptyList;
+  myWorkshop->setSelected(anEmptyList);
+  // Clear mySelection, myListControl and storeValue()
+  onSelectionChanged();
+}
+
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::onSelectionChanged()
 {
@@ -160,6 +183,20 @@ void ModuleBase_WidgetMultiSelector::onSelectionChanged()
   GeomShapePtr aShape;
   for (aIt = aOwnersList.cbegin(); aIt != aOwnersList.cend(); aShpIt.Next(), aIt++) {
     ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(*aIt);
+    if (myFeature) {
+      // We can not select a result of our feature
+      const std::list<ResultPtr>& aResList = myFeature->results();
+      std::list<ResultPtr>::const_iterator aIt;
+      bool isSkipSelf = false;
+      for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) {
+        if ((*aIt) == aResult) {
+          isSkipSelf = true;
+          break;
+        }
+      }
+      if(isSkipSelf)
+        continue;
+    }
     aShape = boost::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
     aShape->setImpl(new TopoDS_Shape(aShpIt.Value()));
     mySelection.append(GeomSelection(aResult, aShape));
@@ -168,31 +205,6 @@ void ModuleBase_WidgetMultiSelector::onSelectionChanged()
   emit valuesChanged();
 }
 
-
-//********************************************************************
-void ModuleBase_WidgetMultiSelector::updateSelectionList()
-{
-  QString aType;
-  if (myTypeCombo->currentText().toLower() == "vertices")
-    aType = "vertex";
-  else if (myTypeCombo->currentText().toLower() == "edges")
-    aType = "edge";
-  else if (myTypeCombo->currentText().toLower() == "faces")
-    aType = "face";
-  else if (myTypeCombo->currentText().toLower() == "solids")
-    aType = "solid";
-  myListControl->clear();
-  int i = 1;
-  foreach (GeomSelection aSel, mySelection) {
-    QString aName(aSel.first->data()->name().c_str());
-    aName += ":" + aType + QString("_%1").arg(i);
-    myListControl->addItem(aName);
-    i++;
-  }
-}
-
-
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::filterShapes(const NCollection_List<TopoDS_Shape>& theShapesToFilter,
                                                   NCollection_List<TopoDS_Shape>& theResult)
@@ -210,34 +222,25 @@ void ModuleBase_WidgetMultiSelector::filterShapes(const NCollection_List<TopoDS_
   }
 }
 
-
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const TopAbs_ShapeEnum theShapeType)
 {
   QString aShapeTypeName;
+  
   for (int idx = 0; idx < myTypeCombo->count(); ++idx) {
     aShapeTypeName = myTypeCombo->itemText(idx);
     TopAbs_ShapeEnum aRefType = ModuleBase_WidgetShapeSelector::shapeType(aShapeTypeName);
     if(aRefType == theShapeType && idx != myTypeCombo->currentIndex()) {
+      activateSelection(false);
+      bool isBlocked = myTypeCombo->blockSignals(true);
       myTypeCombo->setCurrentIndex(idx);
+      myTypeCombo->blockSignals(isBlocked);
+      activateSelection(true);
       break;
     }
   }
 }
 
-//********************************************************************
-void ModuleBase_WidgetMultiSelector::activateSelection(bool toActivate)
-{
-  myIsActive = toActivate;
-  if (myIsActive) {
-    connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
-    //onSelectionTypeChanged();
-  } else {
-    disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
-    myWorkshop->deactivateSubShapesSelection();
-  }
-}
-
 void ModuleBase_WidgetMultiSelector::activateShapeSelection()
 {
   QString aNewType = myTypeCombo->currentText();
@@ -247,10 +250,25 @@ void ModuleBase_WidgetMultiSelector::activateShapeSelection()
 }
 
 //********************************************************************
-void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
+void ModuleBase_WidgetMultiSelector::updateSelectionList()
 {
-  QList<ObjectPtr> anEmptyList;
-  myWorkshop->setSelected(anEmptyList);
-  activateShapeSelection();
-  onSelectionChanged();
+  QString aType;
+  if (myTypeCombo->currentText().toLower() == "vertices")
+    aType = "vertex";
+  else if (myTypeCombo->currentText().toLower() == "edges")
+    aType = "edge";
+  else if (myTypeCombo->currentText().toLower() == "faces")
+    aType = "face";
+  else if (myTypeCombo->currentText().toLower() == "solids")
+    aType = "solid";
+  myListControl->clear();
+  int i = 1;
+  foreach (GeomSelection aSel, mySelection) {
+    QString aName(aSel.first->data()->name().c_str());
+    aName += ":" + aType + QString("_%1").arg(i);
+    myListControl->addItem(aName);
+    i++;
+  }
+  myListControl->repaint();
 }
index 4a53eb0438d730b3671190346966dee17abb413d..76c2da2062fa2955e807410e1198d5dd5470c3c8 100644 (file)
@@ -6,8 +6,10 @@
 #include <ModuleBase_Definitions.h>
 #include <ModuleBase_ISelection.h>
 #include <ModuleBase_IWorkshop.h>
+#include <ModuleBase_IViewer.h>
 #include <ModuleBase_Tools.h>
 #include <ModuleBase_WidgetValueFeature.h>
+
 #include <Config_WidgetAPI.h>
 #include <Events_Loop.h>
 #include <Events_Message.h>
@@ -19,6 +21,7 @@
 #include <ModelAPI_Events.h>
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Result.h>
+#include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_AttributeReference.h>
 #include <ModelAPI_AttributeSelection.h>
 #include <ModelAPI_Session.h>
@@ -98,15 +101,13 @@ ModuleBase_WidgetShapeSelector::ModuleBase_WidgetShapeSelector(QWidget* theParen
   myTextLine->setToolTip(aToolTip);
   myTextLine->installEventFilter(this);
 
-  myBasePalet = myTextLine->palette();
-  myInactivePalet = myBasePalet;
-  myInactivePalet.setBrush(QPalette::Base, QBrush(Qt::gray, Qt::Dense6Pattern));
-  myTextLine->setPalette(myInactivePalet);
-
   aLayout->addWidget(myTextLine, 1);
 
   std::string aTypes = theData->getProperty("shape_types");
-  myShapeTypes = QString(aTypes.c_str()).split(' ');
+  myShapeTypes = QString(aTypes.c_str()).split(' ', QString::SkipEmptyParts);
+
+  std::string aObjTypes = theData->getProperty("object_types");
+  myObjectTypes = QString(aObjTypes.c_str()).split(' ', QString::SkipEmptyParts);
 
   myUseSubShapes = theData->getBooleanAttribute("use_subshapes", false); 
 }
@@ -174,7 +175,6 @@ bool ModuleBase_WidgetShapeSelector::restoreValue()
 QList<QWidget*> ModuleBase_WidgetShapeSelector::getControls() const
 {
   QList<QWidget*> aControls;
-  aControls.append(myLabel);
   aControls.append(myTextLine);
   return aControls;
 }
@@ -213,6 +213,10 @@ void ModuleBase_WidgetShapeSelector::onSelectionChanged()
     if (!aShape)
       return;
 
+    /// Check that object has acceptable type
+    if (!acceptObjectType(aObject)) 
+      return;
+
     // Get sub-shapes from local selection
     if (myUseSubShapes) {
       NCollection_List<TopoDS_Shape> aShapeList;
@@ -226,10 +230,10 @@ void ModuleBase_WidgetShapeSelector::onSelectionChanged()
 
     // Check that the selection corresponds to selection type
     if (myUseSubShapes) {
-      if (!isAccepted(aShape))
+      if (!acceptSubShape(aShape))
         return;
     } else {
-      if (!isAccepted(aObject))
+      if (!acceptObjectShape(aObject))
         return;
     }
     setObject(aObject, aShape);
@@ -256,7 +260,7 @@ void ModuleBase_WidgetShapeSelector::setObject(ObjectPtr theObj, boost::shared_p
 }
 
 //********************************************************************
-bool ModuleBase_WidgetShapeSelector::isAccepted(const ObjectPtr theResult) const
+bool ModuleBase_WidgetShapeSelector::acceptObjectShape(const ObjectPtr theResult) const
 {
   ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(theResult);
 
@@ -285,7 +289,7 @@ bool ModuleBase_WidgetShapeSelector::isAccepted(const ObjectPtr theResult) const
 }
 
 //********************************************************************
-bool ModuleBase_WidgetShapeSelector::isAccepted(boost::shared_ptr<GeomAPI_Shape> theShape) const
+bool ModuleBase_WidgetShapeSelector::acceptSubShape(boost::shared_ptr<GeomAPI_Shape> theShape) const
 {
   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
   foreach (QString aType, myShapeTypes) {
@@ -295,6 +299,26 @@ bool ModuleBase_WidgetShapeSelector::isAccepted(boost::shared_ptr<GeomAPI_Shape>
   return false;
 }
 
+//********************************************************************
+bool ModuleBase_WidgetShapeSelector::acceptObjectType(const ObjectPtr theObject) const
+{
+  // Definition of types is not obligatory. If types are not defined then
+  // it means that accepted any type
+  if (myObjectTypes.isEmpty())
+    return true;
+
+  foreach (QString aType, myObjectTypes) {
+    if (aType.toLower() == "construction") {
+      ResultConstructionPtr aConstr = 
+        boost::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theObject);
+      return (aConstr != NULL);
+    } // ToDo: Process other types of objects
+  }
+  // Object type is defined but not found
+  return false;
+}
+
+
 //********************************************************************
 void ModuleBase_WidgetShapeSelector::updateSelectionName()
 {
@@ -303,17 +327,8 @@ void ModuleBase_WidgetShapeSelector::updateSelectionName()
     myTextLine->setText(QString::fromStdString(aName));
   } else {
     if (myIsActive) {
-      QString aMsg = tr("Select a ");
-      int i = 0;
-      foreach (QString aType, myShapeTypes) {
-        if (i > 0)
-          aMsg += " or ";
-        aMsg += aType;
-        i++;
-      }
-      myTextLine->setText(aMsg);
-    } else
-      myTextLine->setText(tr("No object selected"));
+      myTextLine->setText("");
+    }
   }
 }
 
@@ -322,24 +337,31 @@ void ModuleBase_WidgetShapeSelector::updateSelectionName()
 void ModuleBase_WidgetShapeSelector::activateSelection(bool toActivate)
 {
   myIsActive = toActivate;
-  if (myIsActive)
-    myTextLine->setPalette(myBasePalet);
-  else
-    myTextLine->setPalette(myInactivePalet);
   updateSelectionName();
 
   if (myIsActive) {
     connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
     if (myUseSubShapes) {
+
       QIntList aList;
       foreach (QString aType, myShapeTypes)
         aList.append(shapeType(aType));
       myWorkshop->activateSubShapesSelection(aList);
+      if (!myObjectTypes.isEmpty()) {
+        myObjTypeFilter = new ModuleBase_ObjectTypesFilter(myWorkshop, myObjectTypes);
+        myWorkshop->viewer()->clearSelectionFilters();
+        myWorkshop->viewer()->addSelectionFilter(myObjTypeFilter);
+      }
     }
   } else {
     disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
-    if (myUseSubShapes) 
+    if (myUseSubShapes) {
+      if (!myObjTypeFilter.IsNull()) {
+        myWorkshop->viewer()->removeSelectionFilter(myObjTypeFilter);
+        myObjTypeFilter.Nullify();
+      }
       myWorkshop->deactivateSubShapesSelection();
+    }
   }
 }
 
@@ -364,7 +386,7 @@ void ModuleBase_WidgetShapeSelector::raisePanel() const
 bool ModuleBase_WidgetShapeSelector::focusTo()
 {
   activateSelection(true);
-  return true;
+  return ModuleBase_ModelWidget::focusTo();
 }
 
 //********************************************************************
@@ -385,7 +407,7 @@ bool ModuleBase_WidgetShapeSelector::setValue(ModuleBase_WidgetValue* theValue)
         dynamic_cast<ModuleBase_WidgetValueFeature*>(theValue);
     if (aFeatureValue && aFeatureValue->object()) {
       ObjectPtr aObject = aFeatureValue->object();
-      if (isAccepted(aObject)) {
+      if (acceptObjectShape(aObject)) {
         setObject(aObject);
         return true;
       }
index 7d0a453f6931e4c25646fd6aac9bc739c57e5942..ad3d3b857931ff08b2f62fdc6c82137295c7473f 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "ModuleBase.h"
 #include "ModuleBase_ModelWidget.h"
+#include "ModuleBase_ViewerFilters.h"
 
 #include <ModelAPI_Object.h>
 #include <GeomAPI_Shape.h>
@@ -14,7 +15,6 @@
 #include <TopAbs_ShapeEnum.hxx>
 
 #include <QStringList>
-#include <QPalette>
 
 class Config_WidgetAPI;
 class QWidget;
@@ -63,30 +63,41 @@ Q_OBJECT
   /// \param theValue the wrapped widget value
   virtual bool setValue(ModuleBase_WidgetValue* theValue);
 
-public slots:
+ public slots:
 
   /// Activate or deactivate selection
   void activateSelection(bool toActivate);
 
-private slots:
+ private slots:
   void onSelectionChanged();
 
-protected:
+ protected:
   bool eventFilter(QObject* theObj, QEvent* theEvent);
 
-private:
   void updateSelectionName();
   void raisePanel() const;
-  bool isAccepted(const ObjectPtr theObject) const;
-  bool isAccepted(boost::shared_ptr<GeomAPI_Shape> theShape) const;
+
+  /// Returns true if shape of given object corresponds to requested shape type
+  /// This method is called only in non sub-shapes selection mode
+  virtual bool acceptObjectShape(const ObjectPtr theObject) const;
+
+  /// Returns true if selected shape corresponds to requested shape types
+  /// This method is called only in sub-shapes selection mode
+  virtual bool acceptSubShape(boost::shared_ptr<GeomAPI_Shape> theShape) const;
+
+  /// Returns true if selected object corresponds to requested Object type
+  /// Thid method is used in any selection mode
+  virtual bool acceptObjectType(const ObjectPtr theObject) const;
+
 
   // Set the given object as a value of the widget
   void setObject(ObjectPtr theObj, boost::shared_ptr<GeomAPI_Shape> theShape = boost::shared_ptr<GeomAPI_Shape>());
 
+  //----------- Class members -------------
+ private:
   QWidget* myContainer;
   QLabel* myLabel;
   QLineEdit* myTextLine;
-  //QToolButton* myActivateBtn;
 
   ModuleBase_IWorkshop* myWorkshop;
 
@@ -94,14 +105,14 @@ private:
   boost::shared_ptr<GeomAPI_Shape> myShape;
 
   QStringList myShapeTypes;
+  QStringList myObjectTypes;
 
   /// If true then local selector has to be activated in context
   bool myUseSubShapes;
 
-  QPalette myBasePalet;
-  QPalette myInactivePalet;
-
   bool myIsActive;
+
+  Handle(ModuleBase_ObjectTypesFilter) myObjTypeFilter;
 };
 
 #endif
index 6bb769fdafa20b1bfe402eca040e8418232c6361..9f8bc4543a6ee76012b5b0515195bd9c35e7f6ff 100644 (file)
@@ -70,7 +70,7 @@ private:
 //******************************************************
 NewGeom_Module::NewGeom_Module()
     : LightApp_Module("NewGeom"),
-      mySelector(0), myIsOpened(0)
+      mySelector(0), myIsOpened(0), myPopupMgr(0)
 {
   myWorkshop = new XGUI_Workshop(this);
   myProxyViewer = new NewGeom_SalomeViewer(this);
@@ -131,8 +131,7 @@ bool NewGeom_Module::activateModule(SUIT_Study* theStudy)
         mySelector = createSelector(OCCViewManagers.first());
       }
     }
-    QtxPopupMgr* aMgr = popupMgr();  // Create popup manager
-    action(myEraseAll)->setEnabled(false);
+    //action(myEraseAll)->setEnabled(false);
 
     if (myIsOpened) {
       myWorkshop->objectBrowser()->rebuildDataTree();
@@ -202,6 +201,14 @@ void NewGeom_Module::onViewManagerAdded(SUIT_ViewManager* theMgr)
   }
 }
 
+//******************************************************
+QtxPopupMgr* NewGeom_Module::popupMgr()
+{
+  if (!myPopupMgr)
+    myPopupMgr = new QtxPopupMgr( 0, this );
+  return myPopupMgr;
+}
+
 //******************************************************
 void NewGeom_Module::onDefaultPreferences()
 {
@@ -262,11 +269,12 @@ QAction* NewGeom_Module::addFeature(const QString& theWBName, const QString& the
 }
 
 //******************************************************
-QAction* NewGeom_Module::addEditCommand(const QString& theId, const QString& theTitle,
-                                        const QString& theTip, const QIcon& theIcon,
-                                        const QKeySequence& theKeys, bool isCheckable)
+QAction* NewGeom_Module::addDesktopCommand(const QString& theId, const QString& theTitle,
+                                           const QString& theTip, const QIcon& theIcon,
+                                           const QKeySequence& theKeys, bool isCheckable,
+                                           const char* theMenuSourceText, const int theMenuPosition)
 {
-  int aMenu = createMenu(tr("MEN_DESK_EDIT"), -1, -1);
+  int aMenu = createMenu(tr(theMenuSourceText), -1, -1);
 
   int aId = myActionsList.size();
   myActionsList.append(theId);
@@ -277,15 +285,15 @@ QAction* NewGeom_Module::addEditCommand(const QString& theId, const QString& the
   QAction* aAction = createAction(aId, theTip, theIcon, theTitle, theTip, aKeys, aDesk,
                                   isCheckable);
   aAction->setData(theId);
-  createMenu(aId, aMenu, 10);
+  createMenu(aId, aMenu, theMenuPosition);
   return aAction;
 }
 
 //******************************************************
-void NewGeom_Module::addEditMenuSeparator()
+void NewGeom_Module::addDesktopMenuSeparator(const char* theMenuSourceText, const int theMenuPosition)
 {
-  int aMenu = createMenu(tr("MEN_DESK_EDIT"), -1, -1);
-  createMenu(separator(), aMenu, -1, 10);
+  int aMenu = createMenu(tr(theMenuSourceText), -1, -1);
+  createMenu(separator(), aMenu, -1, theMenuPosition);
 }
 
 //******************************************************
index 11a2e10355d209d230d91c66fc519d26a77c8779..f8fdfb8f960d3e5ace4eb18f349d3932eb1e0bac 100644 (file)
@@ -38,11 +38,14 @@ Q_OBJECT
                               const QKeySequence& theKeys = QKeySequence(),
                               bool isCheckable = false);
 
-  virtual QAction* addEditCommand(const QString& theId, const QString& theTitle,
-                                  const QString& theTip, const QIcon& theIcon,
-                                  const QKeySequence& theKeys, bool isCheckable);
+  virtual QAction* addDesktopCommand(const QString& theId, const QString& theTitle,
+                                     const QString& theTip, const QIcon& theIcon,
+                                     const QKeySequence& theKeys, bool isCheckable,
+                                     const char* theMenuSourceText,
+                                     const int theMenuPosition = 10);
 
-  virtual void addEditMenuSeparator();
+  virtual void addDesktopMenuSeparator(const char* theMenuSourceText,
+                                       const int theMenuPosition = 10);
 
   virtual QMainWindow* desktop() const;
 
@@ -97,6 +100,7 @@ Q_OBJECT
 
  protected:
   CAM_DataModel* createDataModel();
+  virtual QtxPopupMgr* popupMgr();
 
  private:
   NewGeom_OCCSelector* createSelector(SUIT_ViewManager* theMgr);
@@ -115,6 +119,7 @@ Q_OBJECT
   bool myIsOpened;
   bool myIsStorePositions;
 
+  QtxPopupMgr* myPopupMgr;
 };
 
 #endif
index fe9cd2310214d6a07099bc0564055e564f2b992d..419c5d0b88e14593970b5f97fdc27ffac25ba026 100644 (file)
@@ -174,4 +174,31 @@ void NewGeom_SalomeViewer::setViewProjection(double theX, double theY, double th
       aView3d->SetZSize(0.);
     }
   }
-}
\ No newline at end of file
+}
+
+//***************************************
+void NewGeom_SalomeViewer::addSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
+{
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (!aContext.IsNull()) {
+    aContext->AddFilter(theFilter);
+  }
+}
+
+//***************************************
+void NewGeom_SalomeViewer::removeSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
+{
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (!aContext.IsNull()) {
+    aContext->RemoveFilter(theFilter);
+  }
+}
+
+//***************************************
+void NewGeom_SalomeViewer::clearSelectionFilters()
+{
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (!aContext.IsNull()) {
+    aContext->RemoveFilters();
+  }
+}
index 29bdd5218be92523f8d6de153d056fbfbded17f1..5148dcc6db73730209b1a5454d3488182656eaa3 100644 (file)
@@ -50,6 +50,15 @@ Q_OBJECT
 
   void setSelector(NewGeom_OCCSelector* theSel);
 
+  /// Add selection filter to the viewer
+  virtual void addSelectionFilter(const Handle(SelectMgr_Filter)& theFilter);
+
+  /// Remove selection filter from the viewer
+  virtual void removeSelectionFilter(const Handle(SelectMgr_Filter)& theFilter);
+
+  /// Remove all selection filters from the viewer
+  virtual void clearSelectionFilters();
+
   NewGeom_OCCSelector* selector() const
   {
     return mySelector;
index 458410aba5f87f446abc99c8d228e1a6a1b5f9bd..2d53041c0fefa5ef2e8bd84cb707fbfb3e644e53 100644 (file)
@@ -31,8 +31,6 @@
 #include <XGUI_Constants.h>
 
 #include <V3d_View.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <TopoDS.hxx>
 #include <BRep_Tool.hxx>
 
 #ifdef _DEBUG
@@ -73,19 +71,13 @@ void PartSet_OperationFeatureBase::mouseReleased(QMouseEvent* theEvent, ModuleBa
     PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY);
   } else {
     ModuleBase_ViewerPrs aPrs = aSelected.first();
+    if (getViewerPoint(aPrs, theViewer, aX, anY)) {
+      ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget();
+      PartSet_Tools::setConstraints(sketch(), feature(), aActiveWgt->attributeID(), aX, anY);
+    }
     const TopoDS_Shape& aShape = aPrs.shape();
-    if (!aShape.IsNull()) {
-      if (aShape.ShapeType() == TopAbs_VERTEX) { // a point is selected
-        const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
-        if (!aVertex.IsNull()) {
-          aPoint = BRep_Tool::Pnt(aVertex);
-          PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY);
-          ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget();
-          PartSet_Tools::setConstraints(sketch(), feature(), aActiveWgt->attributeID(), aX, anY);
-        }
-      } else if (aShape.ShapeType() == TopAbs_EDGE) { // a line is selected
-        PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY);
-      }
+    if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_EDGE) { // a line is selected
+      PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY);
     }
   }
   ObjectPtr aFeature;
@@ -101,7 +93,21 @@ void PartSet_OperationFeatureBase::mouseReleased(QMouseEvent* theEvent, ModuleBa
     flushUpdated();
     myPropertyPanel->activateNextWidget();
   }
-  commit();
+  // the operation can be committed only when there is no an active widget anymore
+  // if this check is absent, the edit operation for constraint perpendicular is stopped
+  // after the first object selection in the viewer(there are two objects to be selected)
+  // the second case is the constraint distance, the edit is stopped after any mouse click
+  // in the viewer whenever it is applyed or not to the selection control
+  if (!myPropertyPanel->activeWidget())
+    commit();
+}
+
+bool PartSet_OperationFeatureBase::getViewerPoint(ModuleBase_ViewerPrs thePrs,
+                                                       ModuleBase_IViewer* theViewer,
+                                                       double& theX, double& theY)
+{
+  return PartSet_Tools::hasVertexShape(thePrs, sketch(), theViewer->activeView(),
+                                       theX, theY);
 }
 
 /*bool PartSet_OperationFeatureBase::setWidgetValue(ObjectPtr theFeature, double theX, double theY)
index bb74a4431642c6c76b314c2a0e6103840d7bd7bf..ee290dd44cbfdffe130c7ecfefcfd7328c176a2f 100644 (file)
@@ -45,6 +45,16 @@ Q_OBJECT
   virtual void mouseReleased(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer,
                              ModuleBase_ISelection* theSelection);
 
+ protected:
+  /// Return a widget value point by the selection and the viewer position
+  /// \param thePrs the presentation
+  /// \param theViewer a viewer to have the viewer the eye position
+  /// \param theX the horizontal coordinate
+  /// \param theY the vertical coordinate
+  /// \return true if the point exits in the selection
+  virtual bool getViewerPoint(ModuleBase_ViewerPrs thePrs,
+                                   ModuleBase_IViewer* theViewer,
+                                   double& theX, double& theY);
 
  protected:
   CompositeFeaturePtr mySketch;  ///< the sketch of the feature
index 49c8b24901b0e158c54736471d5ccfcb4bf1e294..8e18b675442ca79174d1f9a4c1411d021253f06c 100644 (file)
 #include <XGUI_Constants.h>
 
 #include <V3d_View.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <TopoDS.hxx>
-#include <BRep_Tool.hxx>
-#include <TopoDS.hxx>
 
 #ifdef _DEBUG
 #include <QDebug>
@@ -71,15 +67,6 @@ bool PartSet_OperationFeatureCreate::canProcessKind(const std::string& theId)
       || theId == SketchPlugin_ConstraintRigid::ID();
 }
 
-bool PartSet_OperationFeatureCreate::canBeCommitted() const
-{
-  if (PartSet_OperationSketchBase::canBeCommitted()) {
-    //if(myActiveWidget && !myActiveWidget->isComputedDefault()) {
-    return isValid();
-  }
-  return false;
-}
-
 void PartSet_OperationFeatureCreate::mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer)
 {
     double aX, anY;
@@ -119,26 +106,20 @@ void PartSet_OperationFeatureCreate::mouseReleased(QMouseEvent* theEvent, Module
     PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY);
   } else {
     ModuleBase_ViewerPrs aPrs = aSelected.first();
+    if (getViewerPoint(aPrs, theViewer, aX, anY)) {
+      ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget();
+      PartSet_Tools::setConstraints(sketch(), feature(), aActiveWgt->attributeID(), aX, anY);
+      isClosedContour = true;
+    }
     const TopoDS_Shape& aShape = aPrs.shape();
-    if (!aShape.IsNull()) {
-      if (aShape.ShapeType() == TopAbs_VERTEX) { // a point is selected
-        const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
-        if (!aVertex.IsNull()) {
-          aPoint = BRep_Tool::Pnt(aVertex);
-          PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY);
-          ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget();
-          PartSet_Tools::setConstraints(sketch(), feature(), aActiveWgt->attributeID(), aX, anY);
-          isClosedContour = true;
-        }
-      } else if (aShape.ShapeType() == TopAbs_EDGE) { // a line is selected
-        ObjectPtr aObject = aPrs.object();
-        if (sketch()->isSub(aObject))
-          PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY);
-        else {
-          // we have to create the selected edge for the current sketch
-          ResultPtr aRes = PartSet_Tools::createFixedObjectByEdge(aPrs, sketch());
-          aSelected.first().setFeature(aRes);
-        }
+    if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_EDGE) { // a line is selected
+      ObjectPtr aObject = aPrs.object();
+      if (sketch()->isSub(aObject))
+        PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY);
+      else {
+        // we have to create the selected edge for the current sketch
+        ResultPtr aRes = PartSet_Tools::createFixedObjectByEdge(aPrs, sketch());
+        aSelected.first().setFeature(aRes);
       }
     }
   }
index bbc83f5007c9143d6b61abfac82c4eae195c9870..45e29505ef74d6b4a3d41867f2811d189e76a218 100644 (file)
@@ -88,10 +88,6 @@ Q_OBJECT
   virtual FeaturePtr createFeature(const bool theFlushMessage = true,
     CompositeFeaturePtr theCompositeFeature = CompositeFeaturePtr());
 
-  /// Verifies whether this operator can be commited.
-  /// \return Returns TRUE if current operation can be committed, e.g. all parameters are filled
-  virtual bool canBeCommitted() const;
-
 protected:
   /// Feature of previous operation (for sequintal operations)
   FeaturePtr myInitFeature;
index c91e91b851ca127bea8839c108982e73ed4f3148..a49e63dc7149ce030c9f51ffdf73a700cd07038f 100644 (file)
@@ -28,9 +28,6 @@
 #include <SketchPlugin_Line.h>
 
 #include <V3d_View.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <TopoDS.hxx>
-#include <BRep_Tool.hxx>
 #include <AIS_DimensionOwner.hxx>
 #include <AIS_DimensionSelectionMode.hxx>
 
@@ -56,42 +53,52 @@ PartSet_OperationFeatureEdit::~PartSet_OperationFeatureEdit()
 }
 
 void PartSet_OperationFeatureEdit::initSelection(ModuleBase_ISelection* theSelection,
-                                                      ModuleBase_IViewer* theViewer)
+                                                 ModuleBase_IViewer* theViewer)
 {
   // the method of the parent should is useless here because it processes the given
   // selection in different way
   //PartSet_OperationFeatureBase::initSelection(theSelection, theViewer);
 
-  // 1. unite selected and hightlighted objects in order to have an opportunity to drag
-  // by the highlighted object
-  QList<ModuleBase_ViewerPrs> aFeatures = theSelection->getSelected();
+  QList<ModuleBase_ViewerPrs> aSelected = theSelection->getSelected();
   QList<ModuleBase_ViewerPrs> aHighlighted = theSelection->getHighlighted();
-  // add highlighted elements if they are not selected
+
+  // there is a bug in OCC, where the highlighted objects are repeated and should be
+  // filtered on the unique state here
+  QList<ModuleBase_ViewerPrs> anUniqueHighlighted;
   foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) {
-    if (!PartSet_Tools::isContainPresentation(aFeatures, aPrs))
-      aFeatures.append(aPrs);
+    if (!PartSet_Tools::isContainPresentation(anUniqueHighlighted, aPrs))
+      anUniqueHighlighted.append(aPrs);
+  }
+  fillFeature2Attribute(anUniqueHighlighted, theViewer, myHighlightedFeature2Attribute);
+
+  foreach (ModuleBase_ViewerPrs aPrs, anUniqueHighlighted) {
+    if (!PartSet_Tools::isContainPresentation(aSelected, aPrs))
+      aSelected.append(aPrs);
   }
+  fillFeature2Attribute(aSelected, theViewer, myAllFeature2Attribute);
+}
 
+void PartSet_OperationFeatureEdit::fillFeature2Attribute(
+                                    const QList<ModuleBase_ViewerPrs>& thePresentations,
+                                    ModuleBase_IViewer* theViewer,
+                                    std::map<FeaturePtr, std::list<std::string> >& theFeature2Attribute)
+{
   // 1. find all features with skipping features with selected vertex shapes
-  myFeature2Attribute.clear();
+  theFeature2Attribute.clear();
   // firstly, collect the features without local selection
-  foreach (ModuleBase_ViewerPrs aPrs, aFeatures) {
-    const TopoDS_Shape& aShape = aPrs.shape();
-    if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX) { // a point is selected
-      const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
-      if (!aVertex.IsNull()) {
-        continue;
-      }
-    }
+  double aX, anY;
+  foreach (ModuleBase_ViewerPrs aPrs, thePresentations) {
+    if (getViewerPoint(aPrs, theViewer, aX, anY))
+      continue;
     else {
       ObjectPtr aObject = aPrs.object();
       if (!aObject)
         continue;
       FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
-      if (aFeature && myFeature2Attribute.find(aFeature) == myFeature2Attribute.end()) {
+      if (aFeature && theFeature2Attribute.find(aFeature) == theFeature2Attribute.end()) {
         std::list<std::string> aList;
         // using an empty list as a sign, that this feature should be moved itself
-        myFeature2Attribute[aFeature] = aList;
+        theFeature2Attribute[aFeature] = aList;
       }
     }
   }
@@ -99,13 +106,8 @@ void PartSet_OperationFeatureEdit::initSelection(ModuleBase_ISelection* theSelec
   // if the list already has this feature, the local selection is skipped
   // that means that if the selection contains a feature and a feature with local selected point,
   // the edit is performed for a full feature
-  Handle(V3d_View) aView = theViewer->activeView();
-  foreach (ModuleBase_ViewerPrs aPrs, aFeatures) {
-    const TopoDS_Shape& aShape = aPrs.shape();
-    if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX) { // a point is selected
-      const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
-      if (aVertex.IsNull())
-        continue;
+  foreach (ModuleBase_ViewerPrs aPrs, thePresentations) {
+    if (getViewerPoint(aPrs, theViewer, aX, anY)) {
       ObjectPtr aObject = aPrs.object();
       if (!aObject)
         continue;
@@ -114,18 +116,15 @@ void PartSet_OperationFeatureEdit::initSelection(ModuleBase_ISelection* theSelec
         continue;
 
       // append the attribute of the vertex if it is found on the current feature
-      gp_Pnt aPoint = BRep_Tool::Pnt(aVertex);
-      double aVX, aVY;
-      PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aVX, aVY);
       boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D = PartSet_Tools::getFeaturePoint(
-                                                                    aFeature, aVX, aVY);
+                                                                    aFeature, aX, anY);
       std::string anAttribute = aFeature->data()->id(aPoint2D);
       std::list<std::string> aList;
-      if (myFeature2Attribute.find(aFeature) != myFeature2Attribute.end())
-        aList = myFeature2Attribute[aFeature];
+      if (theFeature2Attribute.find(aFeature) != theFeature2Attribute.end())
+        aList = theFeature2Attribute[aFeature];
 
       aList.push_back(anAttribute);
-      myFeature2Attribute[aFeature] = aList;
+      theFeature2Attribute[aFeature] = aList;
     }
   }
 }
@@ -136,7 +135,10 @@ void PartSet_OperationFeatureEdit::mousePressed(QMouseEvent* theEvent, ModuleBas
   if(aActiveWgt && aActiveWgt->isViewerSelector()) {
     // Almost do nothing, all stuff in on PartSet_OperationFeatureBase::mouseReleased
     PartSet_OperationFeatureBase::mousePressed(theEvent, theViewer, theSelection);
-    return;
+    // the current point should be cleared because it is saved from the previous move and 
+    // should be reinitialized after the start moving. It is important for example for the lenght
+    // constraint where the first widget is a viewer selector.
+    myCurPoint.clear();
   }
   else {
     // commit always until the selection restore is realized (for feature and local selection)
@@ -264,9 +266,20 @@ void PartSet_OperationFeatureEdit::mouseMoved(QMouseEvent* theEvent, ModuleBase_
     //    SketchPlugin_Feature>(feature());
 
     bool isMoved = false;
+    bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
+
     // the functionality to move the feature attribute if it exists in the internal map
-    std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter = myFeature2Attribute.begin();
-    while (aFeatIter != myFeature2Attribute.end()) {
+    std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter, aFeatLast;
+    if (aHasShift || myHighlightedFeature2Attribute.empty()) {
+      aFeatIter = myAllFeature2Attribute.begin();
+      aFeatLast = myAllFeature2Attribute.end();
+    }
+    else {
+      aFeatIter = myHighlightedFeature2Attribute.begin();
+      aFeatLast = myHighlightedFeature2Attribute.end();
+    }
+
+    while (aFeatIter != aFeatLast) {
       FeaturePtr aFeature = aFeatIter->first;
       // MPV: added condition because it could be external edge of some object, not sketch
       if (aFeature && !sketch()->isSub(aFeature)) {
@@ -310,8 +323,8 @@ void PartSet_OperationFeatureEdit::mouseMoved(QMouseEvent* theEvent, ModuleBase_
     //  }
     // }
     //} // multieditoperation
+    sendFeatures(aHasShift);
   }
-  sendFeatures();
 
   myCurPoint.setPoint(aPoint);
 }
@@ -363,6 +376,18 @@ void PartSet_OperationFeatureEdit::mouseReleased(
       commit();
       emitFeaturesDeactivation();
     }
+    else if (aSelected.size() == 1) {
+     /// TODO: OCC bug: 25034 - the highlighted list should be filled not only for AIS_Shape
+     /// but for other IO, for example constraint dimensions.
+     /// It is empty and we have to use the process mouse release to start edition operation
+     /// for these objects
+      ObjectPtr anObject = aSelected.first().object();
+      FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
+      if (aFeature && PartSet_Tools::isConstraintFeature(aFeature->getKind()) &&
+          aFeature != feature()) {
+        restartOperation(PartSet_OperationFeatureEdit::Type(), aFeature);
+      }
+    }
   }
 }
 
@@ -370,9 +395,30 @@ void PartSet_OperationFeatureEdit::mouseDoubleClick(
     QMouseEvent* theEvent, Handle_V3d_View theView,
     ModuleBase_ISelection* theSelection)
 {
-  myIsBlockedByDoubleClick = true;
   // TODO the functionality is important only for constraint feature. Should be moved in another place
   QList<ModuleBase_ViewerPrs> aSelected = theSelection->getSelected();
+  // in case when the double click happens on another constraint feature when selection control is active
+  // we should not perform the double click functionality
+  // if there is no the viewer selector widget active, the operation is restarted with a correct feature
+  ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget();
+  if(aActiveWgt && aActiveWgt->isViewerSelector()) {
+    if (!aSelected.empty()) {
+      if (aSelected.size() == 1) {
+       /// TODO: OCC bug: 25034 - the highlighted list should be filled not only for AIS_Shape
+       /// but for other IO, for example constraint dimensions.
+       /// It is empty and we have to use the process mouse release to start edition operation
+       /// for these objects
+        ObjectPtr anObject = aSelected.first().object();
+        FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
+        if (aFeature && PartSet_Tools::isConstraintFeature(aFeature->getKind()) &&
+            aFeature != feature()) {
+          return;
+        }
+      }
+    }
+  }
+
+  myIsBlockedByDoubleClick = true;
   if (!aSelected.empty()) {
     ModuleBase_ViewerPrs aFeaturePrs = aSelected.first();
     if (!aFeaturePrs.owner().IsNull()) {
@@ -406,7 +452,8 @@ void PartSet_OperationFeatureEdit::stopOperation()
 
   //blockSelection(false, false);
 
-  myFeature2Attribute.clear();
+  myHighlightedFeature2Attribute.clear();
+  myAllFeature2Attribute.clear();
 }
 
 //void PartSet_OperationFeatureEdit::blockSelection(bool isBlocked, const bool isRestoreSelection)
@@ -435,12 +482,20 @@ FeaturePtr PartSet_OperationFeatureEdit::createFeature(const bool theFlushMessag
   return FeaturePtr();
 }
 
-void PartSet_OperationFeatureEdit::sendFeatures()
+void PartSet_OperationFeatureEdit::sendFeatures(const bool theIsAllFeatures)
 {
   static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
 
-  std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter = myFeature2Attribute.begin();
-  while (aFeatIter != myFeature2Attribute.end()) {
+  std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter, aFeatLast;
+  if (theIsAllFeatures || myHighlightedFeature2Attribute.empty()) {
+    aFeatIter = myAllFeature2Attribute.begin();
+    aFeatLast = myAllFeature2Attribute.end();
+  }
+  else {
+    aFeatIter = myHighlightedFeature2Attribute.begin();
+    aFeatLast = myHighlightedFeature2Attribute.end();
+  }
+  while (aFeatIter != aFeatLast) {
     FeaturePtr aFeature = aFeatIter->first;
     if (aFeature) {
       ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent);
@@ -454,8 +509,8 @@ void PartSet_OperationFeatureEdit::sendFeatures()
 
 void PartSet_OperationFeatureEdit::emitFeaturesDeactivation()
 {
-  std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter = myFeature2Attribute.begin();
-  while (aFeatIter != myFeature2Attribute.end()) {
+  std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter = myAllFeature2Attribute.begin();
+  while (aFeatIter != myAllFeature2Attribute.end()) {
     FeaturePtr aFeature = aFeatIter->first;
     if (aFeature) {
       emit featureConstructed(aFeature, FM_Deactivation);
index 7f948d5c7a1ed62126a1457c0f80132e4cdf76cb..267b494c67d2bc75b0a5833e1982e0b667481fe1 100644 (file)
@@ -124,6 +124,10 @@ Q_OBJECT
     CompositeFeaturePtr theCompositeFeature = CompositeFeaturePtr());
 
  protected:
+   void fillFeature2Attribute(const QList<ModuleBase_ViewerPrs>& thePresentations,
+                              ModuleBase_IViewer* theViewer,
+                              std::map<FeaturePtr, std::list<std::string> >& theFeature2Attribute);
+
   /// Emits a signal about the selection blocking. Emits a signal to change the selection.
   /// If the block is true, the signal clear selection, otherwise if restore selection flag allows,
   /// the internal operation features are to be selected
@@ -132,14 +136,16 @@ Q_OBJECT
   //void blockSelection(bool isBlocked, const bool isRestoreSelection = true);
 
   /// Sends the features
-  void sendFeatures();
+  /// \param theIsAllFeatures a boolean value whether all features should be send or only the highlighted ones
+  void sendFeatures(const bool theIsAllFeatures);
 
   /// Sends signal about the current features are to be deactivated
   void emitFeaturesDeactivation();
 
  private:
   // the next map should be removed when selection is processed in the move function
-  std::map<FeaturePtr, std::list<std::string> > myFeature2Attribute; /// a map of a feature to attributes
+  std::map<FeaturePtr, std::list<std::string> > myHighlightedFeature2Attribute; /// a map of a feature to attributes
+  std::map<FeaturePtr, std::list<std::string> > myAllFeature2Attribute; /// a map of a feature to attributes
 
   Point myCurPoint;  ///< the current 3D point clicked or moved
   bool myIsBlockedSelection;  ///< the state of the last state of selection blocked signal
index 5efa67ae3bab39ce884a273b7ff4d940e3f05cf1..c3ca9d922d802d974e962a87ac41eddf62f6983c 100644 (file)
@@ -128,6 +128,7 @@ void PartSet_OperationSketch::selectionChanged(ModuleBase_ISelection* theSelecti
         // Turn viewer to the plane
         emit planeSelected(aDir->x(), aDir->y(), aDir->z());
       }
+      emit updatePropPanel();
       emit launchSketch();
     }
   }
index eb3fa84f4a182368c025a3d64b05881d1ea6ecfa..216b4d94d8717741ad3198be729eaa5f6d169b57 100644 (file)
@@ -108,6 +108,9 @@ signals:
   /// Signal to define sketch mode
   void launchSketch();
 
+  /// Signal to update property panel
+  void updatePropPanel();
+
  protected:
   /// Virtual method called when operation started (see start() method for more description)
   /// Default impl calls corresponding slot and commits immediately.
index b5407f6f78a49a442fa64411b5d11eedcd93b7bc..364d7c9d20e1b0985cd195a0d0ae2f46c89a6d15 100644 (file)
@@ -46,6 +46,7 @@
 #include <BRep_Tool.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Edge.hxx>
+#include <TopoDS_Vertex.hxx>
 
 #ifdef _DEBUG
 #include <QDebug>
@@ -151,13 +152,25 @@ ObjectPtr PartSet_Tools::nearestFeature(QPoint thePoint, Handle_V3d_View theView
                                         FeaturePtr theSketch,
                                         const QList<ModuleBase_ViewerPrs>& theSelected,
                                         const QList<ModuleBase_ViewerPrs>& theHighlighted)
+{
+  // firstly it finds the feature in the list of highlight
+  ObjectPtr aDeltaObject  = nearestFeature(thePoint, theView, theSketch, theHighlighted);
+  if (!aDeltaObject)
+    // secondly it finds the feature in the list of selected objects
+    aDeltaObject  = nearestFeature(thePoint, theView, theSketch, theSelected);
+
+  return aDeltaObject;
+}
+
+ObjectPtr PartSet_Tools::nearestFeature(QPoint thePoint, Handle_V3d_View theView,
+                                        FeaturePtr theSketch,
+                                        const QList<ModuleBase_ViewerPrs>& thePresentations)
 {
   ObjectPtr aDeltaObject;
-  // 1. find the object in the highlighted list
-  if (theHighlighted.size() > 0) {
-    aDeltaObject = theHighlighted.first().object();
-  }
-  // 2. find it in the selected list by the selected point
+
+  CompositeFeaturePtr aSketch = 
+      boost::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theSketch);
+  // 1. find it in the selected list by the selected point
   if (!aDeltaObject) {
     double aX, anY;
     gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(thePoint, theView);
@@ -166,13 +179,13 @@ ObjectPtr PartSet_Tools::nearestFeature(QPoint thePoint, Handle_V3d_View theView
     FeaturePtr aFeature;
     double aMinDelta = -1;
     ModuleBase_ViewerPrs aPrs;
-    foreach (ModuleBase_ViewerPrs aPrs, theSelected) {
+    foreach (ModuleBase_ViewerPrs aPrs, thePresentations) {
       if (!aPrs.object())
         continue;
       FeaturePtr aFeature = ModelAPI_Feature::feature(aPrs.object());
       boost::shared_ptr<SketchPlugin_Feature> aSketchFeature = boost::dynamic_pointer_cast<
           SketchPlugin_Feature>(aFeature);
-      if (!aSketchFeature)
+      if (!aSketchFeature || !aSketch->isSub(aSketchFeature))
         continue;
 
       double aDelta = aSketchFeature->distanceToPoint(
@@ -183,10 +196,17 @@ ObjectPtr PartSet_Tools::nearestFeature(QPoint thePoint, Handle_V3d_View theView
       }
     }
   }
-  // 3. if the object is not found, returns the first selected one
-  if (!aDeltaObject && theSelected.size() > 0)
-    aDeltaObject = theSelected.first().object();
-
+  // 2. if the object is not found, returns the first selected sketch feature
+  if (!aDeltaObject && thePresentations.size() > 0) {
+    // there can be some highlighted objects, e.g. a result of boolean operation and a sketch point
+    foreach (ModuleBase_ViewerPrs aPrs, thePresentations) {
+      if (!aPrs.object())
+        continue;
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aPrs.object());
+      if (aFeature && aSketch->isSub(aFeature))
+        aDeltaObject = aPrs.object();
+    }
+  }
   return aDeltaObject;
 }
 
@@ -486,4 +506,24 @@ ResultPtr PartSet_Tools::findExternalEdge(CompositeFeaturePtr theSketch, boost::
     }
   }
   return ResultPtr();
-}
\ No newline at end of file
+}
+
+bool PartSet_Tools::hasVertexShape(const ModuleBase_ViewerPrs& thePrs, FeaturePtr theSketch,
+                                   Handle_V3d_View theView, double& theX, double& theY)
+{
+  bool aHasVertex = false;
+
+  const TopoDS_Shape& aShape = thePrs.shape();
+  if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX)
+  {
+    const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
+    if (!aVertex.IsNull())
+    {
+      gp_Pnt aPoint = BRep_Tool::Pnt(aVertex);
+      PartSet_Tools::convertTo2D(aPoint, theSketch, theView, theX, theY);
+      aHasVertex = true;
+    }
+  }
+
+  return aHasVertex;
+}
index a436f7b0bf372a79a904eabddfa839c11d8bc6cd..30838ae09f66fc9869e36d6e48c87a3d5a7421e0 100644 (file)
@@ -151,6 +151,27 @@ class PARTSET_EXPORT PartSet_Tools
   /// \param theEdge - the edge
   /// \return result object with external edge if it is found
   static ResultPtr findExternalEdge(CompositeFeaturePtr theSketch, boost::shared_ptr<GeomAPI_Edge> theEdge);
+
+  /// Returns whether the selected presentation has a shape with the vertex type
+  /// \param thePrs a selected presentation
+  /// \param theSketch the sketch feature
+  /// \param theView a 3D view
+  /// \param theX the output horizontal coordinate of the point
+  /// \param theY the output vertical coordinate of the point
+  static bool hasVertexShape(const ModuleBase_ViewerPrs& thePrs, FeaturePtr theSketch,
+                             Handle_V3d_View theView, double& theX, double& theY);
+protected:
+  /// Returns an object that is under the mouse point. Firstly it checks the highlighting,
+  /// if it exists, the first object is returned. Secondly, there is an iteration on
+  /// the selected list to find the point. Thirdly, if the object is not found under the
+  /// the point, the first selected object is returned.
+  /// \param thePoint a screen point
+  /// \param theView a 3D view
+  /// \param theSketch the sketch feature
+  /// \param thePresentations the list of presentations
+  static ObjectPtr nearestFeature(QPoint thePoint, Handle_V3d_View theView, FeaturePtr theSketch,
+                                  const QList<ModuleBase_ViewerPrs>& thePresentations);
+
 };
 
 #endif
index 44228fdeca844f59f71fb46242f43250b712bb73..b6f18fb7f365b654ec02be44ad573d818f7f9d93 100644 (file)
@@ -27,9 +27,7 @@ PartSet_WidgetSketchLabel::PartSet_WidgetSketchLabel(QWidget* theParent,
 
 QList<QWidget*> PartSet_WidgetSketchLabel::getControls() const
 {
-  QList<QWidget*> aLst;
-  aLst << myLabel;
-  return aLst;
+  return QList<QWidget*>();
 }
 
 QWidget* PartSet_WidgetSketchLabel::getControl() const
@@ -43,7 +41,7 @@ void PartSet_WidgetSketchLabel::setOperationsMgr(XGUI_OperationMgr* theMgr)
   if (aOperation->inherits("PartSet_OperationSketch")) {
     PartSet_OperationSketch* aSketchOpe = static_cast<PartSet_OperationSketch*>(aOperation);
     updateLabel(aSketchOpe);
-    connect(aSketchOpe, SIGNAL(planeSelected(double, double, double)), this,
+    connect(aSketchOpe, SIGNAL(updatePropPanel()), this,
             SLOT(onPlaneSelected()));
   }
 }
index 442f319074c52a5a8f34982b4a0a888897936bfb..5ad06d65d615ccac1f197b7cba1ded407f22b026 100644 (file)
@@ -23,7 +23,6 @@ Q_OBJECT
   virtual ~PartSet_WidgetSketchLabel()
   {
   }
-  ;
 
   /// Saves the internal parameters to the given feature
   /// \param theFeature a model feature to be changed
index 06ab76d14be74af9e3e6e017afddb8f246776782..a65a6b7c6ccef3c98d1bc7a6a183b663f59625ad 100644 (file)
@@ -45,6 +45,7 @@ void SketchPlugin_Circle::execute()
       boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(data()->attribute(RADIUS_ID()));
     if (aCenterAttr->isInitialized() && aRadiusAttr->isInitialized()) {
       boost::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
+      //std::cout<<"Execute circle "<<aCenter->x()<<" "<<aCenter->y()<<" "<<aCenter->z()<<std::endl;
       // make a visible point
       boost::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
       boost::shared_ptr<ModelAPI_ResultConstruction> aConstr1 = document()->createConstruction(
@@ -102,7 +103,8 @@ bool SketchPlugin_Circle::isFixed() {
 void SketchPlugin_Circle::attributeChanged() {
   static bool myIsUpdated = false; // to avoid infinitive cycle on attrubtes change
   boost::shared_ptr<GeomAPI_Shape> aSelection = data()->selection(EXTERNAL_ID())->value();
-  if (aSelection && !myIsUpdated) { // update arguments due to the selection value
+  // update arguments due to the selection value
+  if (aSelection && !aSelection->isNull() && aSelection->isEdge() && !myIsUpdated) {
     myIsUpdated = true;
     boost::shared_ptr<GeomAPI_Edge> anEdge( new GeomAPI_Edge(aSelection));
     boost::shared_ptr<GeomAPI_Circ> aCirc = anEdge->circle();
index 2e22f0c3214f7db006b79531e8ffcadb27f3bb34..89faf4208935b55f52961b8be9a7534d0663aa1a 100644 (file)
@@ -38,29 +38,8 @@ void SketchPlugin_ConstraintDistance::execute()
 
   if(anAttrValue->isInitialized())
     return;
-  boost::shared_ptr<GeomDataAPI_Point2D> aPointA =
-      getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_A());
-  boost::shared_ptr<GeomDataAPI_Point2D> aPointB =
-      getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_B());
 
-  double aDistance = -1.;
-  if (aPointA && aPointB) {  // both points
-    aDistance = aPointA->pnt()->distance(aPointB->pnt());
-  } else {
-    if (!aPointA && aPointB) {  //Line and point
-      boost::shared_ptr<SketchPlugin_Line> aLine =
-          getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_A());
-      if (aLine) {
-        aDistance = aLine->distanceToPoint(aPointB->pnt());
-      }
-    } else if (aPointA && !aPointB) {  // Point and line
-      boost::shared_ptr<SketchPlugin_Line> aLine =
-          getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_B());
-      if (aLine) {
-        aDistance = aLine->distanceToPoint(aPointA->pnt());
-      }
-    }
-  }
+  double aDistance = calculateCurrentDistance();
   if(aDistance >= 0) {
     anAttrValue->setValue(aDistance);
   }
@@ -123,6 +102,11 @@ AISObjectPtr SketchPlugin_ConstraintDistance::getAISObject(AISObjectPtr thePrevi
   boost::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = boost::dynamic_pointer_cast<
       ModelAPI_AttributeDouble>(aData->attribute(SketchPlugin_Constraint::VALUE()));
   double aValue = aValueAttr->value();
+  // Issue #196: checking the positivity of the distance constraint
+  // there is a validator for a distance constraint, that the value should be positive
+  // in case if an invalid value is set, the current distance value is shown
+  if (aValue <= 0)
+    aValue = calculateCurrentDistance();
 
   AISObjectPtr anAIS = thePrevious;
   if (!anAIS)
@@ -148,6 +132,37 @@ void SketchPlugin_ConstraintDistance::move(double theDeltaX, double theDeltaY)
   aPoint->move(theDeltaX, theDeltaY);
 }
 
+double SketchPlugin_ConstraintDistance::calculateCurrentDistance() const
+{
+  double aDistance = -1.;
+
+  boost::shared_ptr<ModelAPI_Data> aData = data();
+  boost::shared_ptr<GeomDataAPI_Point2D> aPointA =
+    getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_A());
+  boost::shared_ptr<GeomDataAPI_Point2D> aPointB =
+      getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_B());
+
+  if (aPointA && aPointB) {  // both points
+    aDistance = aPointA->pnt()->distance(aPointB->pnt());
+  } else {
+    if (!aPointA && aPointB) {  //Line and point
+      boost::shared_ptr<SketchPlugin_Line> aLine =
+          getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_A());
+      if (aLine) {
+        aDistance = aLine->distanceToPoint(aPointB->pnt());
+      }
+    } else if (aPointA && !aPointB) {  // Point and line
+      boost::shared_ptr<SketchPlugin_Line> aLine =
+          getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_B());
+      if (aLine) {
+        aDistance = aLine->distanceToPoint(aPointA->pnt());
+      }
+    }
+  }
+  return aDistance;
+}
+
+
 //*************************************************************************************
 boost::shared_ptr<GeomDataAPI_Point2D> getFeaturePoint(DataPtr theData,
                                                        const std::string& theAttribute)
index 4f4fedc627765bc8c1c770cf9ba519e72ae6f84f..b5981d017f24d418bcb0f0e3811f8cb07906a72e 100644 (file)
@@ -56,6 +56,9 @@ class SketchPlugin_ConstraintDistance : public SketchPlugin_ConstraintBase
   /// \param theDeltaY the delta for Y coordinate is moved
   SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
 
+  /// Returns the current distance between the feature attributes
+  double calculateCurrentDistance() const;
+
   /// \brief Use plugin manager for features creation
   SketchPlugin_ConstraintDistance();
 };
index 95b6de896acd8644ace08a86a29f8a48e17f047b..501478a32d77ffb80452128daa62cf759bf9fa14 100644 (file)
@@ -44,6 +44,8 @@ void SketchPlugin_Line::execute()
     if (aStartAttr->isInitialized() && anEndAttr->isInitialized()) {
       boost::shared_ptr<GeomAPI_Pnt> aStart(aSketch->to3D(aStartAttr->x(), aStartAttr->y()));
       boost::shared_ptr<GeomAPI_Pnt> anEnd(aSketch->to3D(anEndAttr->x(), anEndAttr->y()));
+      //std::cout<<"Execute line "<<aStart->x()<<" "<<aStart->y()<<" "<<aStart->z()<<" - "
+      //  <<anEnd->x()<<" "<<anEnd->y()<<" "<<anEnd->z()<<std::endl;
       // make linear edge
       boost::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, anEnd);
       // store the result
@@ -101,7 +103,7 @@ void SketchPlugin_Line::attributeChanged() {
   static bool myIsUpdated = false; // to avoid infinitive cycle on attrubtes change
   boost::shared_ptr<GeomAPI_Shape> aSelection = data()->selection(EXTERNAL_ID())->value();
    // update arguments due to the selection value
-  if (aSelection && !aSelection->isNull() && !myIsUpdated) {
+  if (aSelection && !aSelection->isNull() && aSelection->isEdge() && !myIsUpdated) {
     myIsUpdated = true;
     boost::shared_ptr<GeomAPI_Edge> anEdge( new GeomAPI_Edge(aSelection));
     boost::shared_ptr<GeomDataAPI_Point2D> aStartAttr = 
index 2b45cb65a45458a6bbb61f182e10b2fee5c92a31..e1ac62b0c8c03519117e1aa950f11469dff472d9 100644 (file)
@@ -78,6 +78,8 @@ void SketchPlugin_Sketch::execute()
   for (; anIt != aLast; anIt++) {
     aFeature = boost::dynamic_pointer_cast<SketchPlugin_Feature>(*anIt);
     if (aFeature) {
+      if (!aFeature->sketch()) // on load document the back references are missed
+        aFeature->setSketch(this);
       // do not include the external edges into the result
       if (aFeature->data()->attribute(SketchPlugin_Feature::EXTERNAL_ID())) {
         if (aFeature->data()->selection(SketchPlugin_Feature::EXTERNAL_ID())->value())
@@ -312,6 +314,7 @@ void SketchPlugin_Sketch::attributeChanged() {
       boost::shared_ptr<GeomAPI_Dir> aDir = aPlane->direction();
 
       if (kIsAttrChanged) {
+        /* now it is in updater
         // the plane was changed, so reexecute sub-elements to update shapes (located in new plane)
         ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
         list<ObjectPtr> aSubs = data()->reflist(SketchPlugin_Sketch::FEATURES_ID())->list();
@@ -322,6 +325,7 @@ void SketchPlugin_Sketch::attributeChanged() {
             aFeature->execute();
           }
         }
+        */
         kIsAttrChanged = false;
       }
     }
index dedb420a5d7d41bc0b34474d21a33d4e16c1381f..35e9ac0c8e95da10d1a7776e6d02a34aa52b869c 100644 (file)
@@ -84,9 +84,9 @@ assert (aLineStartPoint.y() == 0)
 deltaX = deltaY = 40.
 #  move line
 aSession.startOperation()
-aLineStartPoint.setValue(aLineStartPoint.x() + deltaX,
+anArcStartPoint.setValue(aLineStartPoint.x() + deltaX,
                          aLineStartPoint.y() + deltaY)
-aLineEndPoint.setValue(aLineEndPoint.x() + deltaX,
+anArcEndPoint.setValue(aLineEndPoint.x() + deltaX,
                        aLineEndPoint.y() + deltaY)
 aSession.finishOperation()
 # check that arc's points are moved also
index 7eff7e79bbab58a89e0d69f4eddabaa26e48494c..2eb18737cdfe15ad5f210365252870dea2db3df9 100644 (file)
@@ -133,6 +133,14 @@ bool SketchSolver_ConstraintGroup::isInteract(
   if (isEmpty())
     return true;
 
+  // Check if the feature is already in the group
+  if (myEntityFeatMap.find(theFeature) != myEntityFeatMap.end())
+    return true;
+  boost::shared_ptr<SketchPlugin_Constraint> aConstr =
+      boost::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
+  if (aConstr && myConstraintMap.find(aConstr) != myConstraintMap.end())
+    return true;
+
   // Go through the attributes and verify if some of them already in the group
   std::list<boost::shared_ptr<ModelAPI_Attribute>> 
       anAttrList = theFeature->data()->attributes(std::string());
@@ -241,6 +249,10 @@ bool SketchSolver_ConstraintGroup::changeConstraint(
       theConstraint->data()->attribute(SketchPlugin_Constraint::VALUE()));
   if (aDistAttr) {
     aDistance = aDistAttr->value();
+    // Issue #196: checking the positivity of the distance constraint
+    if (aDistance < tolerance &&
+       (aConstrType == SLVS_C_PT_PT_DISTANCE || aConstrType == SLVS_C_PT_LINE_DISTANCE))
+      return false;
     // SketchPlugin circle defined by its radius, but SolveSpace uses constraint for diameter
     if (aConstrType == SLVS_C_DIAMETER)
       aDistance *= 2.0;
@@ -963,9 +975,11 @@ void SketchSolver_ConstraintGroup::splitGroup(std::vector<SketchSolver_Constrain
           isFound = (aGrEntIter->find(aConstrEnt[i]) != aGrEntIter->end());
           // Also we need to check sub-entities
           int aEntPos = Search(aConstrEnt[i], myEntities);
-          Slvs_hEntity* aSub = myEntities[aEntPos].point;
-          for (int j = 0; *aSub != 0 && j < 4 && !isFound; aSub++, j++)
-            isFound = (aGrEntIter->find(*aSub) != aGrEntIter->end());
+          if (aEntPos != myEntities.size()) { // MPV: to fix the crash on close
+            Slvs_hEntity* aSub = myEntities[aEntPos].point;
+            for (int j = 0; *aSub != 0 && j < 4 && !isFound; aSub++, j++)
+              isFound = (aGrEntIter->find(*aSub) != aGrEntIter->end());
+          }
         }
       if (isFound)
         anIndexes.push_back(aGrEntIter - aGroupsEntities.begin());
@@ -977,9 +991,11 @@ void SketchSolver_ConstraintGroup::splitGroup(std::vector<SketchSolver_Constrain
         if (aConstrEnt[i] != 0) {
           aNewGrEnt.insert(aConstrEnt[i]);
           int aEntPos = Search(aConstrEnt[i], myEntities);
-          Slvs_hEntity* aSub = myEntities[aEntPos].point;
-          for (int j = 0; *aSub != 0 && j < 4; aSub++, j++)
-            aNewGrEnt.insert(*aSub);
+          if (aEntPos != myEntities.size()) { // MPV: to fix the crash on close
+            Slvs_hEntity* aSub = myEntities[aEntPos].point;
+            for (int j = 0; *aSub != 0 && j < 4; aSub++, j++)
+              aNewGrEnt.insert(*aSub);
+          }
         }
       std::set<Slvs_hConstraint> aNewGrConstr;
       aNewGrConstr.insert(aConstrIter->h);
@@ -994,9 +1010,11 @@ void SketchSolver_ConstraintGroup::splitGroup(std::vector<SketchSolver_Constrain
         if (aConstrEnt[i] != 0) {
           aGrEntIter->insert(aConstrEnt[i]);
           int aEntPos = Search(aConstrEnt[i], myEntities);
-          Slvs_hEntity* aSub = myEntities[aEntPos].point;
-          for (int j = 0; *aSub != 0 && j < 4; aSub++, j++)
-            aGrEntIter->insert(*aSub);
+          if (aEntPos != myEntities.size()) { // MPV: to fix the crash on close
+            Slvs_hEntity* aSub = myEntities[aEntPos].point;
+            for (int j = 0; *aSub != 0 && j < 4; aSub++, j++)
+              aGrEntIter->insert(*aSub);
+          }
         }
       aGroupsConstr[anIndexes.front()].insert(aConstrIter->h);
       if (aGrEntIter->size() > aGroupsEntities[aMaxNbEntities].size())
index 1dec2867f7ee2b098386b0f51ffcf5a82c12353f..ef7420ab53aea6254dc9c78829c99c72dedea9e5 100644 (file)
@@ -84,24 +84,25 @@ void SketchSolver_ConstraintManager::processEvent(
       }
     } else {
       std::set<ObjectPtr>::iterator aFeatIter;
+      // iterate sketchers fisrt to create all sketches before (on load may exist several sketches)
       for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
         FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(*aFeatIter);
         if (!aFeature)
           continue;
-        // Only sketches and constraints can be added by Create event
         const std::string& aFeatureKind = aFeature->getKind();
         if (aFeatureKind.compare(SketchPlugin_Sketch::ID()) == 0) {
           boost::shared_ptr<ModelAPI_CompositeFeature> aSketch = boost::dynamic_pointer_cast<
               ModelAPI_CompositeFeature>(aFeature);
-          if (aSketch)
-            changeWorkplane(aSketch);
-          continue;
+          changeWorkplane(aSketch);
         }
-        // Sketch plugin features can be only updated
-        boost::shared_ptr<SketchPlugin_Feature> aSFeature = boost::dynamic_pointer_cast<
-            SketchPlugin_Feature>(aFeature);
-        if (aSFeature)
-          changeConstraintOrEntity(aSFeature);
+      }
+      // then get anything but not the sketch
+      for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
+        boost::shared_ptr<SketchPlugin_Feature> aFeature = 
+          boost::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+        if (!aFeature)
+          continue;
+          changeConstraintOrEntity(aFeature);
       }
     }
 
index f951d7a279fc590625f6225a739585838f92caf9..3063959fb5f66df1708e265e0dc9412d2324818a 100644 (file)
@@ -121,64 +121,58 @@ QMenu* XGUI_ContextMenuMgr::objectBrowserMenu() const
     XGUI_Displayer* aDisplayer = myWorkshop->displayer();
     bool hasResult = false;
     bool hasFeature = false;
-    bool hasGroup = false;
     foreach(ObjectPtr aObj, aObjects)
     {
       FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
       ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(aObj);
-      ResultGroupPtr aGroupRes = boost::dynamic_pointer_cast<ModelAPI_ResultGroup>(aObj);
       if (aResult)
         hasResult = true;
       if (aFeature)
         hasFeature = true;
-      if (aGroupRes)
-        hasGroup = true;
-      if (hasFeature && hasResult && hasGroup)
+      if (hasFeature && hasResult) // && hasGroup)
         break;
     }
     //Process Feature
-    if (!hasGroup) {
-      if (aSelected == 1) {
-        ObjectPtr aObject = aObjects.first();
-        if (aObject) {
-          ResultPartPtr aPart = boost::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
-          if (aPart) {
-            if (aMgr->activeDocument() == aPart->partDoc())
-              aMenu->addAction(action("DEACTIVATE_PART_CMD"));
+    if (aSelected == 1) {
+      ObjectPtr aObject = aObjects.first();
+      if (aObject) {
+        ResultPartPtr aPart = boost::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
+        if (aPart) {
+          if (aMgr->activeDocument() == aPart->partDoc())
+            aMenu->addAction(action("DEACTIVATE_PART_CMD"));
+          else
+            aMenu->addAction(action("ACTIVATE_PART_CMD"));
+        } else if (hasFeature) {
+          aMenu->addAction(action("EDIT_CMD"));
+        } else {
+          if (aDisplayer->isVisible(aObject)) {
+            if (aDisplayer->displayMode(aObject) == XGUI_Displayer::Shading)
+              aMenu->addAction(action("WIREFRAME_CMD"));
             else
-              aMenu->addAction(action("ACTIVATE_PART_CMD"));
-          } else if (hasFeature) {
-            aMenu->addAction(action("EDIT_CMD"));
+              aMenu->addAction(action("SHADING_CMD"));
+            aMenu->addSeparator();
+            aMenu->addAction(action("HIDE_CMD"));
           } else {
-            if (aDisplayer->isVisible(aObject)) {
-              if (aDisplayer->displayMode(aObject) == XGUI_Displayer::Shading)
-                aMenu->addAction(action("WIREFRAME_CMD"));
-              else
-                aMenu->addAction(action("SHADING_CMD"));
-              aMenu->addSeparator();
-              aMenu->addAction(action("HIDE_CMD"));
-            } else {
-              aMenu->addAction(action("SHOW_CMD"));
-            }
-            aMenu->addAction(action("SHOW_ONLY_CMD"));
+            aMenu->addAction(action("SHOW_CMD"));
           }
-        } else {  // If feature is 0 the it means that selected root object (document)
-          if (aMgr->activeDocument() != aMgr->moduleDocument())
-            aMenu->addAction(action("ACTIVATE_PART_CMD"));
-        }
-      } else {
-        if (hasResult) {
-          aMenu->addAction(action("SHOW_CMD"));
-          aMenu->addAction(action("HIDE_CMD"));
           aMenu->addAction(action("SHOW_ONLY_CMD"));
-          aMenu->addSeparator();
-          aMenu->addAction(action("SHADING_CMD"));
-          aMenu->addAction(action("WIREFRAME_CMD"));
         }
+      } else {  // If feature is 0 the it means that selected root object (document)
+        if (aMgr->activeDocument() != aMgr->moduleDocument())
+          aMenu->addAction(action("ACTIVATE_PART_CMD"));
+      }
+    } else {
+      if (hasResult) {
+        aMenu->addAction(action("SHOW_CMD"));
+        aMenu->addAction(action("HIDE_CMD"));
+        aMenu->addAction(action("SHOW_ONLY_CMD"));
+        aMenu->addSeparator();
+        aMenu->addAction(action("SHADING_CMD"));
+        aMenu->addAction(action("WIREFRAME_CMD"));
       }
-      if (hasFeature)
-        aMenu->addAction(action("DELETE_CMD"));
     }
+    if (hasFeature)
+      aMenu->addAction(action("DELETE_CMD"));
   }
   aMenu->addSeparator();
   aMenu->addActions(myWorkshop->objectBrowser()->actions());
index 14a8735b1dcfaec4f4e236cf0c5f189ba3409ae8..42d96c8bebf2ccad848c317cdf8e2c8c679149ef 100644 (file)
@@ -108,12 +108,14 @@ void XGUI_DocumentDataModel::processEvent(const boost::shared_ptr<Events_Message
       if (aDoc == aRootDoc) {  // If root objects
         if (aGroup == ModelAPI_ResultPart::group()) {  // Update only Parts group
           int aStart = myPartModels.size() - 1;
-          removeSubModel(aStart);
-          removeRow(aStart, partFolderNode());
-          if (myActivePart && (!isPartSubModel(myActivePart))) {
-            myActivePart = 0;
-            myActivePartIndex = QModelIndex();
-            myModel->setItemsColor(ACTIVE_COLOR);
+          if (aStart >= 0) {// MPV: this could be reproduced on close
+            removeSubModel(aStart);
+            removeRow(aStart, partFolderNode());
+            if (myActivePart && (!isPartSubModel(myActivePart))) {
+              myActivePart = 0;
+              myActivePartIndex = QModelIndex();
+              myModel->setItemsColor(ACTIVE_COLOR);
+            }
           }
         } else {  // Update top groups (other except parts
           QModelIndex aIndex = myModel->findGroup(aGroup);
index 42d22cce9ed799b35889a657a8a086d5c7055677..75b57303445d5a89c67ab9e1d1ba8c8066ac7dc4 100644 (file)
@@ -448,7 +448,9 @@ DocumentPtr XGUI_PartDataModel::partDocument() const
   DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
   ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), myId);
   ResultPartPtr aPart = boost::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
-  return aPart->partDoc();
+  if (aPart)
+    return aPart->partDoc();
+  return DocumentPtr(); // null if not found
 }
 
 ObjectPtr XGUI_PartDataModel::object(const QModelIndex& theIndex) const
index 0c36dada2d5113a860c4ca6e388abb3b0bd2a4f5..d055e67c37f13bdd2758cc7c4e878ed6feaf0deb 100644 (file)
@@ -36,13 +36,18 @@ class XGUI_EXPORT XGUI_SalomeConnector
   //! \param theIcon - icon
   //! \param isCheckable - is checkable or not
   //! \param theKeys - hot keys
+  //! \param theMenuSourceText - a source text of the desktop menu
+  //! \param theMenuPosition - a position of the command in the desktop menu
   //! returns created action
-  virtual QAction* addEditCommand(const QString& theId, const QString& theTitle,
-                                  const QString& theTip, const QIcon& theIcon,
-                                  const QKeySequence& theKeys, bool isCheckable) = 0;
+  virtual QAction* addDesktopCommand(const QString& theId, const QString& theTitle,
+                                     const QString& theTip, const QIcon& theIcon,
+                                     const QKeySequence& theKeys, bool isCheckable,
+                                     const char* theMenuSourceText,
+                                     const int theMenuPosition = 10) = 0;
 
   //! Insert separator into Edit menu of SALOME desktop
-  virtual void addEditMenuSeparator() = 0;
+  virtual void addDesktopMenuSeparator(const char* theMenuSourceText,
+                                       const int theMenuPosition = 10) = 0;
 
   //! Returns desktop window of SALOME
   virtual QMainWindow* desktop() const = 0;
index 0dd985f977c8c8c5c7a4aac0b3007b1f0c51079b..265fb9029145f05e8a63370042d921408ef64bff 100644 (file)
@@ -125,10 +125,12 @@ void XGUI_Selection::selectedShapes(NCollection_List<TopoDS_Shape>& theList,
     if (!aShape.IsNull()) {
       theList.Append(aShape);
       Handle(SelectMgr_EntityOwner) aEO = aContext->SelectedOwner();
-      Handle(AIS_InteractiveObject) anObj = 
-        Handle(AIS_InteractiveObject)::DownCast(aEO->Selectable());
-      ObjectPtr anObject = myWorkshop->displayer()->getObject(anObj);
-      theOwners.push_back(anObject);
+      if (!aEO.IsNull()) {
+        Handle(AIS_InteractiveObject) anObj = 
+          Handle(AIS_InteractiveObject)::DownCast(aEO->Selectable());
+        ObjectPtr anObject = myWorkshop->displayer()->getObject(anObj);
+        theOwners.push_back(anObject);
+      }
     }
   }
 }
index 3a81496155da40783e179953e8384d92d2cc0349..47100f7c463e0e33c472f6c372d8978e939ce7f1 100644 (file)
@@ -458,7 +458,7 @@ void XGUI_Viewer::addView(QMdiSubWindow* theView)
           SIGNAL(keyPress(XGUI_ViewWindow*, QKeyEvent*)));
 
   connect(aWindow, SIGNAL(keyReleased(XGUI_ViewWindow*, QKeyEvent*)), this,
-          SIGNAL(keyRelease(XGUI_ViewWindow*, QKeyEvent*)));
+          SLOT(onKeyRelease(XGUI_ViewWindow*, QKeyEvent*)));
 
   //connect(aWindow, SIGNAL(contextMenuRequested( QContextMenuEvent* )),
   //        this,    SLOT  (onContextMenuRequested( QContextMenuEvent* )));
@@ -529,6 +529,8 @@ void XGUI_Viewer::onMouseMove(XGUI_ViewWindow* theWindow, QMouseEvent* theEvent)
   Handle(V3d_View) aView3d = theWindow->viewPort()->getView();
   if (!aView3d.IsNull()) {
     myAISContext->MoveTo(theEvent->x(), theEvent->y(), aView3d);
+    if (myAISContext->HasDetected())
+      theWindow->viewPort()->setFocus(Qt::MouseFocusReason);
   }
 }
 
@@ -607,6 +609,20 @@ void XGUI_Viewer::updateViewsDrawMode() const
   }
 }
 
+//******************************************************
+void XGUI_Viewer::onKeyRelease(XGUI_ViewWindow* theView, QKeyEvent* theKey)
+{
+  Handle(V3d_View) aView = theView->viewPort()->getView();
+  bool noModifiers = (theKey->modifiers() == Qt::NoModifier);
+  if ((theKey->key() == Qt::Key_N) && noModifiers) {
+    myAISContext->HilightNextDetected(aView);
+  } else if ((theKey->key() == Qt::Key_P) && noModifiers) {
+    myAISContext->HilightPreviousDetected(aView);
+  } else {
+    emit keyRelease(theView, theKey);
+  }
+}
+
 //******************************************************
 //void XGUI_Viewer::onContextMenuRequested(QContextMenuEvent* theEvent)
 //{
index 2ae7cdd04feb2b5dfa73364bd174a35a07d7afaf..2cc4c02c05211d88624b22bff81c18fc954737a6 100644 (file)
@@ -182,6 +182,8 @@ signals:
   void onMousePressed(XGUI_ViewWindow* theWindow, QMouseEvent* theEvent);
   //void onContextMenuRequested(QContextMenuEvent* theEvent);
 
+  void onKeyRelease(XGUI_ViewWindow* theView, QKeyEvent* theKey);
+
  private:
   void addView(QMdiSubWindow* theView);
 
@@ -193,7 +195,9 @@ signals:
  private:
   XGUI_MainWindow* myMainWindow;
 
-  Handle(V3d_Viewer) myV3dViewer;Handle(AIS_Trihedron) myTrihedron;Handle(AIS_InteractiveContext) myAISContext;
+  Handle(V3d_Viewer) myV3dViewer;
+  Handle(AIS_Trihedron) myTrihedron;
+  Handle(AIS_InteractiveContext) myAISContext;
 
   XGUI::InteractionStyle myInteractionStyle;
 
index fee0419ddd6dfb31fbd19fce786d7fceee121325..782023d870aa6cb4bdfaf996f1c2436c2b8624fc 100644 (file)
@@ -187,3 +187,30 @@ bool XGUI_ViewerProxy::isMultiSelectionEnabled() const
     return myWorkshop->mainWindow()->viewer()->isMultiSelectionEnabled();
   }
 }
+
+//***************************************
+void XGUI_ViewerProxy::addSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
+{
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (!aContext.IsNull()) {
+    aContext->AddFilter(theFilter);
+  }
+}
+
+//***************************************
+void XGUI_ViewerProxy::removeSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
+{
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (!aContext.IsNull()) {
+    aContext->RemoveFilter(theFilter);
+  }
+}
+
+//***************************************
+void XGUI_ViewerProxy::clearSelectionFilters()
+{
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (!aContext.IsNull()) {
+    aContext->RemoveFilters();
+  }
+}
index 9c39bdf20c9ef3549f8404b1fa614986e448bfcf..caca6ec42133103af9f64c78e0ab2291764e1cbe 100644 (file)
@@ -52,6 +52,15 @@ Q_OBJECT
   /// Connects to a viewer according to current environment
   void connectToViewer();
 
+  /// Add selection filter to the viewer
+  virtual void addSelectionFilter(const Handle(SelectMgr_Filter)& theFilter);
+
+  /// Remove selection filter from the viewer
+  virtual void removeSelectionFilter(const Handle(SelectMgr_Filter)& theFilter);
+
+  /// Remove all selection filters from the viewer
+  virtual void clearSelectionFilters();
+
  private slots:
   void onMousePress(XGUI_ViewWindow*, QMouseEvent*);
   void onMouseRelease(XGUI_ViewWindow*, QMouseEvent*);
index cf38bd9e6975d4ebf6d9fc40e00eb9444c011a60..12e6bb7b37eea54deb7d68da9449a2a487e27c58 100644 (file)
@@ -119,9 +119,11 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
   connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)),
           SLOT(onOperationStopped(ModuleBase_Operation*)));
   connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit()));
-  connect(myOperationMgr, SIGNAL(operationStarted()), myActionsMgr, SLOT(update()));
-  connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)), myActionsMgr,
-          SLOT(update()));
+  // TODO(sbh): It seems that application works properly without update on operationStarted
+  connect(myOperationMgr, SIGNAL(operationStarted(ModuleBase_Operation*)),
+          myActionsMgr,   SLOT(update()));
+  connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)),
+          myActionsMgr,   SLOT(update()));
   connect(this, SIGNAL(errorOccurred(const QString&)), myErrorDlg, SLOT(addError(const QString&)));
 }
 
@@ -167,21 +169,33 @@ void XGUI_Workshop::initMenu()
 
   if (isSalomeMode()) {
     // Create only Undo, Redo commands
-    QAction* aAction = salomeConnector()->addEditCommand("UNDO_CMD", tr("Undo"),
+    QAction* aAction = salomeConnector()->addDesktopCommand("UNDO_CMD", tr("Undo"),
                                                          tr("Undo last command"),
                                                          QIcon(":pictures/undo.png"),
-                                                         QKeySequence::Undo, false);
+                                                         QKeySequence::Undo, false, "MEN_DESK_EDIT");
     connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onUndo()));
-    aAction = salomeConnector()->addEditCommand("REDO_CMD", tr("Redo"), tr("Redo last command"),
+    aAction = salomeConnector()->addDesktopCommand("REDO_CMD", tr("Redo"), tr("Redo last command"),
                                                 QIcon(":pictures/redo.png"), QKeySequence::Redo,
-                                                false);
+                                                false, "MEN_DESK_EDIT");
     connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRedo()));
-    salomeConnector()->addEditMenuSeparator();
-    aAction = salomeConnector()->addEditCommand("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"),
+    salomeConnector()->addDesktopMenuSeparator("MEN_DESK_EDIT");
+    aAction = salomeConnector()->addDesktopCommand("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"),
                                                 QIcon(":pictures/rebuild.png"), QKeySequence(),
-                                                false);
+                                                false, "MEN_DESK_EDIT");
     connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRebuild()));
-    salomeConnector()->addEditMenuSeparator();
+    salomeConnector()->addDesktopMenuSeparator("MEN_DESK_EDIT");
+
+    aAction = salomeConnector()->addDesktopCommand("SAVEAS_CMD", tr("Export NewGeom..."), tr("Export the current document into a NewGeom file"),
+                                                QIcon(), QKeySequence(),
+                                                false, "MEN_DESK_FILE");
+    connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onSaveAs()));
+
+    aAction = salomeConnector()->addDesktopCommand("OPEN_CMD", tr("Import NewGeom..."), tr("Import a NewGeom file"),
+                                                QIcon(), QKeySequence(),
+                                                false, "MEN_DESK_FILE");
+    connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onOpen()));
+    salomeConnector()->addDesktopMenuSeparator("MEN_DESK_FILE");
+
     return;
   }
   // File commands group
@@ -712,7 +726,7 @@ void XGUI_Workshop::onOpen()
     } else if (anAnswer == QMessageBox::Cancel) {
       return;
     }
-    aSession->moduleDocument()->close();
+    aSession->closeAll();
     myCurrentDir = "";
   }
 
@@ -745,7 +759,8 @@ bool XGUI_Workshop::onSave()
   std::list<std::string> aFiles;
   saveDocument(myCurrentDir, aFiles);
   updateCommandStatus();
-  myMainWindow->setModifiedState(false);
+  if (!isSalomeMode())
+    myMainWindow->setModifiedState(false);
   return true;
 }
 
@@ -929,8 +944,7 @@ void XGUI_Workshop::updateCommandStatus()
   }
   SessionPtr aMgr = ModelAPI_Session::get();
   if (aMgr->hasModuleDocument()) {
-    QAction* aUndoCmd;
-    QAction* aRedoCmd;
+    QAction *aUndoCmd, *aRedoCmd;
     foreach(QAction* aCmd, aCommands) {
       QString aId = aCmd->data().toString();
       if (aId == "UNDO_CMD")
@@ -941,8 +955,8 @@ void XGUI_Workshop::updateCommandStatus()
         // Enable all commands
         aCmd->setEnabled(true);
     }
-    aUndoCmd->setEnabled(aMgr->canUndo());
-    aRedoCmd->setEnabled(aMgr->canRedo());
+    aUndoCmd->setEnabled(aMgr->canUndo() && !aMgr->isOperation());
+    aRedoCmd->setEnabled(aMgr->canRedo() && !aMgr->isOperation());
   } else {
     foreach(QAction* aCmd, aCommands) {
       QString aId = aCmd->data().toString();
@@ -1313,6 +1327,6 @@ void XGUI_Workshop::closeDocument()
   objectBrowser()->clearContent();
 
   SessionPtr aMgr = ModelAPI_Session::get();
-  aMgr->moduleDocument()->close();
+  aMgr->closeAll();
   objectBrowser()->clearContent();
 }