Salome HOME
Merge remote-tracking branch 'remotes/origin/master' into SolveSpace
authorazv <azv@opencascade.com>
Fri, 16 May 2014 05:24:03 +0000 (09:24 +0400)
committerazv <azv@opencascade.com>
Fri, 16 May 2014 05:24:03 +0000 (09:24 +0400)
41 files changed:
src/Model/Model_Application.cpp
src/Model/Model_Application.h
src/Model/Model_AttributeDocRef.cpp
src/Model/Model_Data.cpp
src/Model/Model_Data.h
src/Model/Model_Document.cpp
src/Model/Model_Document.h
src/ModelAPI/ModelAPI_Data.h
src/ModelAPI/ModelAPI_Feature.h
src/PartSet/PartSet_Listener.cpp
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_Module.h
src/PartSet/PartSet_OperationSketch.cpp
src/PartSet/PartSet_OperationSketch.h
src/PartSet/PartSet_OperationSketchBase.cpp
src/PartSet/PartSet_OperationSketchBase.h
src/PartSetPlugin/PartSetPlugin_Part.h
src/SketchPlugin/SketchPlugin_Feature.cpp
src/SketchPlugin/SketchPlugin_Feature.h
src/SketchPlugin/SketchPlugin_Line.cpp
src/XGUI/CMakeLists.txt
src/XGUI/XGUI_ContextMenuMgr.cpp [new file with mode: 0644]
src/XGUI/XGUI_ContextMenuMgr.h [new file with mode: 0644]
src/XGUI/XGUI_DataTreeModel.h
src/XGUI/XGUI_Displayer.cpp
src/XGUI/XGUI_Displayer.h
src/XGUI/XGUI_DocumentDataModel.cpp
src/XGUI/XGUI_DocumentDataModel.h
src/XGUI/XGUI_ObjectsBrowser.cpp
src/XGUI/XGUI_ObjectsBrowser.h
src/XGUI/XGUI_OperationMgr.cpp
src/XGUI/XGUI_OperationMgr.h
src/XGUI/XGUI_PartDataModel.cpp
src/XGUI/XGUI_PartDataModel.h
src/XGUI/XGUI_ViewWindow.cpp
src/XGUI/XGUI_Viewer.cpp
src/XGUI/XGUI_Viewer.h
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_Workshop.h
src/XGUI/XGUI_pictures.qrc
src/XGUI/pictures/edit.png [new file with mode: 0644]

index 166b4e1a173f3812013eabdce23d4aec14c8f8f2..df32ef977d7c599acfbb7dbadc23c99492533fb7 100644 (file)
@@ -26,6 +26,12 @@ const boost::shared_ptr<Model_Document>& Model_Application::getDocument(string t
 
   boost::shared_ptr<Model_Document> aNew(new Model_Document(theDocID));
   myDocs[theDocID] = aNew;
+  // load it if it must be loaded by demand
+  if (myLoadedByDemand.find(theDocID) != myLoadedByDemand.end() && !myPath.empty()) {
+    aNew->load(myPath.c_str());
+    myLoadedByDemand.erase(theDocID); // done, don't do it anymore
+  }
+
   return myDocs[theDocID];
 }
 
@@ -40,6 +46,18 @@ bool Model_Application::hasDocument(std::string theDocID)
   return myDocs.find(theDocID) != myDocs.end();
 }
 
+//=======================================================================
+void Model_Application::setLoadPath(std::string thePath)
+{
+  myPath = thePath;
+}
+
+//=======================================================================
+void Model_Application::setLoadByDemand(std::string theID)
+{
+  myLoadedByDemand.insert(theID);
+}
+
 //=======================================================================
 Model_Application::Model_Application()
 {
index ddd3155bd0ed9e599b34ebca545df95da6eca10c..9281f9ce6e4773565072d1c697508f315e09e63c 100644 (file)
@@ -36,6 +36,11 @@ public:
   //! Deletes the document from the application
   MODEL_EXPORT void deleteDocument(std::string theDocID);
 
+  //! Set path for the loaded by demand documents
+  void setLoadPath(std::string thePath);
+  //! Defines that specified document must be loaded by demand
+  void setLoadByDemand(std::string theID);
+
 public:
   // Redefined OCAF methods
   //! Return name of resource (i.e. "Standard")
@@ -51,6 +56,10 @@ public:
 private:
   /// Map from string identifiers to created documents of an application
   std::map<std::string, boost::shared_ptr<Model_Document> > myDocs;
+  /// Path for the loaded by demand documents
+  std::string myPath;
+  /// Path for the loaded by demand documents
+  std::set<std::string> myLoadedByDemand;
 };
 
 #endif
index 93c8af71346ce82569f5cea6cf867f8b0d8ac55b..dfb307f4dbfe0981cc8915fc838cea6a798540a4 100644 (file)
@@ -36,5 +36,11 @@ Model_AttributeDocRef::Model_AttributeDocRef(TDF_Label& theLabel)
   if (!theLabel.FindAttribute(TDataStd_Comment::GetID(), myComment)) {
     // create attribute: not initialized by value yet, just empty string
     myComment = TDataStd_Comment::Set(theLabel, "");
+  } else { // document was already referenced: try to set it as loaded by demand
+    Handle(Model_Application) anApp = Model_Application::getApplication();
+    string anID(TCollection_AsciiString(myComment->Get()).ToCString());
+    if (!anApp->hasDocument(anID)) {
+      anApp->setLoadByDemand(anID);
+    }
   }
 }
index 487d0ca913e052650f6490c6554e6774650de3a1..e6c5c02f2e7311aefacbe361f9733014634c9cc4 100644 (file)
@@ -159,3 +159,16 @@ const string& Model_Data::id(const boost::shared_ptr<ModelAPI_Attribute> theAttr
   static string anEmpty;
   return anEmpty;
 }
+
+bool Model_Data::isEqual(const boost::shared_ptr<ModelAPI_Data> theData)
+{
+  boost::shared_ptr<Model_Data> aData = boost::dynamic_pointer_cast<Model_Data>(theData);
+  if (aData)
+    return myLab.IsEqual(aData->myLab) == Standard_True;
+  return false;
+}
+
+bool Model_Data::isValid()
+{
+  return !myLab.IsNull() && myLab.HasAttribute();
+}
index 1484f68c8db0ac5b7b05c1113ee466b805828002..03ff0c54eddc44dd8fec9cf433b9cfa307edb9b5 100644 (file)
@@ -63,6 +63,10 @@ public:
   /// Identifier by the id (not fast, iteration by map)
   /// \param theAttr attribute already created in this data
   MODEL_EXPORT virtual const std::string& id(const boost::shared_ptr<ModelAPI_Attribute> theAttr);
+  /// Returns true if data belongs to same features
+  MODEL_EXPORT virtual bool isEqual(const boost::shared_ptr<ModelAPI_Data> theData);
+  /// Returns true if it is correctly connected t othe data model
+  MODEL_EXPORT virtual bool isValid();
 
   /// Initializes object by the attributes: must be called just after the object is created
   /// for each attribute of the object
index 8c305effa4f45ff18eee37728e9f1cf8a144e732..73e6adbc75d6828058dbc12b6b5f996943cf3439 100644 (file)
@@ -9,6 +9,7 @@
 #include <Model_PluginManager.h>
 #include <Model_Events.h>
 #include <Events_Loop.h>
+#include <Events_Error.h>
 
 #include <TDataStd_Integer.hxx>
 #include <TDataStd_Comment.hxx>
 
 #include <climits>
 
+#ifdef WIN32
+# define _separator_ '\\'
+#else
+# define _separator_ '/'
+#endif
+
 static const int UNDO_LIMIT = 10; // number of possible undo operations
 
 static const int TAG_GENERAL = 1; // general properties tag
@@ -26,83 +33,125 @@ static const int TAG_HISTORY = 3; // tag of the history sub-tree (python dump)
 
 using namespace std;
 
