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

34 files changed:
doc/CMakeLists.txt
src/ConnectorPlugin/ConnectorPlugin_ExportFeature.py
src/GeomAPI/GeomAPI_AISObject.cpp
src/Model/Model_AttributeSelection.cpp
src/Model/Model_ResultBody.cpp
src/Model/Model_Session.cpp
src/Model/Model_Session.h
src/ModelAPI/ModelAPI_Session.h
src/ModuleBase/CMakeLists.txt
src/ModuleBase/ModuleBase_ActionInfo.cpp [new file with mode: 0644]
src/ModuleBase/ModuleBase_ActionInfo.h [new file with mode: 0644]
src/ModuleBase/ModuleBase_IModule.h
src/ModuleBase/ModuleBase_IViewer.h
src/ModuleBase/ModuleBase_Operation.cpp
src/NewGeom/NewGeom_Module.cpp
src/NewGeom/NewGeom_Module.h
src/NewGeom/NewGeom_SalomeViewer.cpp
src/NewGeom/NewGeom_SalomeViewer.h
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_SketcherMgr.cpp
src/SketchPlugin/SketchPlugin_ConstraintRigid.cpp
src/SketchPlugin/SketchPlugin_Feature.h
src/XGUI/CMakeLists.txt
src/XGUI/XGUI_ActionsMgr.cpp
src/XGUI/XGUI_ActionsMgr.h
src/XGUI/XGUI_ContextMenuMgr.h
src/XGUI/XGUI_HistoryMenu.cpp [new file with mode: 0644]
src/XGUI/XGUI_HistoryMenu.h [new file with mode: 0644]
src/XGUI/XGUI_ObjectsBrowser.cpp
src/XGUI/XGUI_SalomeConnector.h
src/XGUI/XGUI_ViewerProxy.cpp
src/XGUI/XGUI_ViewerProxy.h
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_Workshop.h

index bf800eddae9ee46bb395c72f13549b7df153d7c7..c5d19b119c579d60ca232d9a2a2fb57574dea18e 100644 (file)
@@ -12,7 +12,7 @@ CONFIGURE_FILE(doxyfile.in
 
 ADD_CUSTOM_TARGET(INSTALL_DOCS
     COMMAND "${DOXYGEN_EXECUTABLE}"
-    COMMAND "${CMAKE_COMMAND}" --build "${PROJECT_BINARY_DIR}" --target install
+    COMMAND "${CMAKE_COMMAND}" --build "${PROJECT_BINARY_DIR}" --target install --config ${CMAKE_BUILD_TYPE}
     WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/doc"
 )
 INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tui DESTINATION doc OPTIONAL)
index e69b259fe73e248ffcc950f15fd775f2cc918af8..9f2768e4c68f875ee6a74bfc80fa07615238529e 100644 (file)
@@ -8,6 +8,15 @@ import ModelAPI
 import salome
 from salome.geom import geomBuilder
 
+def getObjectIndex(theName):
+    aStudy = salome.myStudy
+    aId = 0
+    aObj = aStudy.FindObjectByName(theName, "GEOM")
+    while len(aObj) != 0:
+        aId = aId + 1
+        aName = theName + '_' + str(aId)
+        aObj = aStudy.FindObjectByName(aName, "GEOM")
+    return aId
 
 ## @ingroup Plugins
 #  Feature to export all shapes and groups into the GEOM module
@@ -40,6 +49,7 @@ class ExportFeature(ModelAPI.ModelAPI_Feature):
 
     ## Exports all bodies
     def exportBodies(self):
+        global ShapeIndex
         kResultBodyType = "Bodies"
         aPartSize = self.Part.size(kResultBodyType)
         if aPartSize == 0:
@@ -56,7 +66,14 @@ class ExportFeature(ModelAPI.ModelAPI_Feature):
             aDump = aShape.getShapeStream()
             # Load shape to SALOME Geom
             aBrep = self.geompy.RestoreShape(aDump)
-            self.geompy.addToStudy(aBrep, "NewGeomShape_{0}".format(idx + 1))
+            aName = aBodyResult.data().name()
+            
+            # Make unique name
+            aId = getObjectIndex(aName)
+            if aId != 0:
+                aName = aName + '_' + str(aId)
+            
+            self.geompy.addToStudy(aBrep, aName)
             self.geomObjects.append([aShape, aBrep])
 
     ## Exports all groups
index aea1179d62076fc4aaddd0a1c44f53950acf8787..5e0c21b44ae344824eff4008ce15cf299a561dab 100644 (file)
@@ -274,6 +274,8 @@ void GeomAPI_AISObject::setColor(const int& theColor)
   if (!aDimAIS.IsNull()) {
     aDimAIS->DimensionAspect()->SetCommonColor(aColor);
   }
+  Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
+  aContext->SetColor(anAIS, aColor, false);
 }
 
 void GeomAPI_AISObject::setWidth(const double& theWidth)
@@ -296,6 +298,8 @@ void GeomAPI_AISObject::setColor(int theR, int theG, int theB)
   if (!aDimAIS.IsNull()) {
     aDimAIS->DimensionAspect()->SetCommonColor(aColor);
   }
+  Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
+  aContext->SetColor(anAIS, aColor, false);
 }
 
 bool GeomAPI_AISObject::empty() const
index b0b4d4b41d685bfab772d7c9875450b298100b0a..53c04b6863ad4cb7fd7eb1dea4ce00907a292e21 100644 (file)
@@ -384,6 +384,7 @@ void Model_AttributeSelection::selectBody(
       return;
     }
   }
+  //BRepTools::Write(aNewShape, "Selection0.brep");
   aSel.Select(aNewShape, aContext); 
 }
 
@@ -615,8 +616,10 @@ std::string Model_AttributeSelection::namingName()
   TopoDS_Shape aSubShape = aSubSh->impl<TopoDS_Shape>();
   TopoDS_Shape aContext  = aCont->shape()->impl<TopoDS_Shape>();
 #ifdef DEB_NAMING
+  if(aSubShape.ShapeType() == TopAbs_COMPOUND) {
   BRepTools::Write(aSubShape, "Selection.brep");
   BRepTools::Write(aContext, "Context.brep");
+  }
 #endif
   std::shared_ptr<Model_Document> aDoc = 
     std::dynamic_pointer_cast<Model_Document>(aCont->document());
