Salome HOME
Merge branch 'master' into V9_3_BR
[modules/shaper.git] / src / XGUI / XGUI_Workshop.cpp
old mode 100755 (executable)
new mode 100644 (file)
index ea60b2a..b42e4d0
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 //
 // You should have received a copy of the GNU Lesser General Public
 // License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
 #include "XGUI_Workshop.h"
@@ -51,6 +50,7 @@
 #include <XGUI_QtEvents.h>
 #include <XGUI_DataModel.h>
 #include <XGUI_InspectionPanel.h>
+#include <XGUI_CompressFiles.h>
 
 #ifndef HAVE_SALOME
 #include <AppElements_Button.h>
 #include <QAction>
 #include <QDesktopWidget>
 #include <QProcess>
+#include <QDesktopServices>
 
 #include <iterator>
 
@@ -168,10 +169,20 @@ QString XGUI_Workshop::MOVE_TO_END_COMMAND = QObject::tr("Move to the end");
 //#define DEBUG_FEATURE_NAME
 //#define DEBUG_CLEAN_HISTORY
 
+#ifdef HAVE_SALOME
+static QString MyFilter(QObject::tr("SHAPER files (*.shaper *.opp)"));
+static QString MyFilter2(QObject::tr("SHAPER files (*.shaper)"));
+static QString MyExtension(".shaper");
+#else
+static QString MyFilter(QObject::tr("OpenParts files (*.opp);;All files (*.*)"));
+static QString MyFilter2(QObject::tr("OpenParts files (*.opp)"));
+static QString MyExtension(".opp");
+#endif
+
+
 //******************************************************
 XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
     : QObject(),
-      myCurrentDir(QString()),
       myModule(NULL),
       mySalomeConnector(theConnector),
       myPropertyPanel(0),
@@ -186,7 +197,7 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
   myOperationMgr = new XGUI_OperationMgr(this, 0);
   ModuleBase_IWorkshop* aWorkshop = moduleConnector();
   // Has to be defined first in order to get errors and messages from other components
-  myEventsListener = new XGUI_WorkshopListener(aWorkshop);
+  myEventsListener = new XGUI_WorkshopListener(this);
   mySelectionActivate = new XGUI_SelectionActivate(aWorkshop);
 
   SUIT_ResourceMgr* aResMgr = ModuleBase_Preferences::resourceMgr();
@@ -298,6 +309,9 @@ XGUI_Workshop::~XGUI_Workshop(void)
 
   delete myDisplayer;
   delete myDataModelXMLReader;
+  delete mySelectionActivate;
+  delete myMenuMgr;
+  clearTemporaryDir();
 }
 
 //******************************************************
@@ -412,7 +426,7 @@ void XGUI_Workshop::initMenu()
                                                         QKeySequence::Undo, false,
                                                         "MEN_DESK_EDIT");
   QString aToolBarTitle = tr( "INF_DESK_TOOLBAR_STANDARD" );
-  salomeConnector()->addActionInToolbar( aAction,aToolBarTitle  );
+  salomeConnector()->addActionInToolbar( aAction,aToolBarTitle );
 
   connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onUndo()));
   addHistoryMenu(aAction, SIGNAL(updateUndoHistory(const QList<ActionInfo>&)), SLOT(onUndo(int)));
@@ -427,6 +441,18 @@ void XGUI_Workshop::initMenu()
 
   salomeConnector()->addDesktopMenuSeparator("MEN_DESK_EDIT");
 
+  //aAction = salomeConnector()->addDesktopCommand("AUTOCOMPUTE_CMD", tr("Auto rebuild"),
+  //                                            tr("Blocks immediate apply of modifications"),
+  //                                            QIcon(":pictures/autoapply.png"), QKeySequence(),
+  //                                            false, "MEN_DESK_EDIT");
+  //salomeConnector()->addActionInToolbar( aAction, aToolBarTitle );
+
+  //connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onAutoApply()));
+
+  salomeConnector()->addDesktopMenuSeparator("MEN_DESK_EDIT");
+
+
+  // Add commands to a file menu
   aAction = salomeConnector()->addDesktopCommand("SAVEAS_CMD", tr("Export native..."),
                                              tr("Export the current document into a native file"),
                                               QIcon(), QKeySequence(),
@@ -477,6 +503,13 @@ void XGUI_Workshop::initMenu()
                                 QIcon(":pictures/open.png"), QKeySequence::Open);
   aCommand->connectTo(this, SLOT(onOpen()));
 