+/// Returns the file name of this document by the nameof directory and identifuer of a document
+static TCollection_ExtendedString DocFileName(const char* theFileName, const string& theID)
+{
+  TCollection_ExtendedString aPath ((const Standard_CString)theFileName);
+  aPath += _separator_;
+  aPath += theID.c_str();
+  aPath += ".cbf"; // standard binary file extension
+  return aPath;
+}
+
 bool Model_Document::load(const char* theFileName)
 {
-  bool myIsError = Standard_False;
-  /*
-   TCollection_ExtendedString aPath ((const Standard_CString)theFileName);
-   PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus) -1;
-   try
-   {
-   Handle(TDocStd_Document) aDoc = this;
-   aStatus = Model_Application::GetApplication()->Open(aPath, aDoc);
-   }
-   catch (Standard_Failure)
-   {}
-   myIsError = aStatus != PCDM_RS_OK;
-   if (myIsError)
-   {
-   switch (aStatus)
-   {
-   case PCDM_RS_UnknownDocument: cout<<"OCAFApp_Appl_RUnknownDocument"<<endl; break;
-   case PCDM_RS_AlreadyRetrieved: cout<<"OCAFApp_Appl_RAlreadyRetrieved"<<endl; break;
-   case PCDM_RS_AlreadyRetrievedAndModified: cout<<"OCAFApp_Appl_RAlreadyRetrievedAndModified"<<endl; break;
-   case PCDM_RS_NoDriver: cout<<"OCAFApp_Appl_RNoDriver"<<endl; break;
-   case PCDM_RS_UnknownFileDriver: cout<<"OCAFApp_Appl_RNoDriver"<<endl; break;
-   case PCDM_RS_OpenError: cout<<"OCAFApp_Appl_ROpenError"<<endl; break;
-   case PCDM_RS_NoVersion: cout<<"OCAFApp_Appl_RNoVersion"<<endl; break;
-   case PCDM_RS_NoModel: cout<<"OCAFApp_Appl_RNoModel"<<endl; break;
-   case PCDM_RS_NoDocument: cout<<"OCAFApp_Appl_RNoDocument"<<endl; break;
-   case PCDM_RS_FormatFailure: cout<<"OCAFApp_Appl_RFormatFailure"<<endl; break;
-   case PCDM_RS_TypeNotFoundInSchema: cout<<"OCAFApp_Appl_RTypeNotFound"<<endl; break;
-   case PCDM_RS_UnrecognizedFileFormat: cout<<"OCAFApp_Appl_RBadFileFormat"<<endl; break;
-   case PCDM_RS_MakeFailure: cout<<"OCAFApp_Appl_RMakeFailure"<<endl; break;
-   case PCDM_RS_PermissionDenied: cout<<"OCAFApp_Appl_RPermissionDenied"<<endl; break;
-   case PCDM_RS_DriverFailure: cout<<"OCAFApp_Appl_RDriverFailure"<<endl; break;
-   default: cout<<"OCAFApp_Appl_RUnknownFail"<<endl; break;
-   }
-   }
-   SetUndoLimit(UNDO_LIMIT);
-   */
-  return !myIsError;
+  Handle(Model_Application) anApp = Model_Application::getApplication();
+  if (this == Model_PluginManager::get()->rootDocument().get()) {
+    anApp->setLoadPath(theFileName);
+  }
+  TCollection_ExtendedString aPath (DocFileName(theFileName, myID));
+  PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus) -1;
+  try
+  {
+    aStatus = anApp->Open(aPath, myDoc);
+  }
+  catch (Standard_Failure)
+  {
+    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+    Events_Error::send(string("Exception in opening of document: ") + aFail->GetMessageString());
+    return false;
+  }
+  bool isError = aStatus != PCDM_RS_OK;
+  if (isError)
+  {
+    switch (aStatus)
+    {
+    case PCDM_RS_UnknownDocument: 
+      Events_Error::send(string("Can not open document: PCDM_RS_UnknownDocument")); break;
+    case PCDM_RS_AlreadyRetrieved: 
+      Events_Error::send(string("Can not open document: PCDM_RS_AlreadyRetrieved")); break;
+    case PCDM_RS_AlreadyRetrievedAndModified:
+      Events_Error::send(string("Can not open document: PCDM_RS_AlreadyRetrievedAndModified")); break;
+    case PCDM_RS_NoDriver:
+      Events_Error::send(string("Can not open document: PCDM_RS_NoDriver")); break;
+    case PCDM_RS_UnknownFileDriver:
+      Events_Error::send(string("Can not open document: PCDM_RS_UnknownFileDriver")); break;
+    case PCDM_RS_OpenError:
+      Events_Error::send(string("Can not open document: PCDM_RS_OpenError")); break;
+    case PCDM_RS_NoVersion:
+      Events_Error::send(string("Can not open document: PCDM_RS_NoVersion")); break;
+    case PCDM_RS_NoModel:
+      Events_Error::send(string("Can not open document: PCDM_RS_NoModel")); break;
+    case PCDM_RS_NoDocument:
+      Events_Error::send(string("Can not open document: PCDM_RS_NoDocument")); break;
+    case PCDM_RS_FormatFailure:
+      Events_Error::send(string("Can not open document: PCDM_RS_FormatFailure")); break;
+    case PCDM_RS_TypeNotFoundInSchema:
+      Events_Error::send(string("Can not open document: PCDM_RS_TypeNotFoundInSchema")); break;
+    case PCDM_RS_UnrecognizedFileFormat:
+      Events_Error::send(string("Can not open document: PCDM_RS_UnrecognizedFileFormat")); break;
+    case PCDM_RS_MakeFailure:
+      Events_Error::send(string("Can not open document: PCDM_RS_MakeFailure")); break;
+    case PCDM_RS_PermissionDenied:
+      Events_Error::send(string("Can not open document: PCDM_RS_PermissionDenied")); break;
+    case PCDM_RS_DriverFailure:
+      Events_Error::send(string("Can not open document: PCDM_RS_DriverFailure")); break;
+    default:
+      Events_Error::send(string("Can not open document: unknown error")); break;
+    }
+  }
+  if (!isError) {
+    myDoc->SetUndoLimit(UNDO_LIMIT);
+    synchronizeFeatures();
+  }
+  return !isError;
 }
 
 bool Model_Document::save(const char* theFileName)
 {
-  bool myIsError = true;
-  /*
-   TCollection_ExtendedString aPath ((const Standard_CString)theFileName);
-   PCDM_StoreStatus aStatus;
-   try {
-   Handle(TDocStd_Document) aDoc = this;
-   aStatus = Model_Application::GetApplication()->SaveAs (aDoc, aPath);
-   }
-   catch (Standard_Failure) {
-   Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-   cout<<"OCAFApp_Engine:save Error: "<<aFail->GetMessageString()<<endl;
-   return false;
-   }
-   myIsError = aStatus != PCDM_SS_OK;
-   if (myIsError)
-   {
-   switch (aStatus)
-   {
-   case PCDM_SS_DriverFailure:
-   cout<<"OCAFApp_Appl_SDriverFailure"<<endl;
-   break;
-   case PCDM_SS_WriteFailure:
-   cout<<"OCAFApp_Appl_SWriteFailure"<<endl;
-   break;
-   case PCDM_SS_Failure:
-   default:
-   cout<<"OCAFApp_Appl_SUnknownFailure"<<endl;
-   break;
-   }
-   }
-   myTransactionsAfterSave = 0;
-   Standard::Purge(); // Release free memory
-   */
-  return !myIsError;
+  // create a directory in the root document if it is not yet exist
+  if (this == Model_PluginManager::get()->rootDocument().get()) {
+#ifdef WIN32
+    CreateDirectory(theFileName, NULL);
+#else
+    mkdir(theFileName, 0x1ff); 
+#endif
+  }
+  // filename in the dir is id of document inside of the given directory
+  TCollection_ExtendedString aPath(DocFileName(theFileName, myID));
+  PCDM_StoreStatus aStatus;
+  try {
+    aStatus = Model_Application::getApplication()->SaveAs(myDoc, aPath);
+  }
+  catch (Standard_Failure) {
+    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+    Events_Error::send(string("Exception in saving of document: ") + aFail->GetMessageString());
+    return false;
+  }
+  bool isDone = aStatus == PCDM_SS_OK || aStatus == PCDM_SS_No_Obj;
+  if (!isDone)
+  {
+    switch (aStatus)
+    {
+    case PCDM_SS_DriverFailure:
+      Events_Error::send(string("Can not save document: PCDM_SS_DriverFailure"));
+      break;
+    case PCDM_SS_WriteFailure:
+      Events_Error::send(string("Can not save document: PCDM_SS_WriteFailure"));
+      break;
+    case PCDM_SS_Failure:
+    default:
+      Events_Error::send(string("Can not save document: PCDM_SS_Failure"));
+      break;
+    }
+  }
+  myTransactionsAfterSave = 0;
+  if (isDone) { // save also sub-documents if any
+    set<string>::iterator aSubIter = mySubs.begin();
+    for(; aSubIter != mySubs.end() && isDone; aSubIter++)
+      isDone = subDocument(*aSubIter)->save(theFileName);
+  }
+  return isDone;
 }
 
 void Model_Document::close()