@@ -632,7 +635,11 @@ std::string Model_AttributeSelection::namingName()
          case TopAbs_EDGE:
                  {
                  // name structure: F1 | F2 [| F3 | F4], where F1 & F2 the faces which gives the Edge in trivial case
-                 // if it is not atrivial case we use localization by neighbours. F3 & F4 - neighbour faces             
+                 // if it is not atrivial case we use localization by neighbours. F3 & F4 - neighbour faces    
+                 if (BRep_Tool::Degenerated(TopoDS::Edge(aSubShape))) {
+                         aName = "Degenerated_Edge";
+                         break;
+                 }    
                  TopTools_IndexedDataMapOfShapeListOfShape aMap;
                  TopExp::MapShapesAndAncestors(aContext, TopAbs_EDGE, TopAbs_FACE, aMap);
                  TopTools_IndexedMapOfShape aSMap; // map for ancestors of the sub-shape
@@ -716,12 +723,24 @@ std::string Model_AttributeSelection::namingName()
                        //n = aList.Extent();
 #endif
                        int n = aList.Extent();
-                       if(n < 3) { // open topology case => via edges
+                       if(n < 3) { // open topology case or Compound case => via edges
                          TopTools_IndexedDataMapOfShapeListOfShape aMap;
                      TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_EDGE, aMap);
-                         const TopTools_ListOfShape& aList2  = aMap.FindFromKey(aSubShape);
-                         if(aList2.Extent() >= 2)  { // regular solution
-                               TopTools_ListIteratorOfListOfShape itl(aList2);
+                         const TopTools_ListOfShape& aList22  = aMap.FindFromKey(aSubShape);
+                         if(aList22.Extent() >= 2)  { // regular solution
+#ifdef FIX_BUG1
+                       
+                           // bug! duplication; fix is below
+                           aFMap.Clear();
+                           TopTools_ListOfShape aListE;
+                           TopTools_ListIteratorOfListOfShape itl2(aList22);
+                       for (int i = 1;itl2.More();itl2.Next(),i++) {
+                           if(aFMap.Add(itl2.Value()))
+                                 aListE.Append(itl2.Value());
+                               }
+                           n = aListE.Extent();
+#endif
+                               TopTools_ListIteratorOfListOfShape itl(aListE);
                        for (int i = 1;itl.More();itl.Next(),i++) {
                              const TopoDS_Shape& anEdge = itl.Value();
                              std::string anEdgeName = GetShapeName(aDoc, anEdge, selectionLabel());
@@ -730,6 +749,9 @@ std::string Model_AttributeSelection::namingName()
                              else 
                                aName += "|" + anEdgeName;
                                }
+                         }//reg
+                         else { // dangle vertex: if(aList22.Extent() == 1)
+                                 //it should be already in DF
                          }
                        } 
                        else {
index 7d3fa0b8219b24d5b70540ad72362f489d24fbbe..44b4bdbec6fc1be206bf079efa2be6214be1560a 100644 (file)
@@ -33,7 +33,7 @@
 // DEB
 //#include <TCollection_AsciiString.hxx>
 //#include <TDF_Tool.hxx>
-#define DEB_IMPORT 1
+//#define DEB_IMPORT 1
 
 Model_ResultBody::Model_ResultBody()
 {
index 816b87f750d1e391f44a92ef939a0981d5214289..e9edb8856c2c0d1c9ba490caa0c8400951cbc07e 100644 (file)
@@ -50,7 +50,7 @@ void Model_Session::closeAll()
   Model_Application::getApplication()->deleteAllDocuments();
 }
 
-void Model_Session::startOperation()
+void Model_Session::startOperation(const std::string& theId)
 {
   ROOT_DOC->startOperation();
   static std::shared_ptr<Events_Message> aStartedMsg
@@ -118,6 +118,22 @@ void Model_Session::redo()
   setCheckTransactions(true);
 }
 
+//! Returns stack of performed operations
+std::list<std::string> Model_Session::undoList()
+{
+  std::list<std::string> temp;
+  temp.push_front("Part");
+  temp.push_front("Sketch");
+  temp.push_front("Extrusion");
+  return temp;
+}
+//! Returns stack of rolled back operations
+std::list<std::string> Model_Session::redoList()
+{
+  std::list<std::string> temp;
+  return temp;
+}
+
 FeaturePtr Model_Session::createFeature(string theFeatureID)
 {
   if (this != myImpl) {
index fa94b8aae8588b8153a7086aff2d0a4c3c5879e3..0ae8bc46aa44fe763f82023531cb27bc3be7aed7 100644 (file)
@@ -48,7 +48,7 @@ class Model_Session : public ModelAPI_Session, public Events_Listener
   MODEL_EXPORT virtual void closeAll();
 
   //! Starts a new operation (opens a tansaction)
-  MODEL_EXPORT virtual void startOperation();
+  MODEL_EXPORT virtual void startOperation(const std::string& theId);
   //! Finishes the previously started operation (closes the transaction)
   MODEL_EXPORT virtual void finishOperation();
   //! Aborts the operation 
@@ -66,6 +66,10 @@ class Model_Session : public ModelAPI_Session, public Events_Listener
   MODEL_EXPORT virtual bool canRedo();
   //! Redoes last operation
   MODEL_EXPORT virtual void redo();
+  //! Returns stack of performed operations
+  MODEL_EXPORT virtual std::list<std::string> undoList();
+  //! Returns stack of rolled back operations
+  MODEL_EXPORT virtual std::list<std::string> redoList();
 
   /// Returns the root document of the application (that may contains sub-documents)
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Document> moduleDocument();
index 619509dd2cfdeb97f5d75ec53db32c7556aed5c5..933dfc58689bb237d1fee40fa04dcf19a3e88a9b 100644 (file)
@@ -45,7 +45,8 @@ class MODELAPI_EXPORT ModelAPI_Session
   virtual void closeAll() = 0;
 
   //! Starts a new operation (opens a tansaction)
-  virtual void startOperation() = 0;
+  //! \param theId of operation for history (optional)
+  virtual void startOperation(const std::string& theId) = 0;
   //! Finishes the previously started operation (closes the transaction)
   virtual void finishOperation() = 0;
   //! Aborts the operation 
@@ -63,6 +64,10 @@ class MODELAPI_EXPORT ModelAPI_Session
   virtual bool canRedo() = 0;
   //! Redoes last operation
   virtual void redo() = 0;
+  //! Returns stack of performed operations (from last to first)
+  virtual std::list<std::string> undoList() = 0;
+  //! Returns stack of rolled back operations (from last rolled back to first)
+  virtual std::list<std::string> redoList() = 0;
 
   /// Registers the plugin that creates features.
   /// It is obligatory for each plugin to call this function on loading to be found by 
index 6d7fc7cf2afa9aa7dd63e79f81c563f5c42459f1..096e6eaaa0caa053d812baa90274c95cbfa65378 100644 (file)
@@ -42,6 +42,7 @@ SET(PROJECT_HEADERS
        ModuleBase_WidgetLabel.h
        ModuleBase_IPrefMgr.h
        ModuleBase_Preferences.h
+       ModuleBase_ActionInfo.h
 )
 
 SET(PROJECT_SOURCES
@@ -74,10 +75,12 @@ SET(PROJECT_SOURCES
        ModuleBase_ResultPrs.cpp
        ModuleBase_WidgetLabel.cpp
        ModuleBase_Preferences.cpp
+       ModuleBase_ActionInfo.cpp
 )
 
 SET(PROJECT_LIBRARIES
        Config
+       Events
        ModelAPI
        GeomAPI
        GeomAlgoAPI
diff --git a/src/ModuleBase/ModuleBase_ActionInfo.cpp b/src/ModuleBase/ModuleBase_ActionInfo.cpp
new file mode 100644 (file)
index 0000000..9089eca
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * ModuleBase_ActionInfo.cpp
+ *
+ *  Created on: Feb 4, 2015
+ *      Author: sbh
+ */
+
+#include <ModuleBase_ActionInfo.h>
+
+ModuleBase_ActionInfo::ModuleBase_ActionInfo()
+{
+  initDefault();
+}
+
+ModuleBase_ActionInfo::ModuleBase_ActionInfo(const QString &theText)
+{
+  initDefault();
+}
+
+ModuleBase_ActionInfo::ModuleBase_ActionInfo(const QIcon & theIcon, const QString &theText)
+{
+  initDefault();
+  icon = theIcon;
+  text = theText;
+}
+
+ModuleBase_ActionInfo::~ModuleBase_ActionInfo()
+{
+}
+
+void ModuleBase_ActionInfo::initFrom(QAction* theAction)
+{
+  // By convenience, QAction for a feature keeps feature's id as data (QVariant);
+  if (theAction->data().isValid()) {
+    id = theAction->data().toString();
+  }
+  checkable = theAction->isCheckable();
+  checked = theAction->isChecked();
+  enabled = theAction->isEnabled();
+  visible = theAction->isVisible();
+  icon = theAction->icon();
+  text = theAction->text();
+  iconText = theAction->iconText();
+  toolTip = theAction->toolTip();
+  // statusTip = theAction->statusTip();
+  // whatsThis = theAction->whatsThis();
+  shortcut = theAction->shortcut();
+  font = theAction->font();
+}
+
+void ModuleBase_ActionInfo::initFrom(std::shared_ptr<Config_FeatureMessage> theMessage)
+{
+  id = QString::fromStdString(theMessage->id());
+  iconFile = QString::fromStdString(theMessage->icon());
+  if (!iconFile.isEmpty()) {
+    icon = QIcon(iconFile);
+  }
+  text = QString::fromStdString(theMessage->text());
+  toolTip = QString::fromStdString(theMessage->tooltip());
+  QString aShortcutStr = QString::fromStdString(theMessage->keysequence());
+  if (!aShortcutStr.isEmpty()) {
+    shortcut = QKeySequence(aShortcutStr);
+  }
+  // If feature requires PropertyPannel for input, it should be checkable
+  checkable = theMessage->isUseInput();
+}
+
+QAction* ModuleBase_ActionInfo::makeAction(QObject* theParent)
+{
+  QAction* aResult = new QAction(icon, text, theParent);
+  aResult->setCheckable(checkable);
+  aResult->setChecked(checked);
+  aResult->setEnabled(enabled);
+  aResult->setVisible(visible);
+  aResult->setIconText(iconText);
+  aResult->setToolTip(toolTip);
+  // aResult->setStatusTip(statusTip);
+  // aResult->setWhatsThis(whatsThis);
+  aResult->setShortcut(shortcut);
+  aResult->setFont(font);
+  // By convenience, QAction for a feature keeps feature's id as data (QVariant);
+  aResult->setData(id);
+  return aResult;
+}
+
+void ModuleBase_ActionInfo::initDefault()
+{
+  id = QString();
+  checkable = false;
+  checked   = false;
+  enabled   = true;
+  visible   = true;
+  icon = QIcon();
+  text = QString();
+  iconText = QString();
+  iconFile = QString();
+  toolTip = QString();
+  // statusTip = QString();
+  // whatsThis = QString();
+  shortcut = QKeySequence();
+  font = QFont();
+}
diff --git a/src/ModuleBase/ModuleBase_ActionInfo.h b/src/ModuleBase/ModuleBase_ActionInfo.h
new file mode 100644 (file)
index 0000000..766a16b
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * ActionInfo.h
+ *
+ *  Created on: Feb 4, 2015
+ *      Author: sbh
+ */
+
+#ifndef MODULEBASE_ACTIONINFO_H_
+#define MODULEBASE_ACTIONINFO_H_
+
+#include <ModuleBase.h>
+#include <Config_FeatureMessage.h>
+
+#include <QAction>
+#include <QIcon>
+#include <QKeySequence>
+#include <QFont>
+
+#include <memory>
+
+/*!
+ * Structure to pass info about QActions, AppElements_Commands, etc.
+ */
+struct MODULEBASE_EXPORT ModuleBase_ActionInfo
+{
+  QString id;
+
+  bool checkable; //!< action's checkable state
+  bool checked; //!< action's checked state
+  bool enabled; //!< action's enabled state
+  bool visible; //!< action's visibility state
+  QIcon icon; //!< action's icon
+  QString text; //!< action's text
+  QString iconText; //!< action's descriptive icon text
+  QString iconFile; //!< path to icon's file. Can not be initialized from QAction
+  QString toolTip; //!< action's tooltip
+  // QString statusTip;
+  // QString whatsThis;
+  QKeySequence shortcut; //!< action's primary shortcut key
+  QFont font; //!< action's text font
+
+ public:
+  //! Default constructor, \sa initDefault
+  ModuleBase_ActionInfo();
+  //! Initializes structure with default values, except text
+  ModuleBase_ActionInfo(const QString &text);
+  //! Initializes structure with default values, except icon and text
+  ModuleBase_ActionInfo(const QIcon &icon, const QString &text);
+  virtual ~ModuleBase_ActionInfo();
+
+  //! Fills itself with info from given \param theAction
+  void initFrom(QAction* theAction);
+  //! Fills itself with info from given \param theFeatureMessage
+  void initFrom(std::shared_ptr<Config_FeatureMessage> theFeatureMessage);
+  //! Creates new QAction with given parent and data initialized from this structure
+  //! \param theParent - parent of created action
+  QAction* makeAction(QObject* theParent = 0);
+
+ protected:
+  //! Initializes structure with default values, like QAction()
+  void initDefault();
+};
+
+typedef ModuleBase_ActionInfo ActionInfo;
+
+#endif /* XGUI_ACTIONINFO_H_ */
index b500dd6f82ae3f97b4dbcb1498eabbf87925f4cc..32c7cdcbfb7df17206a47373efb8f5b4d516ee3a 100644 (file)
@@ -131,6 +131,9 @@ protected slots:
   /// Register properties of this module
   virtual void registerProperties() {}
 \r
+  /// Register properties of this module\r
+  virtual void registerProperties() {}\r
+\r
   /// Returns new instance of operation object (used in createOperation for customization)\r
   virtual ModuleBase_Operation* getNewOperation(const std::string& theFeatureId);\r
 \r
index ba7ee1b28f536114857a3d6e195018efd5a86e49..3cf3bc5ab332613847b717ad872f65de38ee6f00 100644 (file)
@@ -75,6 +75,10 @@ Q_OBJECT
   /// Update current viewer
   virtual void update() = 0;
 
+  /// Method returns True if the viewer can process editing objects 
+  /// by mouse drugging. If this is impossible thet it has to return False.
+  virtual bool canDragByMouse() const { return true; }
+
 signals:
   /// Signal emited when last view window is closed
   void lastViewClosed();
index de9a9e857adb4ab11e69a832dd9a2c57299b13df..bfe58446d370168a50092075ea228460c6ca7c25 100644 (file)
@@ -146,7 +146,8 @@ std::shared_ptr<ModelAPI_Document> ModuleBase_Operation::document() const
 
 void ModuleBase_Operation::start()
 {
-  ModelAPI_Session::get()->startOperation();
+  QString anId = getDescription()->operationId();
+  ModelAPI_Session::get()->startOperation(anId.toStdString());
 
   if (!myIsEditing)
     createFeature();
index 9f5c22ceb3d5a3936828d8024844e96662265081..50279350e19f198496233c71ed9cde0bcdc72db3 100644 (file)
@@ -325,6 +325,17 @@ QAction* NewGeom_Module::addFeature(const QString& theWBName, const QString& the
   return aAction;
 }
 
+QAction* NewGeom_Module::addFeature(const QString& theWBName, const ActionInfo& theInfo)
+{
+  return addFeature(theWBName,
+                    theInfo.id,
+                    theInfo.text,
+                    theInfo.toolTip,
+                    theInfo.icon,
+                    theInfo.shortcut);
+}
+
+
 //******************************************************
 QAction* NewGeom_Module::addDesktopCommand(const QString& theId, const QString& theTitle,
                                            const QString& theTip, const QIcon& theIcon,
index 3482c12e8ad90e3d830d4325727574957cd99bcc..36bae93af0388832b9f80a025dd97bdaed2fb0cf 100644 (file)
@@ -10,6 +10,8 @@
 #include <LightApp_Module.h>
 #include <XGUI_SalomeConnector.h>
 
+#include <ModuleBase_ActionInfo.h>
+
 #include <QStringList>
 #include <QMap>
 
@@ -51,6 +53,10 @@ Q_OBJECT
                               const QKeySequence& theKeys = QKeySequence(),
                               bool isCheckable = false);
 
+  virtual QAction* addFeature(const QString& theWBName,
+                                const ActionInfo& theInfo);
+
+
   virtual QAction* addDesktopCommand(const QString& theId, const QString& theTitle,
                                      const QString& theTip, const QIcon& theIcon,
                                      const QKeySequence& theKeys, bool isCheckable,
index 0613d66243959e0efcc1ed29da32efc6039d2639..c3c887ae8e71763f04ae01fdc30409815be02ff5 100644 (file)
@@ -153,11 +153,19 @@ void NewGeom_SalomeViewer::onMouseMove(SUIT_ViewWindow* theView, QMouseEvent* th
 {
   OCCViewer_ViewWindow* aViewWnd = dynamic_cast<OCCViewer_ViewWindow*>(theView);
   Handle(AIS_InteractiveContext) aContext = AISContext();
-  if (aContext->HasDetected())
+  if (aContext->HasDetected()) // Set focus to provide key events in the view
     aViewWnd->getViewPort()->setFocus(Qt::MouseFocusReason);
   emit mouseMove(myView, theEvent);
 }
 
+//**********************************************
+bool NewGeom_SalomeViewer::canDragByMouse() const
+{
+  OCCViewer_Viewer* aViewer = mySelector->viewer();
+  return (aViewer->interactionStyle() != 0);
+}
+
+
 //**********************************************
 void NewGeom_SalomeViewer::onKeyPress(SUIT_ViewWindow* theView, QKeyEvent* theEvent)
 {
index 1809dd2430ed674a1f8bda6452b2ccda8aa9caa1..1d471d1dcc97ea11d04d0479e291c804aae2b6c6 100644 (file)
@@ -113,6 +113,9 @@ Q_OBJECT
   /// Update current viewer
   virtual void update();
 
+  /// Method returns True if the viewer can process editing objects 
+  /// by mouse drugging. If this is impossible thet it has to return False.
+  virtual bool canDragByMouse() const;
 
  private slots:
   void onMousePress(SUIT_ViewWindow*, QMouseEvent*);
index 51684d7f37fa0a34fcd0c577e5505729cd8bac92..c3b59579668d445b63acc6eff22d7ab3a6dac072 100644 (file)
@@ -558,7 +558,7 @@ void PartSet_Module::deleteObjects()
   }
 
   SessionPtr aMgr = ModelAPI_Session::get();
-  aMgr->startOperation();
+  aMgr->startOperation("DeletePartSet");
   std::set<FeaturePtr>::const_iterator anIt = aRefFeatures.begin(),
                                        aLast = aRefFeatures.end();
   for (; anIt != aLast; anIt++) {
index 018001423cf4587155181f284f09482fffc8b65f..80fd683fef3c97a3d289cdb4cbced777e9b0fc52 100644 (file)
@@ -143,7 +143,14 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
   if (!(theEvent->buttons() & Qt::LeftButton))
     return;
 
+  // Clear dragging mode
+  myIsDragging = false;
+
   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
+  ModuleBase_IViewer* aViewer = aWorkshop->viewer();
+  if (!aViewer->canDragByMouse())
+    return;
+
   ModuleBase_Operation* aOperation = aWorkshop->currentOperation();
   if (aOperation && aOperation->isEditOperation()) {
     ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
@@ -154,9 +161,6 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
     }
   }
 
-  // Clear dragging mode
-  myIsDragging = false;
-
   // Use only for sketch operations
   if (aOperation && myCurrentSketch) {
     if (!PartSet_Tools::sketchPlane(myCurrentSketch))
@@ -176,7 +180,6 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
       return;
 
     // MoveTo in order to highlight current object
-    ModuleBase_IViewer* aViewer = aWorkshop->viewer();
     aViewer->AISContext()->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView());
 
     // Remember highlighted objects for editing
@@ -226,13 +229,15 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
 void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
 {
   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
+  ModuleBase_IViewer* aViewer = aWorkshop->viewer();
+  if (!aViewer->canDragByMouse())
+    return;
   ModuleBase_Operation* aOp = aWorkshop->currentOperation();
   if (aOp) {
     if (sketchOperationIdList().contains(aOp->id())) {
   get2dPoint(theWnd, theEvent, myClickedPoint);
 
       // Only for sketcher operations
-      ModuleBase_IViewer* aViewer = aWorkshop->viewer();
       if (myIsDragging) {
         if (myDragDone) {
           //aOp->commit();
index 5a7b9d5f9781283302182a23c2e8ad6a6013be56..00e973d1a0a04923945d885946fec94b6c1f5951 100644 (file)
@@ -44,6 +44,13 @@ AISObjectPtr SketchPlugin_ConstraintRigid::getAISObject(AISObjectPtr thePrevious
 
     if (!aConst) 
       return thePrevious;
+
+    std::shared_ptr<SketchPlugin_Feature> aSketchFea = 
+      std::dynamic_pointer_cast<SketchPlugin_Feature>(ModelAPI_Feature::feature(aConst));
+    if (aSketchFea.get() != NULL) {
+      if (aSketchFea->isExternal())
+        return thePrevious;
+    }
     aShape = aConst->shape();
   }
   else {
index acf95e2a67554a19c01394ce5a55f7ceec15c8ad..66d59467b5682dfb6fc6ebcf95a0aeb1083edb73 100644 (file)
@@ -60,7 +60,7 @@ class SketchPlugin_Feature : public ModelAPI_Feature, public GeomAPI_ICustomPrs
   {
     AttributeSelectionPtr aAttr = data()->selection(EXTERNAL_ID());
     if (aAttr)
-      return aAttr->context().get() == NULL;
+      return aAttr->context().get() != NULL;
     return false;
   }
 
@@ -68,8 +68,11 @@ class SketchPlugin_Feature : public ModelAPI_Feature, public GeomAPI_ICustomPrs
   virtual void customisePresentation(AISObjectPtr thePrs)
   {
     // if this is an edge
-    if (thePrs->getShapeType() == 6)
+    if (thePrs->getShapeType() == 6) {
       thePrs->setWidth(3);
+      if (isExternal())
+        thePrs->setColor(0,255,0);
+    }
     // if this is a vertex
     //else if (thePrs->getShapeType() == 7)
     //  thePrs->setPointMarker(6, 2.);
index 26879a5e3e478af7648742a0ed7cc1e13734b073..c7a27c7161cfdc275dc1f0be70c5ca5f2282d253 100644 (file)
@@ -23,6 +23,7 @@ SET(PROJECT_HEADERS
        XGUI_Tools.h
        XGUI_ViewerProxy.h
        XGUI_Workshop.h
+       XGUI_HistoryMenu.h
 )
 
 SET(PROJECT_AUTOMOC 
@@ -46,6 +47,7 @@ SET(PROJECT_SOURCES
        XGUI_Tools.cpp
        XGUI_ViewerProxy.cpp
        XGUI_Workshop.cpp
+       XGUI_HistoryMenu.cpp
 )
 
 SET(PROJECT_RESOURCES 
index 851e3fef0adff9e5feb81c9e2eb35d4f5c9b7f49..0d9c4d01fdf5f435f736757ed67f6a6191199b88 100644 (file)
@@ -161,18 +161,28 @@ void XGUI_ActionsMgr::updateOnViewSelection()
   }
 }
 
-QKeySequence XGUI_ActionsMgr::registerShortcut(const QString& theKeySequence)
+QKeySequence XGUI_ActionsMgr::registerShortcut(const QKeySequence& theKeySequence)
 {
   if (theKeySequence.isEmpty()) {
     return QKeySequence();
   }
-  QKeySequence aResult(theKeySequence);
-  if (myShortcuts.contains(aResult)) {
-    QString aMessage = tr("Shortcut %1 is already defined. Ignore.").arg(theKeySequence);
+  if (myShortcuts.contains(theKeySequence)) {
+    QString aMessage = tr("Shortcut %1 is already defined. Ignore.");
+    aMessage = aMessage.arg(theKeySequence.toString());
     Events_Error::send(aMessage.toStdString());
     return QKeySequence();
   }
-  myShortcuts.append(aResult);
+  myShortcuts.append(theKeySequence);
+  return theKeySequence;
+}
+
+QKeySequence XGUI_ActionsMgr::registerShortcut(const QString& theKeySequence)
+{
+  if (theKeySequence.isEmpty()) {
+    return QKeySequence();
+  }
+  QKeySequence aResult(theKeySequence);
+  registerShortcut(aResult);
   return aResult;
 }
 
index 8007e979421e63275f22a73277b729eed1b78e68..5c74e2b796c0ce6c43f36438561ffdcec1d74a34 100644 (file)
@@ -55,6 +55,11 @@ Q_OBJECT
 
   /// Registers shortcut (key sequence) for the command triggering
   /// \param theKeySequence a key sequence to register
+  QKeySequence registerShortcut(const QKeySequence& theKeySequence);
+
+  /// This is an overloaded function.
+  /// Registers shortcut (key sequence) for the command triggering
+  /// \param theKeySequence - string that contain a key sequence to register
   QKeySequence registerShortcut(const QString& theKeySequence);
 
   //! Redefinition of Events_Listener method
index 7fc3d6bfa9a45f4655fc92f6c805c6983e2cc6b6..a263c96979ce76c5e6d83b3bff37d52b73014f46 100644 (file)
@@ -46,7 +46,7 @@ Q_OBJECT
   void connectViewer() const;
 
   /// Add menu atems for viewer into the given menu (used in SALOME mode)
-  /// \param a popup menu to be shown in the viewer
+  /// \param theMenu a popup menu to be shown in the viewer
   void addViewerItems(QMenu* theMenu) const;
 
 signals:
diff --git a/src/XGUI/XGUI_HistoryMenu.cpp b/src/XGUI/XGUI_HistoryMenu.cpp
new file mode 100644 (file)
index 0000000..7ae27d0
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * XGUI_HistoryMenu.cpp
+ *
+ *  Created on: Feb 2, 2015
+ *      Author: sbh
+ */
+
+#include <XGUI_HistoryMenu.h>
+
+#include <ModelAPI_Session.h>
+
+#include <QListWidget>
+#include <QWidgetAction>
+#include <QToolButton>
+#include <QAction>
+
+//! Extends given feature with previously created context menu.
+//! \param theId - Id of the feature to add \a theMenu
+//! \param theMenu - Enables or disables menu feature
+XGUI_HistoryMenu::XGUI_HistoryMenu(QAction* theParent)
+ : QMenu(NULL),
+   myHistoryList(NULL)
+{
+  theParent->setMenu(this);
+  initMenu();
+
+  connect(theParent, SIGNAL(destroyed()), this, SLOT(deleteLater()));
+}
+
+//! Extends given feature with previously created context menu.
+//! \param theId - Id of the feature to add \a theMenu
+//! \param theMenu - Enables or disables menu feature
+XGUI_HistoryMenu::XGUI_HistoryMenu(QToolButton* theParent)
+ : QMenu(theParent),
+   myHistoryList(NULL)
+{
+  theParent->setMenu(this);
+  theParent->setPopupMode(QToolButton::MenuButtonPopup);
+
+  initMenu();
+}
+
+void XGUI_HistoryMenu::initMenu()
+{
+  myHistoryList = new QListWidget(this);
+  QWidgetAction* aListAction = new QWidgetAction(this);
+  aListAction->setDefaultWidget(myHistoryList);
+  this->addAction(aListAction);
+  myHistoryList->setMouseTracking(true);  // track mouse hover
+  myHistoryList->setSelectionMode(QAbstractItemView::ExtendedSelection);
+  connect(myHistoryList, SIGNAL(itemEntered(QListWidgetItem *)), this,
+          SLOT(setStackSelectedTo(QListWidgetItem *)));
+  connect(myHistoryList, SIGNAL(itemClicked(QListWidgetItem *)), this,
+          SLOT(onItemPressed(QListWidgetItem *)));
+}
+
+XGUI_HistoryMenu::~XGUI_HistoryMenu()
+{
+}
+
+void XGUI_HistoryMenu::setHistory(const QList<ActionInfo>& theActions)
+{
+  myHistoryList->clear();
+  foreach(ActionInfo anAct, theActions) {
+    QListWidgetItem* anItem = new QListWidgetItem(anAct.icon, anAct.text, myHistoryList);
+  }
+}
+
+
+void XGUI_HistoryMenu::setStackSelectedTo(QListWidgetItem * theItem)
+{
+  if (!theItem)
+    return;
+
+  QListWidgetItem* eachItem = NULL;
+  bool isSelect = true;
+  for(int aRow = 0; aRow < myHistoryList->count(); ++aRow) {
+    eachItem = myHistoryList->item(aRow);
+    myHistoryList->setItemSelected(eachItem, isSelect);
+    // Deselect items below hovered
+    if (eachItem == theItem) {
+      isSelect = false;
+    }
+  }
+}
+
+void XGUI_HistoryMenu::onItemPressed(QListWidgetItem * theItem)
+{
+  int selectedSize = myHistoryList->row(theItem) + 1;
+  emit actionSelected(selectedSize);
+  hide();
+  myHistoryList->clear();
+}
diff --git a/src/XGUI/XGUI_HistoryMenu.h b/src/XGUI/XGUI_HistoryMenu.h
new file mode 100644 (file)
index 0000000..bc45f7a
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * XGUI_HistoryMenu.h
+ *
+ *  Created on: Feb 2, 2015
+ *      Author: sbh
+ */
+
+#ifndef XGUI_HISTORYMENU_H_
+#define XGUI_HISTORYMENU_H_
+
+#include <XGUI.h>
+#include <QMenu>
+
+#include <ModuleBase_ActionInfo.h>
+
+class QListWidget;
+class QToolButton;
+class QListWidgetItem;
+
+class XGUI_EXPORT XGUI_HistoryMenu : public QMenu
+{
+  Q_OBJECT
+ public:
+  explicit XGUI_HistoryMenu(QToolButton* theParent);
+  explicit XGUI_HistoryMenu(QAction* theParent);
+  virtual ~XGUI_HistoryMenu();
+
+ signals:
+  void actionSelected(int);
+
+ public slots:
+  void setHistory(const QList<ActionInfo>&);
+
+ protected slots:
+  void setStackSelectedTo(QListWidgetItem *);
+  void onItemPressed(QListWidgetItem *);
+  void initMenu();
+
+ private:
+  QListWidget* myHistoryList;
+};
+
+#endif /* XGUI_OPERATIONSSTACKPOPUP_H_ */
index 69cc9c616c58b32feda738a6194f444cfacd5a26..243e98eafff67da3f6ace9ef8a0520d03c33e68b 100644 (file)
@@ -80,7 +80,7 @@ void XGUI_DataTree::commitData(QWidget* theEditor)
     QString aRes = aEditor->text();
     ObjectPtr aFeature = mySelectedData.first();
     SessionPtr aMgr = ModelAPI_Session::get();
-    aMgr->startOperation();
+    aMgr->startOperation("RenameFeature");
     aFeature->data()->setName(qPrintable(aRes));
     aMgr->finishOperation();
   }
index 10d663b4f039298a03402a2bdbb72b7437f84912..c06bd3e5223e2b0f8293b9147eb78f092d41aab2 100644 (file)
@@ -8,6 +8,8 @@
 #include <QString>
 #include <QStringList>
 
+#include <ModuleBase_ActionInfo.h>
+
 class QMainWindow;
 class ModuleBase_IViewer;
 
@@ -32,6 +34,9 @@ class XGUI_EXPORT XGUI_SalomeConnector
                               const QString& theTitle, const QString& theTip, const QIcon& theIcon,
                               const QKeySequence& theKeys, bool isCheckable) = 0;
 
+  virtual QAction* addFeature(const QString& theWBName,
+                              const ActionInfo& theInfo) = 0;
+
   //! Creates a command in Edit menu of SALOME desktop
   //! \param theId - an id of the feature
   //! \param theTitle - a menu item string
index a4a55cca5f10ed96c784d60b5f06ca19b55dbb28..ec70496183d244a53a2d071c79e4f23bf9f9f130 100644 (file)
@@ -263,3 +263,14 @@ void XGUI_ViewerProxy::update()
 {
   myWorkshop->displayer()->updateViewer();
 }
+
+//***************************************
+bool XGUI_ViewerProxy::canDragByMouse() const
+{
+  if (myWorkshop->isSalomeMode()) {
+    ModuleBase_IViewer* aViewer = myWorkshop->salomeConnector()->viewer();
+    return aViewer->canDragByMouse();
+  } else {
+    return true;
+  }
+}
\ No newline at end of file
index e0894ff0f06724e4d6403102350e2925343a97b4..acd152d23685994672d71022f89b639febba10ce 100644 (file)
@@ -69,6 +69,10 @@ Q_OBJECT
   /// Update current viewer
   virtual void update();
 
+  /// Method returns True if the viewer can process editing objects 
+  /// by mouse drugging. If this is impossible thet it has to return False.
+  virtual bool canDragByMouse() const;
+
 private slots:
   void onTryCloseView(AppElements_ViewWindow*);
   void onDeleteView(AppElements_ViewWindow*);
index 90ea84c529973b4c67511b62738ac74cbc61c7c8..84d3d6a10354f5d6d8f7117f623b79823ff0cfb5 100644 (file)
@@ -16,6 +16,7 @@
 #include "XGUI_ContextMenuMgr.h"
 #include "XGUI_ModuleConnector.h"
 #include <XGUI_QtEvents.h>
+#include <XGUI_HistoryMenu.h>
 
 #include <AppElements_Workbench.h>
 #include <AppElements_Viewer.h>
@@ -68,6 +69,9 @@
 #include <QLayout>
 #include <QThread>
 #include <QObject>
+#include <QMenu>
+#include <QToolButton>
+#include <QAction>
 
 #ifdef _DEBUG
 #include <QDebug>
@@ -222,10 +226,14 @@ void XGUI_Workshop::initMenu()
                                                          QIcon(":pictures/undo.png"),
                                                          QKeySequence::Undo, false, "MEN_DESK_EDIT");
     connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onUndo()));
+    addHistoryMenu(aAction, SIGNAL(updateUndoHistory(const QList<ActionInfo>&)), SLOT(onUndo(int)));
+
     aAction = salomeConnector()->addDesktopCommand("REDO_CMD", tr("Redo"), tr("Redo last command"),
                                                 QIcon(":pictures/redo.png"), QKeySequence::Redo,
                                                 false, "MEN_DESK_EDIT");
     connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRedo()));
+    addHistoryMenu(aAction, SIGNAL(updateRedoHistory(const QList<ActionInfo>&)), SLOT(onRedo(int)));
+
     salomeConnector()->addDesktopMenuSeparator("MEN_DESK_EDIT");
     aAction = salomeConnector()->addDesktopCommand("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"),
                                                 QIcon(":pictures/rebuild.png"), QKeySequence(),
@@ -256,13 +264,23 @@ void XGUI_Workshop::initMenu()
   aCommand->connectTo(this, SLOT(onSave()));
   //aCommand->disable();
 
-  aCommand = aGroup->addFeature("UNDO_CMD", tr("Undo"), tr("Undo last command"),
+  QString aUndoId = "UNDO_CMD";
+  aCommand = aGroup->addFeature(aUndoId, tr("Undo"), tr("Undo last command"),
                                 QIcon(":pictures/undo.png"), QKeySequence::Undo);
   aCommand->connectTo(this, SLOT(onUndo()));
+  QToolButton* aUndoButton = qobject_cast<QToolButton*>(aGroup->widget(aUndoId));
+  addHistoryMenu(aUndoButton,
+                 SIGNAL(updateUndoHistory(const QList<ActionInfo>&)),
+                 SLOT(onUndo(int)));
 
-  aCommand = aGroup->addFeature("REDO_CMD", tr("Redo"), tr("Redo last command"),
+  QString aRedoId = "REDO_CMD";
+  aCommand = aGroup->addFeature(aRedoId, tr("Redo"), tr("Redo last command"),
                                 QIcon(":pictures/redo.png"), QKeySequence::Redo);
   aCommand->connectTo(this, SLOT(onRedo()));
+  QToolButton* aRedoButton = qobject_cast<QToolButton*>(aGroup->widget(aRedoId));
+  addHistoryMenu(aRedoButton,
+                 SIGNAL(updateRedoHistory(const QList<ActionInfo>&)),
+                 SLOT(onRedo(int)));
 
   aCommand = aGroup->addFeature("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"),
     QIcon(":pictures/rebuild.png"), QKeySequence());
@@ -672,28 +690,24 @@ void XGUI_Workshop::addFeature(const std::shared_ptr<Config_FeatureMessage>& the
 #endif
     return;
   }
+  ActionInfo aFeatureInfo;
+  aFeatureInfo.initFrom(theMessage);
   // Remember features icons
-  myIcons[QString::fromStdString(theMessage->id())] = QString::fromStdString(theMessage->icon());
+  myIcons[QString::fromStdString(theMessage->id())] = aFeatureInfo.iconFile;
 
-  //Find or create Workbench
   QString aWchName = QString::fromStdString(theMessage->workbenchId());
-  QString aNestedFeatures = QString::fromStdString(theMessage->nestedFeatures());
-  bool isUsePropPanel = theMessage->isUseInput();
-  QString aFeatureId = QString::fromStdString(theMessage->id());
+  QStringList aNestedFeatures =
+      QString::fromStdString(theMessage->nestedFeatures()).split(" ", QString::SkipEmptyParts);
+  QString aDocKind = QString::fromStdString(theMessage->documentKind());
   if (isSalomeMode()) {
-    QAction* aAction = salomeConnector()->addFeature(aWchName, aFeatureId,
-                                                     QString::fromStdString(theMessage->text()),
-                                                     QString::fromStdString(theMessage->tooltip()),
-                                                     QIcon(theMessage->icon().c_str()),
-                                                     QKeySequence(),
-                                                     isUsePropPanel);
-    salomeConnector()->setNestedActions(aFeatureId, aNestedFeatures.split(" ", QString::SkipEmptyParts));
-    salomeConnector()->setDocumentKind(aFeatureId, QString::fromStdString(theMessage->documentKind()));
+    QAction* aAction = salomeConnector()->addFeature(aWchName, aFeatureInfo);
+    salomeConnector()->setNestedActions(aFeatureInfo.id, aNestedFeatures);
+    salomeConnector()->setDocumentKind(aFeatureInfo.id, aDocKind);
 
     myActionsMgr->addCommand(aAction);
     myModule->actionCreated(aAction);
   } else {
-
+    //Find or create Workbench
     AppElements_MainMenu* aMenuBar = myMainWindow->menuObject();
     AppElements_Workbench* aPage = aMenuBar->findWorkbench(aWchName);
     if (!aPage) {
@@ -705,19 +719,14 @@ void XGUI_Workshop::addFeature(const std::shared_ptr<Config_FeatureMessage>& the
     if (!aGroup) {
       aGroup = aPage->addGroup(aGroupName);
     }
-    QString aDocKind = QString::fromStdString(theMessage->documentKind());
     // Check if hotkey sequence is already defined:
-    QKeySequence aHotKey = myActionsMgr->registerShortcut(
-        QString::fromStdString(theMessage->keysequence()));
+    QKeySequence aHotKey = myActionsMgr->registerShortcut(aFeatureInfo.shortcut);
+    if(aHotKey != aFeatureInfo.shortcut) {
+      aFeatureInfo.shortcut = aHotKey;
+    }
     // Create feature...
-    AppElements_Command* aCommand = aGroup->addFeature(aFeatureId,
-                                                QString::fromStdString(theMessage->text()),
-                                                QString::fromStdString(theMessage->tooltip()),
-                                                QIcon(theMessage->icon().c_str()),
-                                                aDocKind,
-                                                aHotKey,
-                                                isUsePropPanel);
-    aCommand->setNestedCommands(aNestedFeatures.split(" ", QString::SkipEmptyParts));
+    AppElements_Command* aCommand = aGroup->addFeature(aFeatureInfo, aDocKind);
+    aCommand->setNestedCommands(aNestedFeatures);
     myActionsMgr->addCommand(aCommand);
     myModule->actionCreated(aCommand);
   }
@@ -894,24 +903,28 @@ bool XGUI_Workshop::onSaveAs()
 }
 
 //******************************************************
-void XGUI_Workshop::onUndo()
+void XGUI_Workshop::onUndo(int theTimes)
 {
   objectBrowser()->treeView()->setCurrentIndex(QModelIndex());
   SessionPtr aMgr = ModelAPI_Session::get();
   if (aMgr->isOperation())
     operationMgr()->onAbortOperation();
-  aMgr->undo();
+  for (int i = 0; i < theTimes; ++i) {
+    aMgr->undo();
+  }
   updateCommandStatus();
 }
 
 //******************************************************
-void XGUI_Workshop::onRedo()
+void XGUI_Workshop::onRedo(int theTimes)
 {
   objectBrowser()->treeView()->setCurrentIndex(QModelIndex());
   SessionPtr aMgr = ModelAPI_Session::get();
   if (aMgr->isOperation())
     operationMgr()->onAbortOperation();
-  aMgr->redo();
+  for (int i = 0; i < theTimes; ++i) {
+    aMgr->redo();
+  }
   updateCommandStatus();
 }
 
@@ -921,7 +934,7 @@ void XGUI_Workshop::onRebuild()
   SessionPtr aMgr = ModelAPI_Session::get();
   bool aWasOperation = aMgr->isOperation(); // keep this value
   if (!aWasOperation) {
-    aMgr->startOperation();
+    aMgr->startOperation("Rebuild");
   }
   static const Events_ID aRebuildEvent = Events_Loop::loop()->eventByName("Rebuild");
   Events_Loop::loop()->send(std::shared_ptr<Events_Message>(
@@ -1050,6 +1063,9 @@ void XGUI_Workshop::updateCommandStatus()
     }
     aUndoCmd->setEnabled(aMgr->canUndo() && !aMgr->isOperation());
     aRedoCmd->setEnabled(aMgr->canRedo() && !aMgr->isOperation());
+
+    updateHistory();
+
   } else {
     foreach(QAction* aCmd, aCommands) {
       QString aId = aCmd->data().toString();
@@ -1065,6 +1081,33 @@ void XGUI_Workshop::updateCommandStatus()
   emit commandStatusUpdated();
 }
 
+void XGUI_Workshop::updateHistory()
+{
+  std::list<std::string> aUndoList = ModelAPI_Session::get()->undoList();
+  std::list<std::string>::iterator it = aUndoList.begin();
+  QList<ActionInfo> aUndoRes;
+  for ( ; it != aUndoList.end(); it++) {
+    QString anId = QString::fromStdString(*it);
+    QIcon aIcon;
+    if (myIcons.contains(anId))
+      aIcon = QIcon(myIcons[anId]);
+    aUndoRes << ActionInfo(aIcon, anId);
+  }
+  emit updateUndoHistory(aUndoRes);
+
+  std::list<std::string> aRedoList = ModelAPI_Session::get()->redoList();
+  it = aRedoList.begin();
+  QList<ActionInfo> aRedoRes;
+  for ( ; it != aRedoList.end(); it++) {
+    QString anId = QString::fromStdString(*it);
+    QIcon aIcon;
+    if (myIcons.contains(anId))
+      aIcon = QIcon(myIcons[anId]);
+    aRedoRes << ActionInfo(aIcon, anId);
+  }
+  emit updateRedoHistory(aUndoRes);
+}
+
 //******************************************************
 QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent)
 {
@@ -1302,7 +1345,7 @@ These features will be deleted also. Would you like to continue?")).arg(aNames),
   }
 
   SessionPtr aMgr = ModelAPI_Session::get();
-  aMgr->startOperation();
+  aMgr->startOperation("DeleteObjects");
   std::set<FeaturePtr>::const_iterator anIt = aRefFeatures.begin(),
                                        aLast = aRefFeatures.end();
   for (; anIt != aLast; anIt++) {
@@ -1429,3 +1472,20 @@ void XGUI_Workshop::displayObject(ObjectPtr theObj)
   } else 
     myDisplayer->display(theObj, false);
 }
+
+void XGUI_Workshop::addHistoryMenu(QObject* theObject, const char* theSignal, const char* theSlot)
+{
+  XGUI_HistoryMenu* aMenu = NULL;
+  if (isSalomeMode()) {
+    QAction* anAction = qobject_cast<QAction*>(theObject);
+    if (!anAction)
+      return;
+    aMenu = new XGUI_HistoryMenu(anAction);
+  } else {
+    QToolButton* aButton =  qobject_cast<QToolButton*>(theObject);
+    aMenu = new XGUI_HistoryMenu(aButton);
+  }
+  connect(this, theSignal, aMenu, SLOT(setHistory(const QList<ActionInfo>&)));
+  connect(aMenu, SIGNAL(actionSelected(int)), this, theSlot);
+
+}
index 80aa6d2f8358d405b313f1a48f18a8b770feae1f..1cf400d0f89a52956cf8e9d05516641cfea30c80 100644 (file)
@@ -10,6 +10,8 @@
 #include <ModelAPI_Document.h>
 #include <ModelAPI_Feature.h>
 
+#include <ModuleBase_ActionInfo.h>
+
 #include <QObject>
 #include <QMap>
 #include <QKeySequence>
@@ -215,10 +217,16 @@ signals:
   //! the application is started
   void applicationStarted();
 
+  void updateUndoHistory(const QList<ActionInfo>&);
+  void updateRedoHistory(const QList<ActionInfo>&);
+
  public slots:
    /// Update of commands status
   void updateCommandStatus();
 
+  /// update history list (undo/redo commands)
+  void updateHistory();
+
   /// Create a new dokument
   void onNew();
 
@@ -235,10 +243,10 @@ signals:
   void onExit();
 
   /// Undo last command
-  void onUndo();
+  void onUndo(int times = 1);
 
   /// Redo previous command
-  void onRedo();
+  void onRedo(int times = 1);
 
   /// Rebuild data tree
   void onRebuild();
@@ -377,6 +385,13 @@ signals:
   /// Displaus object and fit all viewer if the object is first (update viewer will not be called)
   void displayObject(ObjectPtr theObj);
 
+  //! Extends undo/redo toolbutton's with history menu
+  //! \param theObject - in the OpenParts it is a QToolButton by itself,
+  //! in salome mode - QAction that creates a button.
+  //! \param theSignal - void "updateUndoHistory" or "updateRedoHistory" SIGNAL;
+  //! \param theSlot - onUndo(int) or onRedo(int) SLOT
+  void addHistoryMenu(QObject* theObject, const char* theSignal, const char* theSlot);
+
 private:
   AppElements_MainWindow* myMainWindow;
   ModuleBase_IModule* myModule;