+
+  aCommand = aGroup->addFeature("AUTOCOMPUTE_CMD", tr("Auto rebuild"),
+                                tr("Blocks immediate apply of modifications"),
+                                QIcon(":pictures/autoapply_start.png"), QKeySequence());
+  aCommand->setChecked(ModelAPI_Session::get()->isAutoUpdateBlocked());
+  aCommand->connectTo(this, SLOT(onAutoApply()));
+
   aCommand = aGroup->addFeature("PREF_CMD", tr("Preferences"), tr("Edit preferences"),
                                 QIcon(":pictures/preferences.png"), QKeySequence::Preferences);
   aCommand->connectTo(this, SLOT(onPreferences()));
@@ -567,30 +600,35 @@ void XGUI_Workshop::onHelpActionClicked()
   if (anOperationMgr) {
     ModuleBase_Operation* aOperation = anOperationMgr->currentOperation();
     if (aOperation) {
-      QString aDocDir;
-      const QChar aSep = QDir::separator();
-      QString platform;
-      SUIT_ResourceMgr* aResMgr = ModuleBase_Preferences::resourceMgr();
-#ifdef WIN32
-      platform = "winapplication";
-#else
-      platform = "application";
-#endif
-      QString aBrowserName = aResMgr->stringValue("ExternalBrowser", platform);
+      QString aHelpPage = aOperation->helpFileName();
+      if (!aHelpPage.isEmpty()) {
+        QString aDocDir;
+        const QChar aSep = QDir::separator();
+//        QString platform;
+//        SUIT_ResourceMgr* aResMgr = ModuleBase_Preferences::resourceMgr();
+//#ifdef WIN32
+//        platform = "winapplication";
+//#else
+//        platform = "application";
+//#endif
+//        QString aBrowserName = aResMgr->stringValue("ExternalBrowser", platform);
 
 #ifdef HAVE_SALOME
-      QString aDir(getenv("SHAPER_ROOT_DIR"));
-      if (!aDir.isEmpty()) {
-        aDocDir = aDir + aSep + "share" + aSep + "doc" + aSep +
-          "salome" + aSep + "gui" + aSep + "SHAPER";
-      }
+        QString aDir(getenv("SHAPER_ROOT_DIR"));
+        if (!aDir.isEmpty()) {
+          aDocDir = aDir + aSep + "share" + aSep + "doc" + aSep +
+            "salome" + aSep + "gui" + aSep + "SHAPER";
+        }
 #else
-      QString aDir(getenv("OPENPARTS_ROOT_DIR"));
-      aDocDir = aDir + aSep + "doc";
+        QString aDir(getenv("OPENPARTS_ROOT_DIR"));
+        aDocDir = aDir + aSep + "doc" + aSep + "gui";
 #endif
-      QStringList aParams;
-      aParams << aDocDir + aSep + aOperation->helpFileName();
-      QProcess::startDetached(aBrowserName, aParams);
+        QString aFileName = aDocDir + aSep + aHelpPage;
+        if (QFile::exists(aFileName)) {
+          QUrl aUrl = QUrl::fromLocalFile(aFileName);
+          QDesktopServices::openUrl(aUrl);
+        }
+      }
     }
   }
 }
@@ -888,25 +926,26 @@ void XGUI_Workshop::onOpen()
     } else if (anAnswer == QMessageBox::Cancel) {
       return;
     }
-    myCurrentDir = "";
+    myCurrentFile = QString();
   }
 
   //show file dialog, check if readable and open
-  QString aDirectory = QFileDialog::getExistingDirectory(desktop(), tr("Select directory"));
-  openDirectory(aDirectory);
+  QString aFile = QFileDialog::getOpenFileName(desktop(), tr("Open file"), QString(), MyFilter);
+  if (!aFile.isNull())
+    openFile(aFile);
 }
 
 //******************************************************