@@ -119,6 +168,10 @@ void Model_Document::close()
 
 void Model_Document::startOperation()
 {
+  // check is it nested or not
+  if (myDoc->HasOpenCommand()) {
+    myNestedStart = myTransactionsAfterSave;
+  }
   // new command for this
   myDoc->NewCommand();
   // new command for all subs
@@ -129,6 +182,8 @@ void Model_Document::startOperation()
 
 void Model_Document::finishOperation()
 {
+  if (myNestedStart > myTransactionsAfterSave) // this nested transaction is owervritten
+    myNestedStart = 0;
   // returns false if delta is empty and no transaction was made
   myIsEmptyTr[myTransactionsAfterSave] = !myDoc->CommitCommand();
   myTransactionsAfterSave++;
@@ -161,7 +216,7 @@ bool Model_Document::isModified()
 
 bool Model_Document::canUndo()
 {
-  if (myDoc->GetAvailableUndos() > 0)
+  if (myDoc->GetAvailableUndos() > 0 && myNestedStart != myTransactionsAfterSave)
     return true;
   // check other subs contains operation that can be undoed
   set<string>::iterator aSubIter = mySubs.begin();
@@ -229,8 +284,8 @@ void Model_Document::addFeature(const boost::shared_ptr<ModelAPI_Feature> theFea
   aData->setLabel(anObjLab);
   boost::shared_ptr<ModelAPI_Document> aThis = 
     Model_Application::getApplication()->getDocument(myID);
-  theFeature->setData(aData);
   theFeature->setDoc(aThis);
+  theFeature->setData(aData);
   setUniqueName(theFeature);
   theFeature->initAttributes();
   // keep the feature ID to restore document later correctly
@@ -344,6 +399,10 @@ Model_Document::Model_Document(const std::string theID)
 {
   myDoc->SetUndoLimit(UNDO_LIMIT);
   myTransactionsAfterSave = 0;
+  myNestedStart = 0;
+  myDoc->SetNestedTransactionMode();
+  // to have something in the document and avoid empty doc open/save problem
+  TDataStd_Integer::Set(myDoc->Main().Father(), 0);
 }
 
 TDF_Label Model_Document::groupLabel(const string theGroup)
@@ -451,6 +510,13 @@ void Model_Document::synchronizeFeatures()
           TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(
           aFLabIter.Value())->Get()).ToCString());
 
+        if (aFIter == aFeatures.end()) { // must be before "setData" to redo the sketch line correctly
+          aFeatures.push_back(aFeature);
+          aFIter = aFeatures.end();
+        } else {
+          aFIter++;
+          aFeatures.insert(aFIter, aFeature);
+        }
         boost::shared_ptr<Model_Data> aData(new Model_Data);
         TDF_Label aLab = aFLabIter.Value()->Label();
         aData->setLabel(aLab);
@@ -458,18 +524,12 @@ void Model_Document::synchronizeFeatures()
         aFeature->setDoc(aThis);
         aFeature->setData(aData);
         aFeature->initAttributes();
+
         // event: model is updated
         static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_CREATED);
         Model_FeatureUpdatedMessage aMsg(aFeature, anEvent);
         Events_Loop::loop()->send(aMsg);
 
-        if (aFIter == aFeatures.end()) {
-          aFeatures.push_back(aFeature);
-          aFIter = aFeatures.end();
-        } else {
-          aFIter++;
-          aFeatures.insert(aFIter, aFeature);
-        }
         // feature for this label is added, so go to the next label
         aFLabIter.Next();
       } else { // nothing is changed, both iterators are incremented
index 0bf22b98e5b450e9dcbf1ef7771a64d82a267ba9..6d5d04b6babd0c0dacc596fcae00a1e9ddda8774 100644 (file)
@@ -112,6 +112,8 @@ private:
   Handle_TDocStd_Document myDoc; ///< OCAF document
   /// number of transactions after the last "save" call, used for "IsModified" method
   int myTransactionsAfterSave;
+  /// number of myTransactionsAfterSave for the nested transaction start
+  int myNestedStart;
   /// root labels of the features groups identified by names
   std::map<std::string, TDF_Label> myGroups;
   std::vector<std::string> myGroupsNames; ///< names of added groups to the document
index 3b46bc4a068638a7ab53410e8b5d990572acb98c..187654cd88c4aab6afdc2e1866bf37aa91156621 100644 (file)
@@ -50,6 +50,10 @@ public:
   /// Identifier by the id (not fast, iteration by map)
   /// \param theAttr attribute already created in this data
   virtual const std::string& id(const boost::shared_ptr<ModelAPI_Attribute> theAttr) = 0;
+  /// Returns true if data belongs to same features
+  virtual bool isEqual(const boost::shared_ptr<ModelAPI_Data> theData) = 0;
+  /// Returns true if it is correctly connected t othe data model
+  virtual bool isValid() = 0;
 
   /// Initializes object by the attributes: must be called just after the object is created
   /// for each attribute of the object
index b55e7984621a922f9c7ae197a88bb67c71019648..1dd7b12dbfbf4803602e312167bca7197cad6332 100644 (file)
@@ -62,7 +62,8 @@ protected:
   {}
 
   /// Sets the data manager of an object (document does)
-  MODELAPI_EXPORT void setData(boost::shared_ptr<ModelAPI_Data> theData) {myData = theData;}
+  MODELAPI_EXPORT virtual void setData(boost::shared_ptr<ModelAPI_Data> theData) 
+  {myData = theData;}
   /// Sets the data manager of an object (document does)
   MODELAPI_EXPORT void setDoc(boost::shared_ptr<ModelAPI_Document> theDoc) {myDoc = theDoc;}
 
index 3e1c4886a78f352827be6aadb1a0727f45f02a33..9615dac4cf175d81bc72b4c88c2c6e8c570f0be5 100644 (file)
@@ -21,8 +21,9 @@ PartSet_Listener::PartSet_Listener(PartSet_Module* theModule)
 : myModule(theModule)
 {
   Events_Loop* aLoop = Events_Loop::loop();
-  Events_ID aFeatureUpdatedId = aLoop->eventByName(EVENT_FEATURE_UPDATED);
-  aLoop->registerListener(this, aFeatureUpdatedId);
+  aLoop->registerListener(this, aLoop->eventByName(EVENT_FEATURE_UPDATED));
+  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_CREATED));
+  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_DELETED));
 }
 
 PartSet_Listener::~PartSet_Listener()
@@ -32,11 +33,24 @@ PartSet_Listener::~PartSet_Listener()
 //******************************************************
 void PartSet_Listener::processEvent(const Events_Message* theMessage)
 {
-  if (QString(theMessage->eventID().eventText()) == EVENT_FEATURE_UPDATED)
+  QString aType = QString(theMessage->eventID().eventText());
+  if (aType == EVENT_FEATURE_UPDATED ||
+      aType == EVENT_FEATURE_CREATED)
   {
     const Model_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
     boost::shared_ptr<ModelAPI_Feature> aFeature = aUpdMsg->feature();
-    if (myModule->workshop()->displayer()->IsVisible(aFeature))
+    if (myModule->workshop()->displayer()->IsVisible(aFeature) ||
+        aType == EVENT_FEATURE_CREATED)
       myModule->visualizePreview(aFeature, true);
   }
+  if (aType == EVENT_FEATURE_DELETED)
+  {
+    const Model_FeatureDeletedMessage* aDelMsg = dynamic_cast<const Model_FeatureDeletedMessage*>(theMessage);
+    boost::shared_ptr<ModelAPI_Document> aDoc = aDelMsg->document();
+
+    std::string aGroup = aDelMsg->group();
+    if (aDelMsg->group().compare("Sketch") == 0) { // Update only Sketch group
+      myModule->updateCurrentPreview(aGroup);
+    }
+  }
 }
index d7a92caf5118640d66b07f755918bc2985742a8a..9e47626c8a02a42220e26e1315d41ccebdf1e15f 100644 (file)
@@ -308,3 +308,36 @@ void PartSet_Module::visualizePreview(boost::shared_ptr<ModelAPI_Feature> theFea
     aDisplayer->Erase(anOperation->feature());
   }
 }
+
+void PartSet_Module::updateCurrentPreview(const std::string& theCmdId)
+{
+  ModuleBase_Operation* anOperation = myWorkshop->operationMgr()->currentOperation();
+  if (!anOperation)
+    return;
+
+  PartSet_OperationSketchBase* aPreviewOp = dynamic_cast<PartSet_OperationSketchBase*>(anOperation);
+  if (!aPreviewOp)
+    return;
+
+  boost::shared_ptr<ModelAPI_Feature> aFeature = aPreviewOp->feature();
+  if (!aFeature || aFeature->getKind() != theCmdId)
+    return;
+
+  std::map<boost::shared_ptr<ModelAPI_Feature>, boost::shared_ptr<GeomAPI_Shape> >
+                                                                     aList = aPreviewOp->preview();
+  XGUI_Displayer* aDisplayer = myWorkshop->displayer();
+  std::list<int> aModes = aPreviewOp->getSelectionModes(aPreviewOp->feature());
+
+  std::map<boost::shared_ptr<ModelAPI_Feature>, boost::shared_ptr<GeomAPI_Shape> >::const_iterator
+                                                         anIt = aList.begin(), aLast = aList.end();
+  aDisplayer->EraseAll(false);
+  for (; anIt != aLast; anIt++) {
+    boost::shared_ptr<ModelAPI_Feature> aFeature = (*anIt).first;
+    boost::shared_ptr<GeomAPI_Shape> aPreview = (*anIt).second;
+    aDisplayer->RedisplayInLocalContext(aFeature,
+                                        aPreview ? aPreview->impl<TopoDS_Shape>() : TopoDS_Shape(),
+                                        aModes, false);
+  }
+  aDisplayer->UpdateViewer();
+}
+
index 6138a43dc6ed539da34e0daba492b97e3c84930d..14a418d01435fbb58e037a7af0e375118edf6265 100644 (file)
@@ -44,6 +44,10 @@ public:
   /// \param isDisplay the state whether the presentation should be displayed or erased
   void visualizePreview(boost::shared_ptr<ModelAPI_Feature> theFeature, bool isDisplay);
 
+  /// Updates current operation preview, if it has it.
+  /// \param theCmdId the operation name
+  void updateCurrentPreview(const std::string& theCmdId);
+
 public slots:
   void onFeatureTriggered();
   /// SLOT, that is called after the operation is stopped. Switched off the modfications performed
index e5290aa77eb9bc3cbd86ec285cb4b6afdf623019..bcbbf15719214015b0d593b40ac521c71b0f665e 100644 (file)
@@ -11,6 +11,8 @@
 
 #include <ModelAPI_Data.h>
 #include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefList.h>
+
 #include <GeomAlgoAPI_FaceBuilder.h>
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Dir.h>
@@ -79,6 +81,29 @@ void PartSet_OperationSketch::mouseMoved(QMouseEvent* theEvent, Handle(V3d_View)
     emit launchOperation(PartSet_OperationEditLine::Type(), aFeature);
 }
 
+std::map<boost::shared_ptr<ModelAPI_Feature>, boost::shared_ptr<GeomAPI_Shape> >
+                                                        PartSet_OperationSketch::preview() const
+{
+  std::map<boost::shared_ptr<ModelAPI_Feature>, boost::shared_ptr<GeomAPI_Shape> > aPreviewMap;
+
+  boost::shared_ptr<SketchPlugin_Feature> aFeature;
+
+  boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
+  boost::shared_ptr<ModelAPI_AttributeRefList> aRefList =
+        boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(aData->attribute(SKETCH_ATTR_FEATURES));
+
+  std::list<boost::shared_ptr<ModelAPI_Feature> > aFeatures = aRefList->list();
+  std::list<boost::shared_ptr<ModelAPI_Feature> >::const_iterator anIt = aFeatures.begin(),
+                                                                  aLast = aFeatures.end();
+  for (; anIt != aLast; anIt++) {
+    aFeature = boost::dynamic_pointer_cast<SketchPlugin_Feature>(*anIt);
+    boost::shared_ptr<GeomAPI_Shape> aPreview = aFeature->preview();
+    if (aPreview)
+      aPreviewMap[aFeature] = aPreview;
+  }
+  return aPreviewMap;
+}
+
 void PartSet_OperationSketch::setSketchPlane(const TopoDS_Shape& theShape)
 {
   if (theShape.IsNull())
index 227722dc7c91b9849a8227e11e76d575a40d09d8..3f8215ac953f30f081ebfbdb80720a2ac6e014b2 100644 (file)
@@ -47,6 +47,10 @@ public:
   virtual void mouseMoved(QMouseEvent* theEvent, Handle_V3d_View theView,
                           const std::list<XGUI_ViewerPrs>& theSelected);
 
+  /// Returns the map of the operation previews including the nested feature previews
+  /// \return the map of feature to the feature preview
+  virtual std::map<boost::shared_ptr<ModelAPI_Feature>, boost::shared_ptr<GeomAPI_Shape> >
+                                                                           preview() const;
 signals:
   /// signal about the sketch plane is selected
   /// \param theX the value in the X direction of the plane
index 4113c3cba83fbab23eed59174fbd7e08d98cb4a3..daa0211b1d8b0656ccaf4f0162af8357a5057598 100644 (file)
@@ -32,6 +32,12 @@ boost::shared_ptr<GeomAPI_Shape> PartSet_OperationSketchBase::preview(
   return aFeature->preview();
 }
 
+std::map<boost::shared_ptr<ModelAPI_Feature>, boost::shared_ptr<GeomAPI_Shape> >
+                                                     PartSet_OperationSketchBase::preview() const
+{
+  return std::map<boost::shared_ptr<ModelAPI_Feature>, boost::shared_ptr<GeomAPI_Shape> >();
+}
+
 boost::shared_ptr<ModelAPI_Feature> PartSet_OperationSketchBase::createFeature()
 {
   boost::shared_ptr<ModelAPI_Feature> aFeature = ModuleBase_Operation::createFeature();
index b30f29935ba303eae52adcf9576b3e45ba1de2b0..cce1c55113f1b99362c47e0bce2efdc500d42f18 100644 (file)
@@ -15,6 +15,8 @@
 #include <ModuleBase_Operation.h>
 #include <QObject>
 
+#include <map>
+
 class Handle_V3d_View;
 class QMouseEvent;
 class GeomAPI_Shape;
@@ -43,6 +45,10 @@ public:
   /// \param theFeature the feature object to obtain the preview
   boost::shared_ptr<GeomAPI_Shape> preview(boost::shared_ptr<ModelAPI_Feature> theFeature) const;
 
+  /// Returns the map of the operation previews including the nested feature previews
+  /// \return the map of feature to the feature preview
+  virtual std::map<boost::shared_ptr<ModelAPI_Feature>, boost::shared_ptr<GeomAPI_Shape> > preview() const;
+
   /// Returns the operation local selection mode
   /// \param theFeature the feature object to get the selection mode
   /// \return the selection mode
index 25af3bea7bb586245b7c1def4c684911e9630114..eaae463ad2831260dc75a595e9c8a761f645e09c 100644 (file)
@@ -34,6 +34,9 @@ public:
 
   PARTSETPLUGIN_EXPORT virtual boost::shared_ptr<ModelAPI_Document> documentToAdd();
 
+  /// Returns true if this feature must be displayed in the history (top level of Part tree)
+  PARTSETPLUGIN_EXPORT virtual bool isInHistory() {return false;}
+
   /// Use plugin manager for features creation
   PartSetPlugin_Part();
 };
index e7d9d292ac90e44937429ac44a5ea2fb23052938..00c849fc9e1023abf5aa5c6f842c8852a6055722 100644 (file)
@@ -1,4 +1,34 @@
 #include "SketchPlugin_Feature.h"
+#include "SketchPlugin_Sketch.h"
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_AttributeRefList.h>
+
+SketchPlugin_Feature::SketchPlugin_Feature()
+{
+  mySketch = 0;
+}
+
+void SketchPlugin_Feature::setData(boost::shared_ptr<ModelAPI_Data> theData)
+{
+  ModelAPI_Feature::setData(theData);
+
+  // find sketch that references to this feature
+  int aSketches = document()->size("Construction");
+  for(int a = 0; a < aSketches && !mySketch; a++) {
+    boost::shared_ptr<SketchPlugin_Sketch> aSketch = 
+      boost::dynamic_pointer_cast<SketchPlugin_Sketch>(document()->feature("Construction", a));
+    std::list<boost::shared_ptr<ModelAPI_Feature> > aList = 
+      aSketch->data()->reflist(SKETCH_ATTR_FEATURES)->list();
+    std::list<boost::shared_ptr<ModelAPI_Feature> >::iterator aSub = aList.begin();
+    for(; aSub != aList.end(); aSub++) {
+      if ((*aSub)->data()->isEqual(theData)) {
+        mySketch = aSketch.get();
+        break;
+      }
+    }
+  }
+}
 
 void SketchPlugin_Feature::setPreview(const boost::shared_ptr<GeomAPI_Shape>& theShape)
 {
index d02728011b148aa4589d52b6a26f09ad1e3dc390..d83e21cceb25894ab2b64b1709dd815a6d6ba239 100644 (file)
@@ -43,6 +43,10 @@ protected:
   void setSketch(SketchPlugin_Sketch* theSketch) {mySketch = theSketch;}
   /// Returns the sketch of this feature
   SketchPlugin_Sketch* sketch() {return mySketch;}
+  /// initializes mySketch
+  SketchPlugin_Feature();
+  /// Sets the data manager of an object and here initializes mySketch field
+  SKETCHPLUGIN_EXPORT virtual void setData(boost::shared_ptr<ModelAPI_Data> theData);
 
   friend class SketchPlugin_Sketch;
 
index 8462d99bdea0ca55518a41d6c8fe4efce13b118a..ee3f8c8612dd9fa32e01d082f6864b51be5c561c 100644 (file)
@@ -15,7 +15,9 @@ using namespace std;
 const double PLANE_SIZE = 200;
 
 SketchPlugin_Line::SketchPlugin_Line()
+  : SketchPlugin_Feature()
 {
+  setSketch(0);
 }
 
 void SketchPlugin_Line::initAttributes()
@@ -31,17 +33,18 @@ void SketchPlugin_Line::execute()
 const boost::shared_ptr<GeomAPI_Shape>& SketchPlugin_Line::preview()
 {
   SketchPlugin_Sketch* aSketch = sketch();
-  // compute a start point in 3D view
-  boost::shared_ptr<GeomDataAPI_Point2D> aStartAttr = 
-    boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(LINE_ATTR_START));
-  boost::shared_ptr<GeomAPI_Pnt> aStart(aSketch->to3D(aStartAttr->x(), aStartAttr->y()));
-  // compute an end point in 3D view
-  boost::shared_ptr<GeomDataAPI_Point2D> anEndAttr = 
-    boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(LINE_ATTR_END));
-  boost::shared_ptr<GeomAPI_Pnt> anEnd(aSketch->to3D(anEndAttr->x(), anEndAttr->y()));
-  // make linear edge
-  boost::shared_ptr<GeomAPI_Shape> anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, anEnd);
-  setPreview(anEdge);
-
+  if (aSketch) {
+    // compute a start point in 3D view
+    boost::shared_ptr<GeomDataAPI_Point2D> aStartAttr = 
+      boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(LINE_ATTR_START));
+    boost::shared_ptr<GeomAPI_Pnt> aStart(aSketch->to3D(aStartAttr->x(), aStartAttr->y()));
+    // compute an end point in 3D view
+    boost::shared_ptr<GeomDataAPI_Point2D> anEndAttr = 
+      boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(LINE_ATTR_END));
+    boost::shared_ptr<GeomAPI_Pnt> anEnd(aSketch->to3D(anEndAttr->x(), anEndAttr->y()));
+    // make linear edge
+    boost::shared_ptr<GeomAPI_Shape> anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, anEnd);
+    setPreview(anEdge);
+  }
   return getPreview();
 }