-void XGUI_Workshop::openDirectory(const QString& theDirectory)
+void XGUI_Workshop::openFile(const QString& theDirectory)
 {
-  myCurrentDir = theDirectory;
-  if (myCurrentDir.isEmpty())
+  myCurrentFile = theDirectory;
+  if (myCurrentFile.isEmpty())
     return;
 
-  QFileInfo aFileInfo(myCurrentDir);
+  QFileInfo aFileInfo(myCurrentFile);
   if (!aFileInfo.exists() || !aFileInfo.isReadable()) {
     QMessageBox::critical(desktop(), tr("Warning"), tr("Unable to open the file."));
-    myCurrentDir = "";
+    myCurrentFile = QString();
     return;
   }
 
@@ -914,7 +953,12 @@ void XGUI_Workshop::openDirectory(const QString& theDirectory)
   module()->closeDocument();
   SessionPtr aSession = ModelAPI_Session::get();
   aSession->closeAll();
-  aSession->load(myCurrentDir.toLatin1().constData());
+
+  clearTemporaryDir();
+  if (!XGUI_CompressFiles::uncompress(myCurrentFile, myTmpDir.path()))
+    return;
+
+  aSession->load(myTmpDir.path().toLatin1().constData());
   myObjectBrowser->rebuildDataTree();
 
   // Open first level of data tree
@@ -925,7 +969,7 @@ void XGUI_Workshop::openDirectory(const QString& theDirectory)
 
   updateCommandStatus();
 #ifndef HAVE_SALOME
-  myMainWindow->setCurrentDir(myCurrentDir, true);
+  myMainWindow->setCurrentDir(myCurrentFile, true);
 #endif
 
 #ifdef _DEBUG
@@ -1021,16 +1065,31 @@ bool XGUI_Workshop::onSave()
 {
   if(!myOperationMgr->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage))
     return false;
-  if (myCurrentDir.isEmpty()) {
+  if (myCurrentFile.isEmpty()) {
     return onSaveAs();
   }
+  SessionPtr aMgr = ModelAPI_Session::get();
+  if (aMgr->isAutoUpdateBlocked())
+    aMgr->blockAutoUpdate(false);
+
   std::list<std::string> aFiles;
-  saveDocument(myCurrentDir, aFiles);
-  updateCommandStatus();
+  // issue #2899: create a temporary directory, save and then remove it
+#ifdef HAVE_SALOME
+  std::string aTmpDir = XGUI_Tools::getTmpDirByEnv("SALOME_TMP_DIR");
+#else
+  std::string aTmpDir = XGUI_Tools::getTmpDirByEnv("");
+#endif
+  saveDocument(QString(aTmpDir.c_str()), aFiles);
+  bool aResult = XGUI_CompressFiles::compress(myCurrentFile, aFiles);
+  XGUI_Tools::removeTemporaryFiles(aTmpDir, aFiles);
+
+  if (aResult) {
+    updateCommandStatus();
 #ifndef HAVE_SALOME
     myMainWindow->setModifiedState(false);
 #endif
-  return true;
+  }
+  return aResult;
 }
 
 //******************************************************
@@ -1038,34 +1097,17 @@ bool XGUI_Workshop::onSaveAs()
 {
   if(!myOperationMgr->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage))
     return false;
-  QFileDialog dialog(desktop());
-  dialog.setWindowTitle(tr("Select directory to save files..."));
-  dialog.setFileMode(QFileDialog::Directory);
-  dialog.setFilter(QDir::AllDirs);
-  dialog.setOptions(QFileDialog::HideNameFilterDetails | QFileDialog::ShowDirsOnly);
-  dialog.setViewMode(QFileDialog::Detail);
-
-  if (!dialog.exec()) {
-    return false;
-  }
-
-  QString aTempDir = dialog.selectedFiles().first();
-  QDir aDir(aTempDir);
-  if (aDir.exists() && !aDir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).isEmpty()) {
-    int answer = QMessageBox::question(
-        desktop(),
-        // Title of the dialog which asks user if he wants to save study
-        // in existing non-empty folder
-        tr("Save"),
-        tr("The directory already contains some files, save anyway?"),
-        QMessageBox::Save | QMessageBox::Cancel);
-    if (answer == QMessageBox::Cancel) {
-      return false;
+  myCurrentFile = QFileDialog::getSaveFileName(desktop(), tr("Select name to save file..."),
+    QString(), MyFilter2);
+  if (!myCurrentFile.isNull()) {
+    if (!myCurrentFile.endsWith(MyExtension)) {
+      myCurrentFile += MyExtension;
     }
   }
-  myCurrentDir = aTempDir;
+  else
+    return false;
 #ifndef HAVE_SALOME
-    myMainWindow->setCurrentDir(myCurrentDir, false);
+    myMainWindow->setCurrentDir(myCurrentFile, false);
     myMainWindow->setModifiedState(false);
 #endif
   return onSave();
@@ -1195,7 +1237,7 @@ ModuleBase_IModule* XGUI_Workshop::loadModule(const QString& theModule)
   CREATE_FUNC crtInst = 0;
 
 #ifdef WIN32
-  HINSTANCE modLib = ::LoadLibrary((LPTSTR) qPrintable(libName));
+  HINSTANCE modLib = ::LoadLibraryA(qPrintable(libName));
   if (!modLib) {
     LPVOID lpMsgBuf;
     ::FormatMessage(
@@ -1296,6 +1338,11 @@ void XGUI_Workshop::updateCommandStatus()
         else
           aCmd->setEnabled(myModule->canRedo());
       }
+      else if (aId == "AUTOCOMPUTE_CMD") {
+        aCmd->setIcon(aMgr->isAutoUpdateBlocked() ?
+          QIcon(":pictures/autoapply_stop.png") :
+          QIcon(":pictures/autoapply_start.png"));
+      }
       else
         // Enable all commands
         aCmd->setEnabled(true);
@@ -1388,6 +1435,8 @@ void XGUI_Workshop::createDockWidgets()
     Qt::RightDockWidgetArea);
   aDesktop->addDockWidget(Qt::RightDockWidgetArea, myInspectionPanel);
 
+  myInspectionPanel->hide();
+
   aDesktop->addDockWidget(
 #ifdef HAVE_SALOME
     Qt::RightDockWidgetArea,
@@ -1621,7 +1670,7 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
 #ifdef DEBUG_WITH_MESSAGE_REPORT
         MyTCommunicator->RegisterPlugin("TKMessageView");
 #endif
-        MyTCommunicator->RegisterPlugin("SMBrowser"); // custom plugin to view ModelAPI
+        //MyTCommunicator->RegisterPlugin("SMBrowser"); // custom plugin to view ModelAPI
         //MyTCommunicator->RegisterPlugin("TKSMBrowser"); // custom plugin to view ModelAPI
 
         MyTCommunicator->Init(aParameters);
@@ -2173,6 +2222,9 @@ void setColor(ResultPtr theResult, const std::vector<int>& theColor)
     aColorAttr->setValue(1, theColor[1]);
     aColorAttr->setValue(2, theColor[2]);
   }
+  static const Events_ID kRedisplayEvent =
+    Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  ModelAPI_EventCreator::get()->sendUpdated(theResult, kRedisplayEvent);
 }
 
 //**************************************************************
@@ -2251,6 +2303,9 @@ void setDeflection(ResultPtr theResult, const double theDeflection)
   AttributeDoublePtr aDeflectionAttr = theResult->data()->real(ModelAPI_Result::DEFLECTION_ID());
   if (aDeflectionAttr.get() != NULL)
     aDeflectionAttr->setValue(theDeflection);
+  static const Events_ID kRedisplayEvent =
+    Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  ModelAPI_EventCreator::get()->sendUpdated(theResult, kRedisplayEvent);
 }
 
 //**************************************************************