index aad18bff78f4752c18dcde17c9696f89057e69c9..ea9af50b6bfd6138eea9e3575a077cf30d68ead6 100644 (file)
@@ -32,6 +32,7 @@ SET(PROJECT_HEADERS
     XGUI_ViewerProxy.h
     XGUI_ViewerPrs.h
     XGUI_PropertyPanel.h
+    XGUI_ContextMenuMgr.h
 )
 
 SET(PROJECT_AUTOMOC 
@@ -62,6 +63,7 @@ SET(PROJECT_SOURCES
     XGUI_ViewerProxy.cpp
     XGUI_ViewerPrs.cpp
     XGUI_PropertyPanel.cpp
+    XGUI_ContextMenuMgr.cpp
 )
 
 SET(PROJECT_RESOURCES 
diff --git a/src/XGUI/XGUI_ContextMenuMgr.cpp b/src/XGUI/XGUI_ContextMenuMgr.cpp
new file mode 100644 (file)
index 0000000..b191e7f
--- /dev/null
@@ -0,0 +1,89 @@
+
+#include "XGUI_ContextMenuMgr.h"
+#include "XGUI_Workshop.h"
+#include "XGUI_ObjectsBrowser.h"
+#include "XGUI_SelectionMgr.h"
+
+#include <QAction>
+#include <QContextMenuEvent>
+#include <QMenu>
+
+XGUI_ContextMenuMgr::XGUI_ContextMenuMgr(XGUI_Workshop* theParent) :
+QObject(theParent), myWorkshop(theParent)
+{
+
+}
+
+XGUI_ContextMenuMgr::~XGUI_ContextMenuMgr()
+{
+}
+
+void XGUI_ContextMenuMgr::createActions()
+{
+  QAction* aAction = new QAction(QIcon(":pictures/edit.png"), tr("Edit..."), this);
+  addAction("EDIT_CMD", aAction);
+}
+
+void XGUI_ContextMenuMgr::addAction(const QString& theId, QAction* theAction)
+{
+  if (myActions.contains(theId))
+    qCritical("A command with Id = '%s' already defined!", qPrintable(theId));
+  theAction->setData(theId);
+  connect(theAction, SIGNAL(triggered(bool)), this, SLOT(onAction(bool)));
+  myActions[theId] = theAction;
+}
+
+QAction* XGUI_ContextMenuMgr::action(const QString& theId) const
+{
+  if (myActions.contains(theId))
+    return myActions[theId];
+  return 0;
+}
+
+QStringList XGUI_ContextMenuMgr::actionIds() const
+{
+  return myActions.keys();
+}
+
+void XGUI_ContextMenuMgr::onAction(bool isChecked)
+{
+  QAction* aAction = static_cast<QAction*>(sender());
+  emit actionTriggered(aAction->data().toString(), isChecked);
+}
+
+void XGUI_ContextMenuMgr::updateCommandsStatus()
+{
+}
+
+void XGUI_ContextMenuMgr::onContextMenuRequest(QContextMenuEvent* theEvent)
+{
+  QMenu* aMenu = 0;
+  if (sender() == myWorkshop->objectBrowser())
+    aMenu = objectBrowserMenu();
+
+  if (aMenu) {
+    aMenu->exec(theEvent->globalPos());
+    delete aMenu;
+  }
+}
+
+QMenu* XGUI_ContextMenuMgr::objectBrowserMenu() const
+{
+  XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
+  QFeatureList aFeatures = aSelMgr->selectedFeatures();
+  if (aFeatures.size() == 1) {
+    FeaturePtr aFeature = aFeatures.first();
+    if (aFeature->getKind() != "Part") {
+      QMenu* aMenu = new QMenu();
+      aMenu->addAction(action("EDIT_CMD"));
+      return aMenu;
+    }
+  }
+  return 0;
+}
+
+void XGUI_ContextMenuMgr::connectObjectBrowser() const
+{
+  connect(myWorkshop->objectBrowser(), SIGNAL(contextMenuRequested(QContextMenuEvent*)), 
+    this, SLOT(onContextMenuRequest(QContextMenuEvent*)));
+}
\ No newline at end of file
diff --git a/src/XGUI/XGUI_ContextMenuMgr.h b/src/XGUI/XGUI_ContextMenuMgr.h
new file mode 100644 (file)
index 0000000..3ce0051
--- /dev/null
@@ -0,0 +1,50 @@
+
+#ifndef XGUI_ContextMenuMgr_H
+#define XGUI_ContextMenuMgr_H
+
+#include "XGUI.h"
+
+#include <QObject>
+#include <QMap>
+
+class XGUI_Workshop;
+class QAction;
+class QContextMenuEvent;
+class QMenu;
+
+class XGUI_EXPORT XGUI_ContextMenuMgr: public QObject
+{
+Q_OBJECT
+public:
+  XGUI_ContextMenuMgr(XGUI_Workshop* theParent);
+  virtual ~XGUI_ContextMenuMgr();
+
+  void createActions();
+
+  void addAction(const QString& theId, QAction* theAction);
+
+  QAction* action(const QString& theId) const;
+
+  QStringList actionIds() const;
+
+  void updateCommandsStatus();
+
+  void connectObjectBrowser() const;
+
+signals:
+  void actionTriggered(const QString& theId, bool isChecked);
+
+private slots:
+  void onAction(bool isChecked);
+
+  void onContextMenuRequest(QContextMenuEvent* theEvent);
+
+private:
+  QMenu* objectBrowserMenu() const;
+
+  QMap<QString, QAction*> myActions;
+
+  XGUI_Workshop* myWorkshop;
+};
+
+#endif
\ No newline at end of file
index 676c9d8fdf98e249441ae195287e952f57e4d033..be711129293bb2f8bb55932384b19ce906f0c7d4 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <ModelAPI_Document.h>
 #include <QAbstractItemModel>
+#include <QColor>
 
 /**\class XGUI_FeaturesModel
  * \ingroup GUI
@@ -16,7 +17,7 @@ class XGUI_EXPORT XGUI_FeaturesModel : public QAbstractItemModel
 {
 public:
   XGUI_FeaturesModel(const boost::shared_ptr<ModelAPI_Document>& theDocument, QObject* theParent):
-      QAbstractItemModel(theParent), myDocument(theDocument) {}
+      QAbstractItemModel(theParent), myDocument(theDocument), myItemsColor(Qt::black) {}
 
   //! Returns Feature object by the given Model index.
   //! Returns 0 if the given index is not index of a feature
@@ -28,8 +29,13 @@ public:
   //! Returns index corresponded to the group
   virtual QModelIndex findGroup(const std::string& theGroup) const = 0;
 
+  void setItemsColor(const QColor& theColor) { myItemsColor = theColor; }
+
+  QColor itemsColor() const { return myItemsColor; }
+
 protected:
   boost::shared_ptr<ModelAPI_Document> myDocument;
+  QColor myItemsColor;
 };
 
 
@@ -48,6 +54,9 @@ public:
   //! Returns true if the given document is a sub-document of this tree
   virtual bool hasDocument(const boost::shared_ptr<ModelAPI_Document>& theDoc) const = 0;
 
+  //! Return a Part object
+  virtual FeaturePtr part() const = 0;
+
 protected:
   //! Id of the current part object in the document
   int myId;
index 20a6f721e9f38e7285b3440405e7e18a2edf67e5..2613adae6bbc9ab20b77f31e8b3f5e49b7bb6e75 100644 (file)
@@ -141,6 +141,26 @@ void XGUI_Displayer::RedisplayInLocalContext(boost::shared_ptr<ModelAPI_Feature>
     aContext->UpdateCurrentViewer();
 }
 
+void XGUI_Displayer::EraseAll(const bool isUpdateViewer)
+{
+  Handle(AIS_InteractiveContext) ic = AISContext();
+
+  AIS_ListOfInteractive aList;
+  ic->DisplayedObjects(aList);
+  AIS_ListIteratorOfListOfInteractive anIter(aList);
+  for (; anIter.More(); anIter.Next()) {
+    if ((anIter.Value()->DynamicType() == STANDARD_TYPE(AIS_Trihedron)))
+      continue;
+
+    // erase an object
+    Handle(AIS_InteractiveObject) anIO = anIter.Value();
+    ic->Erase(anIO, false);
+  }
+  myFeature2AISObjectMap.clear();
+  if (isUpdateViewer)
+    ic->UpdateCurrentViewer();
+}
+
 void XGUI_Displayer::CloseLocalContexts(const bool isUpdateViewer)
 {
   closeAllContexts(true);
@@ -156,6 +176,13 @@ void XGUI_Displayer::closeAllContexts(const bool isUpdateViewer)
   }
 }
 
+void XGUI_Displayer::UpdateViewer()
+{
+  Handle(AIS_InteractiveContext) ic = AISContext();
+  if (!ic.IsNull())
+    ic->UpdateCurrentViewer();
+}
+
 Handle(AIS_InteractiveContext) XGUI_Displayer::AISContext() const 
 { 
   return myWorkshop->viewer()->AISContext(); 
index cda9331e648489f658a302927900d3a2af8e1d3d..a8bfbe2f35d0d2364befa48b2b01163bf6deb4ea 100644 (file)
@@ -81,10 +81,17 @@ public:
   /// \param isUpdateViewer the parameter whether the viewer should be update immediatelly
   void Erase(boost::shared_ptr<ModelAPI_Feature> theFeature, const bool isUpdateViewer = true);
 
+  /// Erase all presentations
+  /// \param isUpdateViewer the parameter whether the viewer should be update immediatelly
+  void EraseAll(const bool isUpdateViewer = true);
+
   /// Deactivates selection of sub-shapes
   /// \param isUpdateViewer the parameter whether the viewer should be update immediatelly
   void CloseLocalContexts(const bool isUpdateViewer = true);
 
+  /// Updates the viewer
+  void UpdateViewer();
+
 protected:
   /// Deactivate local selection
   /// \param isUpdateViewer the state wether the viewer should be updated immediatelly
index 16a56174e2c13013a8ac36e29399bd0ccc315719..7962105ca1f2221b7b8e33474741e29ae6259ed6 100644 (file)
 
 #include <QIcon>
 #include <QString>
+#include <QBrush>
 
 
+#define ACTIVE_COLOR QColor(0,72,140)
+#define PASSIVE_COLOR Qt::black
+
 XGUI_DocumentDataModel::XGUI_DocumentDataModel(QObject* theParent)
-  : QAbstractItemModel(theParent)
+  : QAbstractItemModel(theParent), myActivePart(0)
 {
   // Find Document object
   boost::shared_ptr<ModelAPI_PluginManager> aMgr = ModelAPI_PluginManager::get();
@@ -30,6 +34,7 @@ XGUI_DocumentDataModel::XGUI_DocumentDataModel(QObject* theParent)
 
   // Create a top part of data tree model
   myModel = new XGUI_TopDataModel(myDocument, this);
+  myModel->setItemsColor(ACTIVE_COLOR);
 }
 
 
@@ -154,6 +159,11 @@ QVariant XGUI_DocumentDataModel::data(const QModelIndex& theIndex, int theRole)
       return QIcon(":pictures/constr_folder.png");
     case Qt::ToolTipRole:
       return tr("Parts folder");
+    case Qt::ForegroundRole:
+      if (myActivePart)
+        return QBrush(PASSIVE_COLOR);
+      else
+        return QBrush(ACTIVE_COLOR);
     default:
       return QVariant();
     }
@@ -174,6 +184,11 @@ QVariant XGUI_DocumentDataModel::data(const QModelIndex& theIndex, int theRole)
         return QIcon(XGUI_Workshop::featureIcon(aFeature->getKind()));
       case Qt::ToolTipRole:
         return tr("Feature object");
+      case Qt::ForegroundRole:
+        if (myActivePart)
+          return QBrush(PASSIVE_COLOR);
+        else
+          return QBrush(ACTIVE_COLOR);
       default:
         return QVariant();
       }
@@ -184,7 +199,7 @@ QVariant XGUI_DocumentDataModel::data(const QModelIndex& theIndex, int theRole)
   if (aParent.isValid() && (aParent.internalId() == PartsFolder)) {
     return myPartModels.at(theIndex.row())->data(QModelIndex(), theRole);
   }
-  return toSourceModelIndex(theIndex).data(theRole);
+  return toSourceModelIndex(theIndex)->data(theRole);
 }
 
 
@@ -208,11 +223,16 @@ int XGUI_DocumentDataModel::rowCount(const QModelIndex& theParent) const
   if (theParent.internalId() == HistoryNode) {
     return 0;
   }
-  QModelIndex aParent = toSourceModelIndex(theParent);
-  if (!isSubModel(aParent.model())) 
+  QModelIndex* aParent = toSourceModelIndex(theParent);
+  const QAbstractItemModel* aModel = aParent->model();
+  if (!isSubModel(aModel)) 
     return 0;
 
-  return aParent.model()->rowCount(aParent);
+  /*if (isPartSubModel(aModel)) {
+    if (aModel != myActivePart)
+      return 0;
+  }*/
+  return aModel->rowCount(*aParent);
 }
 
 int XGUI_DocumentDataModel::columnCount(const QModelIndex& theParent) const
@@ -252,21 +272,21 @@ QModelIndex XGUI_DocumentDataModel::parent(const QModelIndex& theIndex) const
   if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
     return QModelIndex();
 
-  QModelIndex aIndex = toSourceModelIndex(theIndex);
-  const QAbstractItemModel* aModel = aIndex.model();
+  QModelIndex* aIndex = toSourceModelIndex(theIndex);
+  const QAbstractItemModel* aModel = aIndex->model();
   if (!isSubModel(aModel)) 
     return QModelIndex();
 
   if (isPartSubModel(aModel)) {
-    if (!aModel->parent(aIndex).isValid()) {
+    if (!aModel->parent(*aIndex).isValid()) {
       return partFolderNode();
     }
   }
 
-  aIndex = aModel->parent(aIndex);
-  if (aIndex.isValid())
-    return createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
-  return aIndex;
+  QModelIndex aIndex1 = aModel->parent(*aIndex);
+  if (aIndex1.isValid())
+    return createIndex(aIndex1.row(), aIndex1.column(), (void*)getModelIndex(aIndex1));
+  return aIndex1;
 }
 
 
@@ -278,10 +298,10 @@ bool XGUI_DocumentDataModel::hasChildren(const QModelIndex& theParent) const
 }
 
 
-QModelIndex XGUI_DocumentDataModel::toSourceModelIndex(const QModelIndex& theProxy) const
+QModelIndex* XGUI_DocumentDataModel::toSourceModelIndex(const QModelIndex& theProxy) const
 {
   QModelIndex* aIndexPtr = static_cast<QModelIndex*>(theProxy.internalPointer());
-  return (*aIndexPtr);
+  return aIndexPtr;
 }
 
 
@@ -323,12 +343,12 @@ FeaturePtr XGUI_DocumentDataModel::feature(const QModelIndex& theIndex) const
       int aOffset = historyOffset();
       return myDocument->feature(FEATURES_GROUP, theIndex.row() - aOffset);
   }
-  QModelIndex aIndex = toSourceModelIndex(theIndex);
-  if (!isSubModel(aIndex.model())) 
+  QModelIndex* aIndex = toSourceModelIndex(theIndex);
+  if (!isSubModel(aIndex->model())) 
     return FeaturePtr();
 
-  const XGUI_FeaturesModel* aModel = dynamic_cast<const XGUI_FeaturesModel*>(aIndex.model());
-  return aModel->feature(aIndex);
+  const XGUI_FeaturesModel* aModel = dynamic_cast<const XGUI_FeaturesModel*>(aIndex->model());
+  return aModel->feature(*aIndex);
 }
 
 bool XGUI_DocumentDataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
@@ -394,4 +414,38 @@ int XGUI_DocumentDataModel::historyOffset() const
 {
   // Nb of rows of top model + Parts folder
   return myModel->rowCount(QModelIndex()) + 1;
+}
+
+bool XGUI_DocumentDataModel::activatedIndex(const QModelIndex& theIndex)
+{
+  if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
+    return false;
+
+  QModelIndex* aIndex = toSourceModelIndex(theIndex);
+  if (!aIndex)
+    return false;
+
+  const QAbstractItemModel* aModel = aIndex->model();
+
+  if (isPartSubModel(aModel)) {
+    // if this is root node (Part item index)
+    if (!aIndex->parent().isValid()) {
+      if (myActivePart) myActivePart->setItemsColor(PASSIVE_COLOR);
+      myActivePart = (myActivePart == aModel)? 0 : (XGUI_PartModel*)aModel;
+      if (myActivePart) {
+        myActivePart->setItemsColor(ACTIVE_COLOR);
+        myModel->setItemsColor(PASSIVE_COLOR);
+      } else 
+         myModel->setItemsColor(ACTIVE_COLOR);
+     return true;
+    }
+  }
+  return false;
+}
+
+FeaturePtr XGUI_DocumentDataModel::activePart() const
+{
+  if (myActivePart) 
+    return myActivePart->part();
+  return FeaturePtr();
 }
\ No newline at end of file
index 7214c82f4e443a68244b4e8428c49ad6618fb6bf..68bfa406252f3c8e30a112fab1ca8ea98dee4cdc 100644 (file)
@@ -54,13 +54,19 @@ public:
   //! Returns 0 if the given index is not index of a feature
   FeaturePtr feature(const QModelIndex& theIndex) const;
 
+  //! Activates a part data model if the index is a Part node index. 
+  //! Returns true if active part changed.
+  bool activatedIndex(const QModelIndex& theIndex);
+
+  FeaturePtr activePart() const;
+
 private:
 
   enum {PartsFolder, HistoryNode};
 
 
   //! Converts QModelIndex of this model to QModelIndex of a one of sub-models.
-  QModelIndex toSourceModelIndex(const QModelIndex& theProxy) const;
+  QModelIndex* toSourceModelIndex(const QModelIndex& theProxy) const;
 
   //! Finds a pointer on QModelIndex which is equal to the given one
   QModelIndex* findModelIndex(const QModelIndex& theIndex) const;
@@ -95,6 +101,9 @@ private:
   //! Data models for Parts data tree representation (one data model per a one part)
   QList<XGUI_PartModel*> myPartModels;
 
+  //! Active part in part editing mode
+  XGUI_PartModel* myActivePart;
+
   //! List of saved QModelIndexes created by sub-models
   QList<QModelIndex*> myIndexes;
 
index 8355754d6bbd70e88ce846d07e3b9992cf00603c..21530908eadd40b545986b574b114e2f6d780ade 100644 (file)
@@ -31,4 +31,19 @@ void XGUI_ObjectsBrowser::onSelectionChanged(const QItemSelection& theSelected,
       mySelectedData.append(aFeature);
   }
   emit selectionChanged();
+}
+
+void XGUI_ObjectsBrowser::mouseDoubleClickEvent(QMouseEvent* theEvent)
+{
+  QModelIndex aIndex = currentIndex();
+  bool isChanged = myDocModel->activatedIndex(aIndex);
+  QTreeView::mouseDoubleClickEvent(theEvent);
+  if (isChanged) {
+    emit activePartChanged(myDocModel->activePart());
+  }
+}
+
+void XGUI_ObjectsBrowser::contextMenuEvent(QContextMenuEvent* theEvent)
+{
+  emit contextMenuRequested(theEvent);
 }
\ No newline at end of file
index b0949534bb6e321af70a2c9fe74cfdf484b9f027..fd1adbed8b1cc6b1852fecc7e96706b1fb9fc00a 100644 (file)
@@ -29,7 +29,14 @@ public:
 signals:
   //! Emited when selection is changed
   void selectionChanged();
+  void activePartChanged(FeaturePtr thePart); 
+  //! Emited on context menu request
+  void contextMenuRequested(QContextMenuEvent* theEvent);
 