@@ -2262,6 +2317,9 @@ void setTransparency(ResultPtr theResult, double theTransparency)
   AttributeDoublePtr anAttribute = theResult->data()->real(ModelAPI_Result::TRANSPARENCY_ID());
   if (anAttribute.get() != NULL)
     anAttribute->setValue(theTransparency);
+  static const Events_ID kRedisplayEvent =
+    Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  ModelAPI_EventCreator::get()->sendUpdated(theResult, kRedisplayEvent);
 }
 
 //**************************************************************
@@ -2458,11 +2516,14 @@ void XGUI_Workshop::showObjects(const QObjectPtrList& theList, bool isVisible)
 //**************************************************************
 void XGUI_Workshop::showOnlyObjects(const QObjectPtrList& theList)
 {
+  QObjectPtrList aSrcList = theList;
   // Hide all displayed objects
   QObjectPtrList aList = myDisplayer->displayedObjects();
   foreach (ObjectPtr aObj, aList) {
-    if (module()->canEraseObject(aObj))
+    if ((!aSrcList.contains(aObj)) && (module()->canEraseObject(aObj)))
       aObj->setDisplayed(false);
+    else
+      aSrcList.removeAll(aObj);
   }
   //Do not use eraseAll if you didn't send Redisplay event:
   //all objects are erased from viewer, but considered as displayed in displayer
@@ -2474,7 +2535,7 @@ void XGUI_Workshop::showOnlyObjects(const QObjectPtrList& theList)
 #endif
 
   std::set<ObjectPtr> anObjects;
-  foreach (ObjectPtr aObj, theList) {
+  foreach (ObjectPtr aObj, aSrcList) {
     anObjects.insert(aObj);
   }
 
@@ -2482,7 +2543,7 @@ void XGUI_Workshop::showOnlyObjects(const QObjectPtrList& theList)
     return;
 
   // Show only objects from the list
-  foreach (ObjectPtr aObj, theList) {
+  foreach (ObjectPtr aObj, aSrcList) {
     aObj->setDisplayed(true);
   }
   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
@@ -2647,12 +2708,28 @@ void XGUI_Workshop::synchronizeGroupInViewer(const DocumentPtr& theDoc,
       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
       if (aRes.get() && (!aRes->shape().get() || aRes->shape()->isNull()))
         continue;
-      myDisplayer->display(aObj, false);
+      ResultBodyPtr aResBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aObj);
+      if (aResBody.get())
+        synchronizeResultTree(aResBody, false);
+      else
+        myDisplayer->display(aObj, false);
     }
   }
   if (theUpdateViewer)
     myDisplayer->updateViewer();
 }