+protected:
+  virtual void mouseDoubleClickEvent(QMouseEvent* theEvent);
+  virtual void contextMenuEvent(QContextMenuEvent* theEvent);
 
 private slots:
   //! Called when selection in Data Tree is changed
@@ -41,6 +48,8 @@ private:
 
   //! List of currently selected data
   QFeatureList mySelectedData;
+
+  //QModelIndex myActivePartIndex;
 };
 
 #endif
\ No newline at end of file
index 7119a8fa19cbf726c364190dd736e9d70cef6f74..00419c69238d19063e84d0aa1c41cb39cce61bf2 100644 (file)
@@ -46,6 +46,16 @@ bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation)
   return true;
 }
 
+bool XGUI_OperationMgr::abortOperation()
+{
+  ModuleBase_Operation* aCurrentOp = currentOperation();
+  if (!aCurrentOp || !canStopOperation())
+    return false; 
+
+  aCurrentOp->abort();
+  return true;
+}
+
 void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation)
 {
   connect(theOperation, SIGNAL(stopped()), this, SLOT(onOperationStopped()));
@@ -60,10 +70,7 @@ bool XGUI_OperationMgr::canStartOperation(ModuleBase_Operation* theOperation)
   ModuleBase_Operation* aCurrentOp = currentOperation();
   if (aCurrentOp && !theOperation->isGranted())
   {
-    int anAnswer = QMessageBox::question(0, tr("Operation launch"),
-                                tr("Previous operation is not finished and will be aborted"),
-                                QMessageBox::Ok, QMessageBox::Cancel);
-    if (anAnswer == QMessageBox::Ok) {
+    if (canStopOperation()) {
       aCurrentOp->abort();
     } else {
       aCanStart = false;
@@ -72,6 +79,14 @@ bool XGUI_OperationMgr::canStartOperation(ModuleBase_Operation* theOperation)
   return aCanStart;
 }
 
+bool XGUI_OperationMgr::canStopOperation()
+{
+  int anAnswer = QMessageBox::question(0, tr("Operation launch"),
+                              tr("Previous operation is not finished and will be aborted"),
+                              QMessageBox::Ok, QMessageBox::Cancel);
+  return anAnswer == QMessageBox::Ok;
+}
+
 void XGUI_OperationMgr::onOperationStopped()
 {
   ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
index fc6214d56748e7772dd6e86cf64935ee3243cab8..41323570ec46fc3e6fcf12566182c9c84e0e48a6 100644 (file)
@@ -43,6 +43,10 @@ public:
   /// \return the state whether the current operation is started
   bool startOperation(ModuleBase_Operation* theOperation);
 
+  /// Abort the operation and append it to the stack of operations
+  /// \return the state whether the current operation is aborted
+  bool abortOperation();
+
 signals:
   /// Signal about an operation is started. It is emitted after the start() of operation is done.
   void operationStarted();
@@ -62,6 +66,9 @@ protected:
   /// \param theOperation an operation to check
   bool canStartOperation(ModuleBase_Operation* theOperation);
 
+  /// Returns whether the operation can be stopped.
+  bool canStopOperation();
+
 protected slots:
   /// Slot that is called by an operation stop. Removes the stopped operation form the stack.
   /// If there is a suspended operation, restart it.
index cc5b7395c17e8c856e4f9610eceb95040f72fc4d..fc55498462b07b665eaf7d84d542130e5fb6e702 100644 (file)
@@ -8,6 +8,7 @@
 #include <ModelAPI_AttributeDocRef.h>
 
 #include <QIcon>
+#include <QBrush>
 
 XGUI_TopDataModel::XGUI_TopDataModel(const boost::shared_ptr<ModelAPI_Document>& theDocument, QObject* theParent)
   : XGUI_FeaturesModel(theDocument, theParent)
@@ -63,6 +64,9 @@ QVariant XGUI_TopDataModel::data(const QModelIndex& theIndex, int theRole) const
   case Qt::ToolTipRole:
     // return Tooltip
     break;
+  case Qt::ForegroundRole:
+    return QBrush(myItemsColor);
+    break;
   }
   return QVariant();
 }
@@ -248,6 +252,9 @@ QVariant XGUI_PartDataModel::data(const QModelIndex& theIndex, int theRole) cons
   case Qt::ToolTipRole:
     // return Tooltip
     break;
+  case Qt::ForegroundRole:
+    return QBrush(myItemsColor);
+    break;
   }
   return QVariant();
 }
@@ -384,3 +391,8 @@ QModelIndex XGUI_PartDataModel::findGroup(const std::string& theGroup) const
     return createIndex(1, 0, (qint32) ConstructFolder);
   return QModelIndex();
 }
+
+FeaturePtr XGUI_PartDataModel::part() const
+{
+  return myDocument->feature(PARTS_GROUP, myId);
+}
\ No newline at end of file
index abda0bfded8df3b8a616c6aee4b265d9e0a5dccb..0c857f95b83e153507b30e3d9da30a9e56370ebc 100644 (file)
@@ -94,6 +94,9 @@ public:
   //! Returns index corresponded to the group
   virtual QModelIndex findGroup(const std::string& theGroup) const;
 
+  //! Return a Part object
+  virtual FeaturePtr part() const;
+
 private: 
   boost::shared_ptr<ModelAPI_Document> featureDocument() const;
 
index bff1e923f5451a5e8226e17ee41cc45be1f5c4da..5a1a9ba4097ed64aeef7c13082fce24c09e0f8ae 100644 (file)
@@ -680,7 +680,8 @@ void XGUI_ViewWindow::vpMousePressEvent(QMouseEvent* theEvent)
 void XGUI_ViewWindow::contextMenuEvent(QContextMenuEvent* theEvent)
 {
   if (theEvent->modifiers() == Qt::NoModifier) {
-    QFrame::contextMenuEvent(theEvent);
+    // Temporary: has to be removed when viewer popup will be defined
+    //QFrame::contextMenuEvent(theEvent);
     emit contextMenuRequested(theEvent);
   }
 }
index b5b5aaedccec41b460b3aa7b6d4f6ba5b63ee8bf..78d9d841ccd01c6ba2f8407fc096e46d36e14e44 100644 (file)
@@ -6,6 +6,8 @@
 #include <QMdiArea>
 #include <QMdiSubWindow>
 #include <QApplication>
+#include <QMouseEvent>
+#include <QMenu>
 
 #include <V3d_View.hxx>
 
@@ -22,7 +24,6 @@
 #include <AIS_ListIteratorOfListOfInteractive.hxx>
 #include <AIS_Shape.hxx>
 
-#include <QMouseEvent>
 
 #ifdef WIN32
 #include <WNT_Window.hxx>
@@ -443,8 +444,8 @@ void XGUI_Viewer::addView(QMdiSubWindow* theView)
     connect(aWindow, SIGNAL(keyReleased(XGUI_ViewWindow*, QKeyEvent*)),
             this,    SIGNAL(keyRelease(XGUI_ViewWindow*, QKeyEvent*)));
 
-    //connect(aWindow, SIGNAL(contextMenuRequested( QContextMenuEvent* )),
-    //        this,    SLOT  (onContextMenuRequested( QContextMenuEvent* )));
+    connect(aWindow, SIGNAL(contextMenuRequested( QContextMenuEvent* )),
+            this,    SLOT  (onContextMenuRequested( QContextMenuEvent* )));
     //connect(aWindow, SIGNAL( contextMenuRequested(QContextMenuEvent*) ), 
     //        this, SIGNAL( contextMenuRequested(QContextMenuEvent*) ) );
 
@@ -583,3 +584,31 @@ void XGUI_Viewer::updateViewsDrawMode() const
     aView->updateEnabledDrawMode();
   }
 }
+
+//******************************************************
+void XGUI_Viewer::onContextMenuRequested(QContextMenuEvent* theEvent)
+{
+  XGUI_ViewWindow* aWnd = dynamic_cast<XGUI_ViewWindow*>(sender());
+  if (!aWnd) return;
+
+  QMenu aMenu;
+
+  // Include Viewer actions
+  if (myActions.size() > 0) {
+    aMenu.addActions(myActions);
+    aMenu.addSeparator();
+  }
+  if (aWnd->actions().size() > 0) {
+    aMenu.addActions(aWnd->actions());
+    aMenu.addSeparator();
+  }
+
+  QMdiArea* aMDI = myMainWindow->mdiArea();
+  if (aMenu.actions().size() > 0) {
+    QMenu* aSubMenu = aMenu.addMenu(tr("Windows"));
+    aSubMenu->addActions(aMDI->actions());
+  } else {
+    aMenu.addActions(aMDI->actions());
+  }
+  aMenu.exec(theEvent->globalPos());
+}
\ No newline at end of file
index 1eb2bd47ebee640af40ecba489046274a8a94629..d85a160cf9edbf96c33e98cdce185eb2e4aec4be 100644 (file)
@@ -7,6 +7,8 @@
 #include <QObject>
 #include <QMap>
 #include <QList>
+#include <QPoint>
+#include <QAction>
 
 #include <V3d_Viewer.hxx>
 #include <AIS_InteractiveContext.hxx>
@@ -14,7 +16,6 @@
 #include <NCollection_List.hxx>
 #include <TopoDS_Shape.hxx>
 
-#include <QPoint>
 
 class XGUI_MainWindow;
 class QMdiSubWindow;
@@ -123,6 +124,10 @@ public:
   //! Compute trihedron size dependent on 3d scene size
   bool computeTrihedronSize(double& theNewSize, double& theSize);
 