+
+void XGUI_Workshop::synchronizeResultTree(const ResultBodyPtr& theRes, bool theUpdateViewer)
+{
+  if (theRes->numberOfSubs() > 0)
+    for (int i = 0; i < theRes->numberOfSubs(); i++) {
+      ResultBodyPtr aRes = theRes->subResult(i);
+      if (aRes.get())
+        synchronizeResultTree(aRes, theUpdateViewer);
+    }
+  else
+    myDisplayer->display(theRes, theUpdateViewer);
+}
 #endif
 
 //******************************************************
@@ -2677,9 +2754,7 @@ void XGUI_Workshop::highlightResults(const QObjectPtrList& theObjects)
   }
   if (aSelList.count() > theObjects.count()) {
     // if something was found
-    bool aBlocked = objectBrowser()->blockSignals(true);
     objectBrowser()->setObjectsSelected(aSelList);
-    objectBrowser()->blockSignals(aBlocked);
     objectBrowser()->ensureVisible(aNewSel.first());
   }
   if (aHasHidden)
@@ -2706,9 +2781,7 @@ void XGUI_Workshop::highlightFeature(const QObjectPtrList& theObjects)
   }
   if (aSelList.count() > theObjects.count()) {
     // if something was found
-    bool aBlocked = objectBrowser()->blockSignals(true);
     objectBrowser()->setObjectsSelected(aSelList);
-    objectBrowser()->blockSignals(aBlocked);
     objectBrowser()->ensureVisible(aNewSel.first());
   }
 }
@@ -2785,3 +2858,46 @@ void XGUI_Workshop::moveOutFolder(bool isBefore)
 
   updateCommandStatus();
 }
+
+void XGUI_Workshop::onAutoApply()
+{
+  SessionPtr aMgr = ModelAPI_Session::get();
+  bool isBlocked = aMgr->isAutoUpdateBlocked();
+  aMgr->blockAutoUpdate(!isBlocked);
+}
+
+void XGUI_Workshop::updateAutoComputeState()
+{
+  SessionPtr aMgr = ModelAPI_Session::get();
+  bool isComputeBlocked = aMgr->isAutoUpdateBlocked();
+#ifdef HAVE_SALOME
+//  QAction* aUpdateCmd;
+//  QList<QAction*> aCommands = mySalomeConnector->commandList();
+//  foreach(QAction* aCmd, aCommands) {
+//    if (aCmd->data().toString() == "AUTOCOMPUTE_CMD") {
+//      aUpdateCmd = aCmd;
+//      break;
+//    }
+//  }
+//  aUpdateCmd->setIcon(isComputeBlocked? QIcon(":pictures/autoapply_stop.png") :
+//    QIcon(":pictures/autoapply_start.png"));
+#else
+  AppElements_MainMenu* aMenuBar = myMainWindow->menuObject();
+  AppElements_Command* aUpdateCmd = aMenuBar->feature("AUTOCOMPUTE_CMD");
+  aUpdateCmd->button()->setIcon(isComputeBlocked? QIcon(":pictures/autoapply_stop.png") :
+    QIcon(":pictures/autoapply_start.png"));
+#endif
+}
+
+
+void XGUI_Workshop::clearTemporaryDir()
+{
+  QDir aDir(myTmpDir.path());
+  if (!aDir.isEmpty()) {
+    QStringList aEntries;
+    aDir.entryList(aEntries);
+    foreach(QString aFile, aEntries) {
+      aDir.remove(aFile);
+    }
+  }
+}
\ No newline at end of file