+  //! Add action to the viewer
+  void addAction(QAction* theAction) { myActions.append(theAction); }
+
+
   static void setHotButton(XGUI::InteractionStyle theInteractionStyle, XGUI::HotOperation theOper,
                            Qt::KeyboardModifiers theState, Qt::MouseButtons theButton);
   static void getHotButton(XGUI::InteractionStyle theInteractionStyle, XGUI::HotOperation theOper,
@@ -160,6 +165,7 @@ private slots:
   void onMouseMove(XGUI_ViewWindow* theWindow, QMouseEvent* theEvent);
   void onMouseReleased(XGUI_ViewWindow* theWindow, QMouseEvent* theEvent);
   void onMousePressed(XGUI_ViewWindow* theWindow, QMouseEvent* theEvent);
+  void onContextMenuRequested(QContextMenuEvent* theEvent);
 
 private:
   void addView(QMdiSubWindow* theView);
@@ -192,8 +198,11 @@ private:
   /// Points used for selection management
   QPoint myStartPnt, myEndPnt, myCurPnt;
 
-  // A counter of created windows
+  /// A counter of created windows
   int myWndIdCount;
+
+  /// List of Viewer actions
+  QList<QAction*> myActions;
 };
 
 #endif
index b0db00ee93d8df6efc5adafbea20916a801c88f0..20f4e47c7bc6e25184a512f58fdd12f54bfc6543 100644 (file)
@@ -19,6 +19,7 @@
 #include "XGUI_ErrorDialog.h"
 #include "XGUI_ViewerProxy.h"
 #include "XGUI_PropertyPanel.h"
+#include "XGUI_ContextMenuMgr.h"
 
 #include <Model_Events.h>
 #include <ModelAPI_PluginManager.h>
@@ -79,11 +80,11 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
   myDisplayer = new XGUI_Displayer(this);
 
   mySelector = new XGUI_SelectionMgr(this);
-  connect(mySelector, SIGNAL(selectionChanged()), this, SLOT(changeCurrentDocument()));
 
   myOperationMgr = new XGUI_OperationMgr(this);
   myActionsMgr = new XGUI_ActionsMgr(this);
   myErrorDlg = new XGUI_ErrorDialog(myMainWindow);
+  myContextMenuMgr = new XGUI_ContextMenuMgr(this);
 
   myViewerProxy = new XGUI_ViewerProxy(this);
 
@@ -178,6 +179,7 @@ void XGUI_Workshop::initMenu()
                                 QIcon(":pictures/close.png"), QKeySequence::Close);
   aCommand->connectTo(this, SLOT(onExit()));
 
+  myContextMenuMgr->createActions();
 }
 
 //******************************************************
@@ -422,7 +424,7 @@ void XGUI_Workshop::onOpen()
   }
 
   //show file dialog, check if readable and open
-  myCurrentFile = QFileDialog::getOpenFileName(mainWindow());
+  myCurrentFile = QFileDialog::getExistingDirectory(mainWindow());
   if(myCurrentFile.isEmpty())
     return;
   QFileInfo aFileInfo(myCurrentFile);
@@ -471,6 +473,9 @@ void XGUI_Workshop::onUndo()
   objectBrowser()->setCurrentIndex(QModelIndex());
   boost::shared_ptr<ModelAPI_PluginManager> aMgr = ModelAPI_PluginManager::get();
   boost::shared_ptr<ModelAPI_Document> aDoc = aMgr->rootDocument();
+  //if (!operationMgr()->abortOperation())
+  //  return;
+  operationMgr()->abortOperation();
   aDoc->undo();
   updateCommandStatus();
 }
@@ -572,25 +577,25 @@ void XGUI_Workshop::updateCommandStatus()
   if (aMgr->hasRootDocument()) {
     XGUI_Command* aUndoCmd;
     XGUI_Command* aRedoCmd;
-    for (aIt = aCommands.constBegin(); aIt != aCommands.constEnd(); ++aIt) {
-      if ((*aIt)->id() == "UNDO_CMD")
-        aUndoCmd = (*aIt);
-      else if ((*aIt)->id() == "REDO_CMD")
-        aRedoCmd = (*aIt);
+    foreach(XGUI_Command* aCmd, aCommands) {
+      if (aCmd->id() == "UNDO_CMD")
+        aUndoCmd = aCmd;
+      else if (aCmd->id() == "REDO_CMD")
+        aRedoCmd = aCmd;
       else // Enable all commands
-        (*aIt)->enable();
+        aCmd->enable();
     }
     boost::shared_ptr<ModelAPI_Document> aDoc = aMgr->rootDocument();
     aUndoCmd->setEnabled(aDoc->canUndo());
     aRedoCmd->setEnabled(aDoc->canRedo());
   } else {
-    for (aIt = aCommands.constBegin(); aIt != aCommands.constEnd(); ++aIt) {
-      if ((*aIt)->id() == "NEW_CMD")
-        (*aIt)->enable();
-      else if ((*aIt)->id() == "EXIT_CMD")
-        (*aIt)->enable();
+    foreach(XGUI_Command* aCmd, aCommands) {
+      if (aCmd->id() == "NEW_CMD")
+        aCmd->enable();
+      else if (aCmd->id() == "EXIT_CMD")
+        aCmd->enable();
       else 
-        (*aIt)->disable();
+        aCmd->disable();
     }
   }
 }
@@ -602,7 +607,10 @@ QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent)
   aObjDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
   aObjDock->setWindowTitle(tr("Object browser"));
   myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock);
+  connect(myObjectBrowser, SIGNAL(activePartChanged(FeaturePtr)), this, SLOT(changeCurrentDocument(FeaturePtr)));
   aObjDock->setWidget(myObjectBrowser);
+
+  myContextMenuMgr->connectObjectBrowser();
   return aObjDock;
 }
 
@@ -667,18 +675,15 @@ void XGUI_Workshop::onFeatureTriggered()
 }
 
 //******************************************************
-void XGUI_Workshop::changeCurrentDocument()
+void XGUI_Workshop::changeCurrentDocument(FeaturePtr thePart)
 {
-  QFeatureList aFeatures = objectBrowser()->selectedFeatures();
-  
-  // Set current document
-  if (aFeatures.size() > 0) {
-    FeaturePtr aFeature = aFeatures.first();
-
-    boost::shared_ptr<ModelAPI_PluginManager> aMgr = ModelAPI_PluginManager::get();
-    boost::shared_ptr<ModelAPI_AttributeDocRef> aDocRef = aFeature->data()->docRef("PartDocument");
+  boost::shared_ptr<ModelAPI_PluginManager> aMgr = ModelAPI_PluginManager::get();
+  if (thePart) {
+    boost::shared_ptr<ModelAPI_AttributeDocRef> aDocRef = thePart->data()->docRef("PartDocument");
     if (aDocRef)
       aMgr->setCurrentDocument(aDocRef->value());
+  } else {
+    aMgr->setCurrentDocument(aMgr->rootDocument());
   }
 }
 
index 922a4dd89726886200b87b5e1ebbedaa8bbf3aca..f0121474b608056a73f56fff7444d7ca5f8748c8 100644 (file)
@@ -2,6 +2,7 @@
 #define XGUI_WORKSHOP_H
 
 #include "XGUI.h"
+#include "XGUI_Constants.h"
 #include <Events_Listener.h>
 
 #include <QObject>
@@ -23,6 +24,7 @@ class XGUI_ErrorDialog;
 class XGUI_SalomeViewer;
 class XGUI_ViewerProxy;
 class XGUI_PropertyPanel;
+class XGUI_ContextMenuMgr;
 
 class ModuleBase_Operation;
 
@@ -68,6 +70,9 @@ public:
   //! Returns property panel widget
   XGUI_PropertyPanel* propertyPanel() const { return myPropertyPanel; }
 
+  //! Returns context menu manager object
+  XGUI_ContextMenuMgr* contextMenuMgr() const { return myContextMenuMgr; }
+
   //! Creates and adds a new workbench (menu group) with the given name and returns it
   XGUI_Workbench* addWorkbench(const QString& theName);
 
@@ -114,7 +119,7 @@ public slots:
   void hideObjectBrowser();
 
   void onFeatureTriggered();
-  void changeCurrentDocument();
+  void changeCurrentDocument(FeaturePtr thePart);
 
 signals:
   void errorOccurred(const QString&);
@@ -158,6 +163,7 @@ private:
   XGUI_SalomeConnector* mySalomeConnector;
   XGUI_ErrorDialog* myErrorDlg;
   XGUI_ViewerProxy* myViewerProxy;
+  XGUI_ContextMenuMgr* myContextMenuMgr;
 
   static QMap<QString, QString> myIcons;
 
index 1efefb0801060fbf0d75d8bd6973275844609fe6..893d8d7b6b2a0442e8eaad115d2ea915630b6309 100644 (file)
@@ -7,7 +7,6 @@
      <file>pictures/redo.png</file>
      <file>pictures/undo.png</file>
      <file>pictures/rebuild.png</file>
-     <!--For test purposes-->
 
      <file>pictures/occ_view_back.png</file>
      <file>pictures/occ_view_bottom.png</file>
@@ -52,5 +51,6 @@
      <file>pictures/cascade_views.png</file>
      <file>pictures/tile_views.png</file>
      <file>pictures/new_view.png</file>
+     <file>pictures/edit.png</file>
  </qresource>
  </RCC>
diff --git a/src/XGUI/pictures/edit.png b/src/XGUI/pictures/edit.png
new file mode 100644 (file)
index 0000000..43a3174
Binary files /dev/null and b/src/XGUI/pictures/edit.png differ