]> SALOME platform Git repositories - modules/multipr.git/commitdiff
Salome HOME
Merge BR_MULTIPR_INDUS and BR_MULTIPR_EVOLUTION
authorjfa <jfa@opencascade.com>
Thu, 20 Sep 2007 11:41:55 +0000 (11:41 +0000)
committerjfa <jfa@opencascade.com>
Thu, 20 Sep 2007 11:41:55 +0000 (11:41 +0000)
idl/MULTIPR.idl
src/MULTIPR/MULTIPR_i.cxx
src/MULTIPR/MULTIPR_i.hxx
src/MULTIPR/Makefile.in
src/MULTIPRGUI/MULTIPR_GUI.cxx
src/MULTIPRGUI/MULTIPR_GUI.h
src/MULTIPRGUI/MULTIPR_GUI_Dlg.cxx
src/MULTIPRGUI/MULTIPR_GUI_Dlg.h

index 6c54f489eeb6afbeef796e713650c597c5c59df8..8a2a2eb4f14c61ff2041bf5e14c1d0809906a12a 100644 (file)
@@ -35,13 +35,18 @@ typedef sequence<string> string_array;
 // Interface of the %MULTIPR component used to manage partition/decimation
 //*************************************************************************
 
-interface MULTIPR_Obj
+interface MULTIPR_Obj : SALOME::GenericObj
 {
 
        //---------------------------------------------------------------------
        // Basic accessors/mutators
        //--------------------------------------------------------------------
        
+    /*!
+     * Reset the object.
+     */
+    void    reset();
+    
        /*!
         * Return true iff this obj represents a valid sequential MED file.
         */
@@ -86,15 +91,21 @@ interface MULTIPR_Obj
        /*!
         * Return the list of fields contained in the current mesh of the associated MED file.
         */
-       string_array getFields()
+       string_array getFields(in string pPartList)
                raises (SALOME::SALOME_Exception);
        
        /*!
         * Return the number of iterations for a given field.
         */
-       long getTimeStamps(in string fieldName)
+       long getTimeStamps(in string pPartList, in string fieldName)
                raises (SALOME::SALOME_Exception);
 
+    /*!
+     * Get the minimum and maximum value of a part's field.
+     */
+    void getFieldMinMax(in string pPartName, in string pFieldName, inout float pMin, inout float pMax)
+        raises (SALOME::SALOME_Exception);
+        
        /*!
         * Return the name of all partitions.
         * Assume this object encapsulates a distributed MED file.
@@ -114,7 +125,8 @@ interface MULTIPR_Obj
        //--------------------------------------------------------------------
        
        /*!
-        * Create a distributed MED file (v2.3) by extracting all the groups from the current mesh of the current MED sequential MED file.
+        * Create a distributed MED file (v2.3) by extracting all the groups from the 
+     * current mesh of the current MED sequential MED file.
         * Assume:
         * - the file is in MED format and can be read using MED file v2.3.
         * - the file is sequential (not a distributed MED).
@@ -126,7 +138,8 @@ interface MULTIPR_Obj
                raises (SALOME::SALOME_Exception);
        
        /*! 
-        * Create a distributed MED file (V2.3) by splitting a group of a MED file previously created by partitionneDomaine.
+        * Create a distributed MED file (V2.3) by splitting a group of a MED file 
+     * previously created by partitionneDomaine.
         * Assume:
         * - the file is a distributed MED file, previously created by partitionneDomaine()
         *   (=> each part only contain 1 mesh, TETRA10 elements only)
@@ -134,7 +147,7 @@ interface MULTIPR_Obj
         * - partitionner METIS=0 or SCOTCH=1
         * \return the name of each part.
         */
-       string_array partitionneGrain(
+       string_array partitionneGroupe(
                in string partName, 
                in long   nbParts, 
                in long   partitionner)
@@ -143,7 +156,8 @@ interface MULTIPR_Obj
        /*!
         * Create 3 resolutions of the given part of a distributed MED file (V2.3).
         * Assume:
-        * - the file is a distributed MED file, previously created by partitionneDomaine() or partitionneGrain()
+        * - the file is a distributed MED file, previously created by 
+     *   partitionneDomaine() or partitionneGrain()
         *   (=> each part only contain 1 mesh, TETRA10 elements only)
         */
        string_array decimePartition(
@@ -151,9 +165,7 @@ interface MULTIPR_Obj
                in string fieldName,
                in long   fieldIt,
                in string filterName,
-               in double tmed,
-               in double tlow,
-               in double radius)
+               in string filterParams)
                raises (SALOME::SALOME_Exception);
 
        /*!
@@ -170,12 +182,20 @@ interface MULTIPR_Obj
        
        /*!
         * Remove all the parts starting with the given prefix from the distributed MED file.
-        * Example: if prefixPartName="PART_4" => remove "PART_4" and all sub-parts "PART_4_*", but not "PART41".
+        * Example: if prefixPartName="PART_4" => remove "PART_4" and all sub-parts "PART_4_*", 
+     * but not "PART41".
         * Assume this object encapsulates a distributed MED file.
         */
        void removeParts(in string prefixPartName)
                raises (SALOME::SALOME_Exception);
        
+       /*!
+        * Get mesh statistics.
+        */
+       string getMEDInfo(
+               in string partName)
+               raises (SALOME::SALOME_Exception);
+               
        //---------------------------------------------------------------------
        // i/o
        //--------------------------------------------------------------------
@@ -186,6 +206,17 @@ interface MULTIPR_Obj
        void save(in string path)
                raises (SALOME::SALOME_Exception);
 
+    /*!
+    * Check save progress.
+    * \return current save progress in percents.
+    */
+    long getSaveProgress();
+
+    /*!
+    * Reset save progress to zero.
+    */
+    void resetSaveProgress();
+
 }; // interface MULTIPR_Obj
 
 
@@ -193,7 +224,7 @@ interface MULTIPR_Obj
 // Interface of the %MULTIPR component; used to create MULTIPR_Obj object 
 // and to define high level API.
 //*************************************************************************
-interface MULTIPR_Gen : Engines::Component
+interface MULTIPR_Gen : Engines::Component, SALOMEDS::Driver
 {
        /*!
         * Return the version of the MULTIPR library.
@@ -207,7 +238,8 @@ interface MULTIPR_Gen : Engines::Component
        //------------------------------------------------------------------------      
 
        /*!         
-        * Create a distributed MED file (v2.3) by extracting all the groups from the mesh of a sequential MED file.
+        * Create a distributed MED file (v2.3) by extracting all the groups from the 
+     * mesh of a sequential MED file.
         * High level function.
         */
        void partitionneDomaine(
@@ -216,10 +248,11 @@ interface MULTIPR_Gen : Engines::Component
                raises (SALOME::SALOME_Exception);
 
        /*!         
-        * Create a distributed MED file (V2.3) by splitting a group of a MED file previously created by partitionneDomaine().
+        * Create a distributed MED file (V2.3) by splitting a group of a MED file 
+     * previously created by partitionneDomaine().
         * High level function.
         */
-       void partitionneGrain(
+       void partitionneGroupe(
                in string medFilename, 
                in string partName, 
                in long   nbParts, 
@@ -236,10 +269,7 @@ interface MULTIPR_Gen : Engines::Component
                in string fieldName,
                in long   fieldIt,
                in string filterName,
-               in double tmed,
-               in double tlow,
-               in double radius,
-               in long   boxing)
+               in string filterParams)
                raises (SALOME::SALOME_Exception);
 
        //------------------------------------------------------------------------
@@ -253,6 +283,22 @@ interface MULTIPR_Gen : Engines::Component
        MULTIPR_Obj getObject(in string medFilename)
                raises (SALOME::SALOME_Exception);
 
+    //------------------------------------------------------------------------
+    // Engine API
+    // Methods to correctly serve Persistence and Dump Python.
+    //------------------------------------------------------------------------
+
+    /*!
+     * Set the current study
+     */
+    void SetCurrentStudy (in SALOMEDS::Study theStudy);
+
+    /*!
+     * Get the current study
+     */
+    SALOMEDS::Study GetCurrentStudy();
+
+        
 }; // interface MULTIPR_Gen
  
   
index 126f14a48d1bc7d57614b328c0cee06ebd37a1b3..7e2b7db45edf2d7ce39259fad0b888d6a8a28228 100644 (file)
  * \brief   see MULTIPR_i.hxx
  *
  * \author  Olivier LE ROUX - CS, Virtual Reality Dpt
- * 
+ *
  * \date    01/2007
  */
+
 
 //*****************************************************************************
 // Includes section
 //*****************************************************************************
+
 using namespace std;
 
 #include "MULTIPR_i.hxx"
 #include "utilities.h"
 
 #include <string>
+#include <sstream>
 
 #include "MULTIPR_API.hxx"
 #include "MULTIPR_Exceptions.hxx"
+#include "MULTIPR_Utils.hxx"
+
+#include <SALOMEDS_Tool.hxx>
+
+#include CORBA_CLIENT_HEADER(SALOMEDS)
+#include CORBA_CLIENT_HEADER(SALOMEDS_Attributes)
+
+#ifdef _DEBUG_
+static int MYDEBUG = 1;
+#else
+static int MYDEBUG = 0;
+#endif
+
+// Dump Python utilities
+namespace MULTIPR
+{
+  class TPythonDump
+  {
+    std::ostringstream myStream;
+    static size_t myCounter;
+    //MULTIPR_ORB::MULTIPR_Gen_ptr myEngine;
+    MULTIPR_Gen_i* myEngine;
+
+  public:
+    //TPythonDump (MULTIPR_ORB::MULTIPR_Gen_ptr theEngine);
+    TPythonDump (MULTIPR_Gen_i* theEngine);
+    virtual ~TPythonDump();
+
+    TPythonDump& operator<< (long int theArg);
+    TPythonDump& operator<< (int theArg);
+    TPythonDump& operator<< (double theArg);
+    TPythonDump& operator<< (float theArg);
+    TPythonDump& operator<< (const void* theArg);
+    TPythonDump& operator<< (const char* theArg);
+
+    TPythonDump& operator<< (SALOMEDS::SObject_ptr theArg);
+    TPythonDump& operator<< (CORBA::Object_ptr theArg);
+
+    TPythonDump& operator<< (MULTIPR_ORB::MULTIPR_Gen_ptr theArg);
+    TPythonDump& operator<< (MULTIPR_ORB::MULTIPR_Obj_ptr theArg);
+
+    TPythonDump& operator<< (MULTIPR_Gen_i* theArg);
+    TPythonDump& operator<< (MULTIPR_Obj_i* theArg);
+
+    static char* MULTIPRGenName() { return "mpr_gen"; }
+    static char* MULTIPRObjName() { return "mpr_obj"; }
+  };
+
+  size_t TPythonDump::myCounter = 0;
+
+  //TPythonDump::TPythonDump (MULTIPR_ORB::MULTIPR_Gen_ptr theEngine)
+  TPythonDump::TPythonDump (MULTIPR_Gen_i* theEngine)
+  {
+    ++myCounter;
+    //myEngine = MULTIPR_ORB::MULTIPR_Gen::_duplicate(theEngine);
+    myEngine = theEngine;
+  }
+
+  TPythonDump::~TPythonDump()
+  {
+    if (--myCounter == 0)
+    {
+      SALOMEDS::Study_ptr aStudy = myEngine->GetCurrentStudy();
+      int aStudyID = -1;
+      if (!aStudy->_is_nil()) aStudyID = aStudy->StudyId();
+
+      std::string aString = myStream.str();
+      myEngine->AddToPythonScript(aStudyID, aString);
+      //if(MYDEBUG) MESSAGE(" *DP* " << aString.c_str());
+    }
+  }
+
+  TPythonDump& TPythonDump::operator<< (long int theArg)
+  {
+    myStream << theArg;
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (int theArg)
+  {
+    myStream << theArg;
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (double theArg)
+  {
+    myStream << theArg;
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (float theArg)
+  {
+    myStream << theArg;
+    return *this;
+  }
 
+  TPythonDump& TPythonDump::operator<< (const void* theArg)
+  {
+    myStream << theArg;
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (const char* theArg)
+  {
+    if (theArg)
+      myStream << theArg;
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (SALOMEDS::SObject_ptr aSObject)
+  {
+    if (aSObject->_is_nil())
+      myStream << "None";
+    else
+      myStream << "theStudy.FindObjectID(\"" << aSObject->GetID() << "\")";
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (CORBA::Object_ptr theArg)
+  {
+    if (CORBA::is_nil(theArg))
+      myStream << "None";
+    else
+      myStream << theArg;
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (MULTIPR_ORB::MULTIPR_Gen_ptr theArg)
+  {
+    myStream << MULTIPRGenName();
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (MULTIPR_ORB::MULTIPR_Obj_ptr theArg)
+  {
+    myStream << MULTIPRObjName();
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (MULTIPR_Gen_i* theArg)
+  {
+    myStream << MULTIPRGenName();
+    return *this;
+  }
+
+  TPythonDump& TPythonDump::operator<< (MULTIPR_Obj_i* theArg)
+  {
+    myStream << MULTIPRObjName();
+    return *this;
+  }
+}
 
 //*****************************************************************************
 // Class MULTIPR_Gen_i implementation
@@ -34,8 +185,8 @@ using namespace std;
 MULTIPR_Gen_i::MULTIPR_Gen_i(
     CORBA::ORB_ptr orb,
     PortableServer::POA_ptr poa,
-    PortableServer::ObjectId* contId, 
-    const char* instanceName, 
+    PortableServer::ObjectId* contId,
+    const char* instanceName,
     const char* interfaceName) :
     Engines_Component_i(orb, poa, contId, instanceName, interfaceName)
 {
@@ -62,7 +213,7 @@ char* MULTIPR_Gen_i::getVersion()
 
 
 void MULTIPR_Gen_i::partitionneDomaine(
-    const char* medFilename, 
+    const char* medFilename,
     const char* meshName)
     throw (SALOME::SALOME_Exception)
 {
@@ -78,16 +229,16 @@ void MULTIPR_Gen_i::partitionneDomaine(
 }
 
 
-void MULTIPR_Gen_i::partitionneGrain(
-    const char* medFilename, 
-    const char* partName, 
-    CORBA::Long nbParts, 
+void MULTIPR_Gen_i::partitionneGroupe(
+    const char* medFilename,
+    const char* partName,
+    CORBA::Long nbParts,
     CORBA::Long partitionner)
     throw (SALOME::SALOME_Exception)
 {
     try
     {
-        multipr::partitionneGrain(
+        multipr::partitionneGroupe(
             medFilename,
             partName,
             nbParts,
@@ -96,23 +247,21 @@ void MULTIPR_Gen_i::partitionneGrain(
     catch (multipr::RuntimeException& e)
     {
         e.dump(cout);
-        THROW_SALOME_CORBA_EXCEPTION("partitionneGrain() failed", SALOME::INTERNAL_ERROR);
+        THROW_SALOME_CORBA_EXCEPTION("partitionneGroupe() failed", SALOME::INTERNAL_ERROR);
     }
 }
 
 
 void MULTIPR_Gen_i::decimePartition(
-    const char*   medFilename, 
-    const char*   partName, 
+    const char*   medFilename,
+    const char*   partName,
     const char*   fieldName,
     CORBA::Long   fieldIt,
     const char*   filterName,
-    CORBA::Double tmed,
-    CORBA::Double tlow,
-    CORBA::Double radius,
-    CORBA::Long   boxing)
+    const char*   filterParams)
     throw (SALOME::SALOME_Exception)
 {
+
     /*
     // debug
     cout << "File  : " << medFilename << endl;
@@ -126,19 +275,16 @@ void MULTIPR_Gen_i::decimePartition(
     cout << "Box   : " << boxing      << endl;
     cout << endl;
     */
-    
+
     try
     {
         multipr::decimePartition(
-            medFilename, 
-            partName, 
+            medFilename,
+            partName,
             fieldName,
             fieldIt,
             filterName,
-            tmed,
-            tlow,
-            radius,
-            boxing);
+            filterParams);
     }
     catch (multipr::RuntimeException& e)
     {
@@ -155,21 +301,48 @@ void MULTIPR_Gen_i::decimePartition(
 MULTIPR_ORB::MULTIPR_Obj_ptr MULTIPR_Gen_i::getObject(const char* medFilename)
     throw (SALOME::SALOME_Exception)
 {
-    MULTIPR_Obj_i* obj = new MULTIPR_Obj_i(medFilename);
+    MULTIPR_Obj_i* obj = new MULTIPR_Obj_i(_poa, medFilename);
+    obj->setEngine(this);
+
+    // Dump Python
+    MULTIPR::TPythonDump(this) << obj << " = " << this << ".getObject(\"" << medFilename << "\")";
+
     return obj->POA_MULTIPR_ORB::MULTIPR_Obj::_this();
 }
 
 
-MULTIPR_Obj_i::MULTIPR_Obj_i(const char* medFilename)
+void MULTIPR_Gen_i::ObjModified (MULTIPR_ORB::MULTIPR_Obj_ptr theObj)
+{
+  // Mark current study as modified, if theObj is published in it
+  if (!CORBA::is_nil(myCurrentStudy) && !CORBA::is_nil(theObj))
+  {
+    SALOMEDS::SObject_var aSO = myCurrentStudy->FindObjectIOR(_orb->object_to_string(theObj));
+    // if published
+    if (!CORBA::is_nil(aSO))
+      myCurrentStudy->Modified();
+  }
+}
+
+
+MULTIPR_Obj_i::MULTIPR_Obj_i(PortableServer::POA_ptr thePOA,
+                              const char* medFilename,
+                              bool isPersistence,
+                              bool isMultifile)
     throw (SALOME::SALOME_Exception)
+    : SALOME::GenericObj_i(thePOA),
+      mBoxing(100),
+      _engine(NULL),
+      mIsTmp(isPersistence && !isMultifile)
 {
     mObj    = new multipr::Obj();
-    mBoxing = 100;
-    
+
     try
     {
         cout << "Load " << medFilename << endl;
-        mObj->create(medFilename);
+        if (isPersistence)
+          mObj->restorePersistent(medFilename);
+        else
+          mObj->create(medFilename);
         cout << endl;
     }
     catch (multipr::RuntimeException& e)
@@ -186,18 +359,37 @@ MULTIPR_Obj_i::~MULTIPR_Obj_i()
 {
     if (mObj != NULL)
     {
-        cout << "MULTIPR: Destructor: remove mObj" << endl;
+        if (mIsTmp)
+        {
+            // Remove temporary files, created during study loading, together with directory
+            std::string strFile = mObj->getMEDFilename();
+            std::string strPath = multipr::getPath(strFile.c_str());
+#ifdef WNT
+            //std::string cmd_rm ("del /F \"");
+#else
+            std::string cmd_rm ("rm -rf \"");
+#endif
+            cmd_rm += strPath + "\"";
+            system(cmd_rm.c_str());
+        }
+
+        if(MYDEBUG) MESSAGE("MULTIPR_Obj_i: Destructor: remove mObj");
         delete mObj;
         mObj = NULL;
     }
 }
 
+void MULTIPR_Obj_i::reset()
+        throw (SALOME::SALOME_Exception)
+{
+    mObj->reset();
+}
 
 CORBA::Boolean MULTIPR_Obj_i::isValidSequentialMEDFile()
         throw (SALOME::SALOME_Exception)
 {
     if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+
     return mObj->isValidSequentialMEDFile();
 }
 
@@ -206,7 +398,7 @@ CORBA::Boolean MULTIPR_Obj_i::isValidDistributedMEDFile()
     throw (SALOME::SALOME_Exception)
 {
     if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+
     return mObj->isValidDistributedMEDFile();
 }
 
@@ -215,7 +407,7 @@ char* MULTIPR_Obj_i::getFilename()
         throw (SALOME::SALOME_Exception)
 {
     if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+
     return CORBA::string_dup(mObj->getMEDFilename().c_str());
 }
 
@@ -224,7 +416,7 @@ char* MULTIPR_Obj_i::getSeqFilename()
         throw (SALOME::SALOME_Exception)
 {
     if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+
     return CORBA::string_dup(mObj->getSequentialMEDFilename().c_str());
 }
 
@@ -233,18 +425,32 @@ void MULTIPR_Obj_i::setMesh(const char* meshName)
         throw (SALOME::SALOME_Exception)
 {
     if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+
     try
     {
         mObj->setMesh(meshName);
-        
-        cout << "Set mesh OK" << endl << endl;
+
+        // Dump Python
+        MULTIPR::TPythonDump(_engine) << this << ".setMesh(\"" << meshName << "\")";
+
+        if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::setMesh - OK");
     }
     catch (multipr::RuntimeException& e)
     {
         e.dump(cout);
         THROW_SALOME_CORBA_EXCEPTION("Unable to set mesh", SALOME::INTERNAL_ERROR);
     }
+
+  // Mark current study as modified, if theObj is published in it
+  _engine->ObjModified(_this());
+}
+
+std::string MULTIPR_Obj_i::getMeshName() const
+        throw (SALOME::SALOME_Exception)
+{
+  if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+  return mObj->getMeshName();
 }
 
 
@@ -253,23 +459,29 @@ void MULTIPR_Obj_i::setBoxing(CORBA::Long pBoxing)
 {
     if (mBoxing < 0) THROW_SALOME_CORBA_EXCEPTION("Invalid boxing parameter; should be >= 1", SALOME::INTERNAL_ERROR);
     if (mBoxing > 200) THROW_SALOME_CORBA_EXCEPTION("Invalid boxing parameter; should be <= 200", SALOME::INTERNAL_ERROR);
-    
+
     mBoxing = pBoxing;
+
+    // Dump Python
+    MULTIPR::TPythonDump(_engine) << this << ".setBoxing(" << pBoxing << ")";
+
+  // Mark current study as modified, if theObj is published in it
+  _engine->ObjModified(_this());
 }
 
 
-MULTIPR_ORB::string_array* MULTIPR_Obj_i::getMeshes() 
+MULTIPR_ORB::string_array* MULTIPR_Obj_i::getMeshes()
     throw (SALOME::SALOME_Exception)
 {
     if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+
     MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
-    
+
     try
     {
         std::vector<std::string> listMeshes = mObj->getMeshes();
         mySeq->length(listMeshes.size());
-        
+
         for (size_t i = 0 ; i < listMeshes.size() ; i++)
         {
             mySeq[i] = CORBA::string_dup(listMeshes[i].c_str());
@@ -280,23 +492,23 @@ MULTIPR_ORB::string_array* MULTIPR_Obj_i::getMeshes()
         e.dump(cout);
         THROW_SALOME_CORBA_EXCEPTION("Unable to get meshes", SALOME::INTERNAL_ERROR);
     }
-    
+
     return mySeq._retn();
 }
 
 
-MULTIPR_ORB::string_array* MULTIPR_Obj_i::getFields(
+MULTIPR_ORB::string_array* MULTIPR_Obj_i::getFields(const char* pPartList)
     throw (SALOME::SALOME_Exception)
 {
     if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+
     MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
-    
+
     try
     {
-        std::vector<std::string> listFields = mObj->getFields();
+        std::vector<std::string> listFields = mObj->getFields(pPartList);
         mySeq->length(listFields.size());
-        
+
         for (size_t i = 0 ; i < listFields.size() ; i++)
         {
             mySeq[i] = CORBA::string_dup(listFields[i].c_str());
@@ -307,19 +519,19 @@ MULTIPR_ORB::string_array* MULTIPR_Obj_i::getFields()
         e.dump(cout);
         THROW_SALOME_CORBA_EXCEPTION("Unable to get fields", SALOME::INTERNAL_ERROR);
     }
-    
+
     return mySeq._retn();
 }
 
 
-CORBA::Long MULTIPR_Obj_i::getTimeStamps(const char* fieldName)
+CORBA::Long MULTIPR_Obj_i::getTimeStamps(const char* pPartList, const char* fieldName)
     throw (SALOME::SALOME_Exception)
 {
     if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+
     try
     {
-        return mObj->getTimeStamps(fieldName);
+        return mObj->getTimeStamps(pPartList, fieldName);
     }
     catch (multipr::RuntimeException& e)
     {
@@ -328,19 +540,34 @@ CORBA::Long MULTIPR_Obj_i::getTimeStamps(const char* fieldName)
     }
 }
 
+void MULTIPR_Obj_i::getFieldMinMax(const char* pPartName, const char* pFieldName,
+                                   CORBA::Float& pMin, CORBA::Float& pMax)
+    throw (SALOME::SALOME_Exception)
+{
+    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+    try
+    {
+        mObj->getFieldMinMax(pPartName, pFieldName, pMin, pMax);
+    }
+    catch (multipr::RuntimeException& e)
+    {
+        e.dump(cout);
+        THROW_SALOME_CORBA_EXCEPTION("Unable to get parts", SALOME::INTERNAL_ERROR);
+    }
+}
 
 MULTIPR_ORB::string_array* MULTIPR_Obj_i::getParts()
     throw (SALOME::SALOME_Exception)
 {
     if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+
     MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
-    
+
     try
     {
         std::vector<std::string> listParts = mObj->getParts();
         mySeq->length(listParts.size());
-        
+
         for (size_t i = 0 ; i < listParts.size() ; i++)
         {
             mySeq[i] = CORBA::string_dup(listParts[i].c_str());
@@ -351,7 +578,7 @@ MULTIPR_ORB::string_array* MULTIPR_Obj_i::getParts()
         e.dump(cout);
         THROW_SALOME_CORBA_EXCEPTION("Unable to get parts", SALOME::INTERNAL_ERROR);
     }
-    
+
     return mySeq._retn();
 }
 
@@ -360,7 +587,7 @@ char* MULTIPR_Obj_i::getPartInfo(const char* pPartName)
     throw (SALOME::SALOME_Exception)
 {
     if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+
     return CORBA::string_dup(mObj->getPartInfo(pPartName).c_str());
 }
 
@@ -369,60 +596,79 @@ MULTIPR_ORB::string_array* MULTIPR_Obj_i::partitionneDomaine()
     throw (SALOME::SALOME_Exception)
 {
     if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+
     MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
-    
+
     try
     {
         std::vector<std::string> listParts = mObj->partitionneDomaine();
         mySeq->length(listParts.size());
-        
+
         for (size_t i = 0 ; i < listParts.size() ; i++)
         {
             mySeq[i] = CORBA::string_dup(listParts[i].c_str());
         }
+
+        // Dump Python
+        MULTIPR::TPythonDump(_engine) << "parts = " << this << ".partitionneDomaine()";
     }
     catch (multipr::RuntimeException& e)
     {
         e.dump(cout);
         THROW_SALOME_CORBA_EXCEPTION("Unable to partition mesh", SALOME::INTERNAL_ERROR);
     }
-    
-    return mySeq._retn();
+
+  // Mark current study as modified, if theObj is published in it
+  _engine->ObjModified(_this());
+
+  return mySeq._retn();
 }
 
 
-MULTIPR_ORB::string_array* MULTIPR_Obj_i::partitionneGrain(
-        const char* pPartName, 
-        CORBA::Long pNbParts, 
+MULTIPR_ORB::string_array* MULTIPR_Obj_i::partitionneGroupe(
+        const char* pPartName,
+        CORBA::Long pNbParts,
         CORBA::Long pPartitionner)
         throw (SALOME::SALOME_Exception)
 {
     if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+
     MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
-    
+
     try
     {
-        std::vector<std::string> listParts = mObj->partitionneGrain(
+        std::vector<std::string> listParts = mObj->partitionneGroupe(
             pPartName,
             pNbParts,
             pPartitionner);
-            
+
         mySeq->length(listParts.size());
-        
+
         for (size_t i = 0 ; i < listParts.size() ; i++)
         {
             mySeq[i] = CORBA::string_dup(listParts[i].c_str());
         }
+
+        // Dump Python
+        MULTIPR::TPythonDump(_engine) << "new_parts = " << this << ".partitionneGroupe(\""
+        << pPartName << "\", " << pNbParts << ", " << pPartitionner << ")";
     }
-    catch (multipr::RuntimeException& e)
+    catch (std::exception& exc)
     {
-        e.dump(cout);
-        THROW_SALOME_CORBA_EXCEPTION("Unable to partition group", SALOME::INTERNAL_ERROR);
+        THROW_SALOME_CORBA_EXCEPTION(exc.what(), SALOME::INTERNAL_ERROR);
     }
-    
-    return mySeq._retn();
+    catch (multipr::RuntimeException& exc)
+    {
+        std::ostringstream aStream;
+        exc.dump(aStream);
+        aStream<<ends;
+        THROW_SALOME_CORBA_EXCEPTION(aStream.str().c_str(), SALOME::INTERNAL_ERROR);
+    }
+
+  // Mark current study as modified, if theObj is published in it
+  _engine->ObjModified(_this());
+
+  return mySeq._retn();
 }
 
 
@@ -431,15 +677,15 @@ MULTIPR_ORB::string_array* MULTIPR_Obj_i::decimePartition(
         const char*   pFieldName,
         CORBA::Long   pFieldIt,
         const char*   pFilterName,
-        CORBA::Double pTmed,
-        CORBA::Double pTlow,
-        CORBA::Double pRadius)
+        const char*   pFilterParams)
         throw (SALOME::SALOME_Exception)
 {
-    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+  if (mObj == NULL)
+  {
+    THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+  }
     MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
-    
+
     try
     {
         std::vector<std::string> listParts = mObj->decimePartition(
@@ -447,38 +693,90 @@ MULTIPR_ORB::string_array* MULTIPR_Obj_i::decimePartition(
             pFieldName,
             pFieldIt,
             pFilterName,
-            pTmed,
-            pTlow,
-            pRadius,
-            mBoxing);
-        
+            pFilterParams);
         mySeq->length(listParts.size());
-        
         for (size_t i = 0 ; i < listParts.size() ; i++)
         {
             mySeq[i] = CORBA::string_dup(listParts[i].c_str());
         }
+
+        // Dump Python
+        MULTIPR::TPythonDump(_engine) << "parts = " << this << ".decimePartition(\""
+                                      << pPartName << "\", \"" << pFieldName << "\", "
+                                      << pFieldIt << ", \"" << pFilterName << "\", \""
+                                      << pFilterParams << "\")";
     }
     catch (multipr::RuntimeException& e)
     {
         e.dump(cout);
         THROW_SALOME_CORBA_EXCEPTION("Unable to decimate", SALOME::INTERNAL_ERROR);
     }
-    
-    return mySeq._retn();
+
+  // Mark current study as modified, if theObj is published in it
+  _engine->ObjModified(_this());
+
+  return mySeq._retn();
 }
 
+/*
+MULTIPR_ORB::string_array* MULTIPR_Obj_i::decimatePart(
+        const char*   pPartName,
+        const char*   pFieldName,
+        CORBA::Long   pFieldIt,
+        const char*   pFilterName,
+        const char*   pFilterParams)
+        throw (SALOME::SALOME_Exception)
+{
+  if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+  MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array();
+
+  try
+  {
+    std::list<std::string> emptyParts;
+    mObj->decimePartition(pPartName,
+                          pFieldName,
+                          pFieldIt,
+                          pFilterName,
+                          pFilterParams,
+                          emptyParts);
+
+    mySeq->length(emptyParts.size());
+    std::list<std::string>::const_iterator it = emptyParts.begin(), end = emptyParts.end();
+    for (size_t i = 0; it != end; it++, i++)
+    {
+      mySeq[i] = CORBA::string_dup((*it).c_str());
+    }
+
+    // Dump Python
+    MULTIPR::TPythonDump(_engine) << "empty_parts = " << this << ".decimatePart(\""
+                                  << pPartName << "\", \"" << pFieldName << "\", "
+                                  << pFieldIt << ", \"" << pFilterName << "\", \""
+                                  << pFilterParams << "\")";
+  }
+  catch (multipr::RuntimeException& e)
+  {
+    e.dump(cout);
+    THROW_SALOME_CORBA_EXCEPTION("Unable to decimate", SALOME::INTERNAL_ERROR);
+  }
+
+  // Mark current study as modified, if theObj is published in it
+  _engine->ObjModified(_this());
+
+  return mySeq._retn();
+}
+*/
 
 char* MULTIPR_Obj_i::evalDecimationParams(
-    const char* pPartName, 
-    const char* pFieldName, 
-    CORBA::Long pFieldIt, 
+    const char* pPartName,
+    const char* pFieldName,
+    CORBA::Long pFieldIt,
     const char* pFilterName,
     const char* pFilterParams)
     throw (SALOME::SALOME_Exception)
 {
     if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+
     try
     {
         string res = mObj->evalDecimationParams(
@@ -487,9 +785,13 @@ char* MULTIPR_Obj_i::evalDecimationParams(
             pFieldIt,
             pFilterName,
             pFilterParams);
-            
+
+        // Dump Python
+        MULTIPR::TPythonDump(_engine) << "dec_params = " << this << ".evalDecimationParams(\""
+                                      << pPartName << "\", \"" << pFieldName << "\", " << pFieldIt
+                                      << ", \"" << pFilterName << "\", \"" << pFilterParams
+                                      << "\") # " << res.c_str();
         return CORBA::string_dup(res.c_str());
-            
     }
     catch (multipr::RuntimeException& e)
     {
@@ -503,36 +805,902 @@ void MULTIPR_Obj_i::removeParts(const char* pPrefixPartName)
     throw (SALOME::SALOME_Exception)
 {
     if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
+
     mObj->removeParts(pPrefixPartName);
+
+    // Dump Python
+    MULTIPR::TPythonDump(_engine) << this << ".removeParts(\"" << pPrefixPartName << "\")";
+
+  // Mark current study as modified, if theObj is published in it
+  _engine->ObjModified(_this());
 }
 
+char* MULTIPR_Obj_i::getMEDInfo(const char* pPartName)
+  throw (SALOME::SALOME_Exception)
+{
+  if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+  char res[128];
+
+  mObj->getMEDInfo(res, const_cast<char*>(pPartName));
+  return CORBA::string_dup(res);
+}
 
 void MULTIPR_Obj_i::save(const char* pPath)
     throw (SALOME::SALOME_Exception)
 {
-    if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
-    
-    try
+  if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+  try
+  {
+    std::string strFile = mObj->getMEDFilename();
+
+    // Do Save
+    mObj->save(pPath);
+
+    // Remove temporary files, if needed
+    if (mIsTmp)
     {
-        mObj->save(pPath);
-        
+      mIsTmp = false;
+
+      // Remove temporary files, created during study loading, together with directory
+      std::string strPath = multipr::getPath(strFile.c_str());
+#ifdef WNT
+      //std::string cmd_rm ("del /F \"");
+#else
+      std::string cmd_rm ("rm -rf \"");
+#endif
+      cmd_rm += strPath + "\"";
+      system(cmd_rm.c_str());
     }
-    catch (multipr::RuntimeException& e)
+  }
+  catch (multipr::RuntimeException& e)
+  {
+    e.dump(cout);
+    THROW_SALOME_CORBA_EXCEPTION("Unable to save MED file", SALOME::INTERNAL_ERROR);
+  }
+
+  // Dump Python
+  MULTIPR::TPythonDump(_engine) << this << ".save(\"" << pPath << "\")";
+}
+
+CORBA::Long MULTIPR_Obj_i::getSaveProgress()
+{
+  return mObj->getProgress();
+}
+
+void MULTIPR_Obj_i::resetSaveProgress()
+{
+  mObj->resetProgress();
+}
+
+//-----------------------------------------------------------------------------
+// savePersistent and setEngine (for Persistence & Dump Python)
+//-----------------------------------------------------------------------------
+
+void MULTIPR_Obj_i::savePersistent (const char* pPath)
+    throw (SALOME::SALOME_Exception)
+{
+  if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR);
+
+  try
+  {
+    mObj->savePersistent(pPath);
+  }
+  catch (multipr::RuntimeException& e)
+  {
+    e.dump(cout);
+    THROW_SALOME_CORBA_EXCEPTION("Unable to save MED file", SALOME::INTERNAL_ERROR);
+  }
+}
+
+void MULTIPR_Obj_i::setEngine (MULTIPR_Gen_i* theEngine)
+{
+  _engine = theEngine;
+}
+
+
+//-----------------------------------------------------------------------------
+// Set/Get current study (for Persistence & Dump Python)
+//-----------------------------------------------------------------------------
+
+/*! Set current study
+ */
+void MULTIPR_Gen_i::SetCurrentStudy (SALOMEDS::Study_ptr theStudy)
+{
+  //if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::SetCurrentStudy");
+
+  // theStudy or myCurrentStudy may be nil
+  if (!CORBA::is_nil(theStudy))
+  {
+    if (CORBA::is_nil(myCurrentStudy))
     {
-        e.dump(cout);
-        THROW_SALOME_CORBA_EXCEPTION("Unable to save MED file", SALOME::INTERNAL_ERROR);
+      // move python trace of unknown study to the real study
+      int studyId = theStudy->StudyId();
+      if (myPythonScripts.find(-1) != myPythonScripts.end())
+      {
+        myPythonScripts[studyId].insert(myPythonScripts[studyId].begin(), // at
+                                        myPythonScripts[-1].begin(), // from
+                                        myPythonScripts[-1].end());  // to
+        myPythonScripts[-1].clear();
+      }
     }
+  }
+
+  myCurrentStudy = SALOMEDS::Study::_duplicate(theStudy);
 }
 
+/*! Get current study
+ */
+SALOMEDS::Study_ptr MULTIPR_Gen_i::GetCurrentStudy()
+{
+  //if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::GetCurrentStudy: study Id = " << GetCurrentStudyID());
+  return SALOMEDS::Study::_duplicate(myCurrentStudy);
+}
+
+//-----------------------------------------------------------------------------
+// SALOMEDS::Driver methods (Persistence & Dump Python)
+//-----------------------------------------------------------------------------
 
+/*! Get component data type
+ */
+char* MULTIPR_Gen_i::ComponentDataType()
+{
+  if(MYDEBUG) MESSAGE( "MULTIPR_Gen_i::ComponentDataType" );
+  return CORBA::string_dup( "MULTIPR" );
+}
+
+/*! Clears study-connected data when it is closed
+ */
+void MULTIPR_Gen_i::Close (SALOMEDS::SComponent_ptr theComponent)
+{
+  if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::Close");
+}
+
+/*! Save MULTIPR module's data
+ */
+SALOMEDS::TMPFile* MULTIPR_Gen_i::Save (SALOMEDS::SComponent_ptr theComponent,
+                                        const char*              theURL,
+                                        bool                     isMultiFile)
+{
+  INFOS( "MULTIPR_Gen_i::Save" );
+
+  if (myCurrentStudy->_is_nil() ||
+      theComponent->GetStudy()->StudyId() != myCurrentStudy->StudyId())
+    SetCurrentStudy(theComponent->GetStudy());
+
+  // Store study contents as a set of python commands
+  SavePython(myCurrentStudy);
+
+  // Study name (for tmp directory and tmp files naming)
+  std::string aStudyName;
+  if (isMultiFile)
+    aStudyName = SALOMEDS_Tool::GetNameFromPath(myCurrentStudy->URL());
+
+  // Declare a byte stream
+  SALOMEDS::TMPFile_var aStreamFile;
+
+  SALOMEDS::ChildIterator_ptr obj_it (myCurrentStudy->NewChildIterator(theComponent));
+
+  // TODO: iterate on all objects under theComponent
+  if (!obj_it->More())
+    return aStreamFile._retn();
+
+  SALOMEDS::SObject_ptr aSObj = obj_it->Value();
+  CORBA::Object_var anObj = aSObj->GetObject();
+  MULTIPR_ORB::MULTIPR_Obj_ptr obj = MULTIPR_ORB::MULTIPR_Obj::_narrow(anObj);
+  if (CORBA::is_nil(obj))
+    return aStreamFile._retn();
+
+  // Obtain a temporary directory
+  std::string tmpDir = isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir();
+
+  // Directory for MED data to be stored in a distributed MED file
+  std::string subDir  = aStudyName + "_MULTIPR_MED";
+  std::string meshDir = tmpDir + subDir;
+
+  // Create a new dir <meshDir> to save the sequential/distributed file in.
+  // Remove all the files in <meshDir> if they exist.
+#ifdef WNT
+  std::string dirSeparator = "\\";
+  //std::string cmd_mk ("mkdir /F \"");
+  //std::string cmd_rm ("del /F \"");
+#else
+  std::string dirSeparator = "/";
+  std::string cmd_mk ("mkdir \"");
+  std::string cmd_rm ("rm -rf \"");
+#endif
+  cmd_mk += meshDir + "\"";
+  cmd_rm += meshDir + dirSeparator + "\"*";
+  system(cmd_mk.c_str());
+  system(cmd_rm.c_str());
+
+  // Create a sequence of files processed
+  SALOMEDS::ListOfFileNames_var aFileSeq = new SALOMEDS::ListOfFileNames;
+
+  if (obj->isValidSequentialMEDFile())
+  {
+    std::string aFile = obj->getFilename();
+    std::string aFileName = multipr::getFilenameWithoutPath(aFile.c_str());
+
+    // Copy initial sequential MED file to <meshDir>
+#ifdef WNT
+    std::string dirSeparator = "\\";
+    //std::string cmd_cp ("copy \"");
+#else
+    std::string dirSeparator = "/";
+    std::string cmd_cp ("cp \"");
+#endif
+    cmd_cp += aFile + "\" \"" + meshDir + dirSeparator + "\"";
+    system(cmd_cp.c_str());
+
+    // Set names of temporary files
+    std::string aFileNameRel = subDir + dirSeparator + aFileName;
+    aFileSeq->length(1);
+    aFileSeq[0] = CORBA::string_dup(aFileNameRel.c_str()); // sequential MED file
+  }
+  else if (obj->isValidDistributedMEDFile())
+  {
+    // Save distributed MED file to the <meshDir>
+    PortableServer::Servant aServant = _poa->reference_to_servant(obj);
+    MULTIPR_Obj_i* objServant = dynamic_cast<MULTIPR_Obj_i*>(aServant);
+    if (!objServant)
+    {
+      // TODO: exception
+      return aStreamFile._retn();
+    }
+    objServant->savePersistent(meshDir.c_str());
+
+    // ASCII master file name
+    std::string aMaitreFile = obj->getFilename();
+    std::string aMaitreFileName = multipr::getFilenameWithoutPath(aMaitreFile.c_str());
+    // just after partitionneDomaine() the state is MULTIPR_OBJ_STATE_DIS_MEM,
+    // and getFilename() returns name of sequential file
+    // (because distributed file is not created on disk yet). So, build the name:
+    if (aMaitreFile == obj->getSeqFilename())
+    {
+      std::string strExtension (".med");
+      std::string strNamePrefix =
+        multipr::removeExtension(aMaitreFileName.c_str(), strExtension.c_str());
+      aMaitreFileName = strNamePrefix + "_grains_maitre" + strExtension;
+    }
+    //std::string aMaitreFileName = SALOMEDS_Tool::GetNameFromPath(aMaitreFile);
+    std::string aMaitreFileNameRel = subDir + dirSeparator + aMaitreFileName;
+
+    // Set names of temporary files
+    MULTIPR_ORB::string_array* listParts = obj->getParts();
+    unsigned int nbParts = listParts->length();
+    aFileSeq->length(nbParts + 1);
+
+    char   lMeshName[256];
+    int    lId;
+    char   lPartName[256];
+    char   lPath[256];
+    char   lMEDFileName[256];
+
+    for (unsigned int i = 0; i < nbParts; i++) // each part MED files
+    {
+      const char* strPartName = (*listParts)[i];
+      char* strPartInfo = obj->getPartInfo(strPartName);
+
+      // parse infos
+      int ret = sscanf(strPartInfo, "%s %d %s %s %s",
+                       lMeshName, &lId, lPartName, lPath, lMEDFileName);
+
+      if (ret != 5)
+      {
+        // TODO: exception
+        return aStreamFile._retn();
+      }
+
+      std::string aPartFileName = multipr::getFilenameWithoutPath(lMEDFileName);
+      std::string aPartFileNameRel = subDir + dirSeparator + aPartFileName;
+
+      aFileSeq[i] = CORBA::string_dup(aPartFileNameRel.c_str()); // part MED file
+    }
+    aFileSeq[nbParts] = CORBA::string_dup(aMaitreFileNameRel.c_str()); // ASCII master file
+  }
+  else
+  {
+    // TODO: exception
+    return aStreamFile._retn();
+  }
+
+  // Convert temporary files to stream
+  aStreamFile = SALOMEDS_Tool::PutFilesToStream(tmpDir, aFileSeq.in(), isMultiFile);
+
+  // Remove temporary files and directory
+  if (!isMultiFile)
+  {
+    //SALOMEDS_Tool::RemoveTemporaryFiles(tmpDir, aFileSeq.in(), true);
+    // remove with shell command, because SALOMEDS_Tool::RemoveTemporaryFiles does not remove sub-folders
+#ifdef WNT
+    //std::string cmd_rm ("del /F \"");
+#else
+    std::string cmd_rm ("rm -rf \"");
+#endif
+    cmd_rm += tmpDir + "\"";
+    system(cmd_rm.c_str());
+  }
+
+  INFOS("MULTIPR_Gen_i::Save() completed");
+  return aStreamFile._retn();
+}
+
+/*! Save MULTIPR module's data in ASCII format
+ */
+SALOMEDS::TMPFile* MULTIPR_Gen_i::SaveASCII (SALOMEDS::SComponent_ptr theComponent,
+                                             const char*              theURL,
+                                             bool                     isMultiFile)
+{
+  if(MYDEBUG) MESSAGE( "MULTIPR_Gen_i::SaveASCII" );
+  SALOMEDS::TMPFile_var aStreamFile = Save(theComponent, theURL, isMultiFile);
+  return aStreamFile._retn();
+}
+
+/*! Load MULTIPR module's data
+ */
+bool MULTIPR_Gen_i::Load (SALOMEDS::SComponent_ptr theComponent,
+                          const SALOMEDS::TMPFile& theStream,
+                          const char*              theURL,
+                          bool                     isMultiFile)
+{
+  INFOS("MULTIPR_Gen_i::Load");
+
+  if (myCurrentStudy->_is_nil() ||
+      theComponent->GetStudy()->StudyId() != myCurrentStudy->StudyId())
+    SetCurrentStudy(theComponent->GetStudy());
+
+  // Get temporary files location
+  std::string tmpDir = isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir();
+
+  INFOS("THE URL++++++++++++++");
+  INFOS(theURL);
+  INFOS("THE TMP PATH+++++++++");
+  INFOS(tmpDir.c_str());
+
+  // For LocalPersistentIDToIOR():
+  myTmpDir = tmpDir;
+
+  // Create a new dir <meshDir> to restore the distributed/sequential
+  // MED file in. It is needed only if not multifile, because in
+  // multifile study all required files are already on disk.
+  if (!isMultiFile)
+  {
+    std::string subDir  = "_MULTIPR_MED";
+    std::string meshDir = tmpDir + subDir;
+#ifdef WNT
+    //std::string cmd_mk ("mkdir /F \"");
+#else
+    std::string cmd_mk ("mkdir \"");
+#endif
+    cmd_mk += meshDir + "\"";
+    system(cmd_mk.c_str());
+  }
+
+  // Convert the stream into sequence of files to process
+  SALOMEDS::ListOfFileNames_var aFileSeq =
+    SALOMEDS_Tool::PutStreamToFiles(theStream, tmpDir.c_str(), isMultiFile);
+
+  //TCollection_AsciiString aStudyName;
+  //if (isMultiFile)
+  //  aStudyName = ((char*)SALOMEDS_Tool::GetNameFromPath(myCurrentStudy->URL()).c_str());
+
+  // Set names of "temporary" files
+  //TCollection_AsciiString filename = tmpDir + aStudyName + TCollection_AsciiString( "_MULTIPR.hdf" );
+  //TCollection_AsciiString meshfile = tmpDir + aStudyName + TCollection_AsciiString( "_MULTIPR_Mesh.med" );
+
+  // Remove temporary files created from the stream
+  //if (!isMultiFile)
+  //  SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
+
+  INFOS("MULTIPR_Gen_i::Load completed");
+  return true;
+}
+
+/*! Load MULTIPR module's data in ASCII format
+ */
+bool MULTIPR_Gen_i::LoadASCII (SALOMEDS::SComponent_ptr theComponent,
+                               const SALOMEDS::TMPFile& theStream,
+                               const char*              theURL,
+                               bool                     isMultiFile)
+{
+  if(MYDEBUG) MESSAGE( "MULTIPR_Gen_i::LoadASCII" );
+  return Load(theComponent, theStream, theURL, isMultiFile);
+}
+
+/*! Transform data from transient form to persistent
+ */
+char* MULTIPR_Gen_i::IORToLocalPersistentID (SALOMEDS::SObject_ptr /*theSObject*/,
+                                             const char*           IORString,
+                                             CORBA::Boolean        isMultiFile,
+                                             CORBA::Boolean        /*isASCII*/ )
+{
+  if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::IORToLocalPersistentID");
+
+  MULTIPR_ORB::MULTIPR_Obj_ptr obj =
+    MULTIPR_ORB::MULTIPR_Obj::_narrow(_orb->string_to_object(IORString));
+
+  if (!CORBA::is_nil(obj))
+  {
+    std::string aStudyName;
+    if (isMultiFile)
+      aStudyName = SALOMEDS_Tool::GetNameFromPath(myCurrentStudy->URL());
+
+    std::string subDir  = aStudyName + "_MULTIPR_MED";
+
+    std::string aFile = obj->getFilename();
+    std::string aFileName = multipr::getFilenameWithoutPath(aFile.c_str());
+
+    // Get servant (to call methods, not present in IDL interface
+    PortableServer::Servant aServant = _poa->reference_to_servant(obj);
+    MULTIPR_Obj_i* objServant = dynamic_cast<MULTIPR_Obj_i*>(aServant);
+    if (!objServant)
+    {
+      // TODO: exception
+      return CORBA::string_dup("");
+    }
+
+    std::string strSeparator ("|");
+    if (obj->isValidSequentialMEDFile())
+    {
+      // Save Boxing
+      char strBoxing[32];
+      sprintf(strBoxing, "%d", objServant->getBoxing());
+      aFileName += strSeparator + strBoxing;
+
+      // Save Mesh Name
+      std::string aMeshName = objServant->getMeshName();
+      if (!aMeshName.empty())
+      {
+        aFileName += strSeparator + aMeshName;
+      }
+    }
+    else if (obj->isValidDistributedMEDFile())
+    {
+      // just after partitionneDomaine() the state is MULTIPR_OBJ_STATE_DIS_MEM,
+      // and getFilename() returns name of sequential file
+      // (because distributed file is not created on disk yet). So, build the name:
+      if (aFile == obj->getSeqFilename())
+      {
+        std::string strExtension (".med");
+        std::string strNamePrefix =
+          multipr::removeExtension(aFileName.c_str(), strExtension.c_str());
+        aFileName = strNamePrefix + "_grains_maitre" + strExtension;
+      }
+
+      // Save Boxing
+      char strBoxing[32];
+      sprintf(strBoxing, "%d", objServant->getBoxing());
+      aFileName += strSeparator + strBoxing;
+    }
+    else
+    {
+      // TODO: exception
+      return CORBA::string_dup("");
+    }
+
+    // PersistentID will be a relative path to MED file (relatively tmp dir)
+    // plus additianal parameters, separated by '|' (see above)
+#ifdef WNT
+    std::string dirSeparator = "\\";
+#else
+    std::string dirSeparator = "/";
+#endif
+    aFileName = subDir + dirSeparator + aFileName;
+
+    if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::IORToLocalPersistentID: id = " << aFileName.c_str());
+
+    return CORBA::string_dup(aFileName.c_str());
+  }
+  return CORBA::string_dup("");
+}
+
+/*! Transform data from persistent form to transient
+ */
+char* MULTIPR_Gen_i::LocalPersistentIDToIOR (SALOMEDS::SObject_ptr /*theSObject*/,
+                                             const char*           aLocalPersistentID,
+                                             CORBA::Boolean        isMultiFile,
+                                             CORBA::Boolean        /*isASCII*/)
+{
+  if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::LocalPersistentIDToIOR(): id = " << aLocalPersistentID);
+
+  if (strlen(aLocalPersistentID) > 0)
+  {
+    // Extract relative path
+    std::string strLocalPersistentID (aLocalPersistentID);
+    int nb = strLocalPersistentID.find("|");
+    if (nb < 1) nb = strLocalPersistentID.size();
+    if (nb < 1)
+    {
+      // TODO: exception
+      return CORBA::string_dup("");
+    }
+    std::string strRelativePath = strLocalPersistentID.substr(0, nb);
+    strLocalPersistentID.erase(0, nb); // erase <strRelativePath>
+    if (strLocalPersistentID.size() > 0) strLocalPersistentID.erase(0, 1); // erase "|"
+
+    // the only kind of available objects is a MULTIPR_ORB::MULTIPR_Obj,
+    // representing a sequential or a distributed MED file.
+    std::string medFilename = myTmpDir + strRelativePath; // myTmpDir already contains dir separator
+
+    // create MULTIPR_Obj from file
+    //MULTIPR_ORB::MULTIPR_Obj_ptr obj = getObject(medFilename.c_str());
+    MULTIPR_Obj_i* obj_i = new MULTIPR_Obj_i (_poa,
+                                              medFilename.c_str(),
+                                              /*isPersistence = */true,
+                                              isMultiFile);
+    obj_i->setEngine(this);
+    MULTIPR_ORB::MULTIPR_Obj_ptr obj = obj_i->POA_MULTIPR_ORB::MULTIPR_Obj::_this();
+
+    // Set boxing and mesh name, if provided
+    nb = strLocalPersistentID.find("|");
+    if (nb < 1) nb = strLocalPersistentID.size();
+    if (nb > 0)
+    {
+      std::string strBoxing = strLocalPersistentID.substr(0, nb);
+      strLocalPersistentID.erase(0, nb); // erase <strBoxing>
+      if (strLocalPersistentID.size() > 0) strLocalPersistentID.erase(0, 1); // erase "|"
+      int aBoxing = atoi(strBoxing.c_str());
+      obj->setBoxing(aBoxing);
+    }
+
+    if (obj->isValidSequentialMEDFile())
+    {
+      nb = strLocalPersistentID.size();
+      if (nb > 0)
+      {
+        std::string strMeshName = strLocalPersistentID.substr(0, nb);
+        obj->setMesh(strMeshName.c_str());
+        // we do not cut <strLocalPersistentID> here,
+        // because we do not expect to find in it anything
+      }
+    }
+
+    // get IOR string
+    CORBA::String_var anIORString = _orb->object_to_string(obj);
+    return CORBA::string_dup(anIORString);
+  }
+  return CORBA::string_dup("");
+}
+
+/*! Transform data from persistent form to transient
+ */
+Engines::TMPFile* MULTIPR_Gen_i::DumpPython (CORBA::Object_ptr theStudy,
+                                             CORBA::Boolean isPublished,
+                                             CORBA::Boolean& isValidScript)
+{
+  isValidScript = false;
+
+  SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(theStudy);
+  if (CORBA::is_nil(aStudy))
+    return new Engines::TMPFile(0);
+
+  /*
+  SALOMEDS::SObject_var aSO = aStudy->FindComponent(ComponentDataType());
+  if (CORBA::is_nil(aSO))
+    return new Engines::TMPFile(0);
+
+  // Map study entries to object names
+  Resource_DataMapOfAsciiStringAsciiString aMap;
+  Resource_DataMapOfAsciiStringAsciiString aMapNames;
+
+  SALOMEDS::ChildIterator_var Itr = aStudy->NewChildIterator(aSO);
+  for (Itr->InitEx(true); Itr->More(); Itr->Next()) {
+    SALOMEDS::SObject_var aValue = Itr->Value();
+    CORBA::String_var anID = aValue->GetID();
+    CORBA::String_var aName = aValue->GetName();
+    TCollection_AsciiString aGUIName ( (char*) aName.in() );
+    TCollection_AsciiString anEnrty ( (char*) anID.in() );
+    if (aGUIName.Length() > 0) {
+      aMapNames.Bind( anEnrty, aGUIName );
+      aMap.Bind( anEnrty, aGUIName );
+    }
+  }
+  //*/
+
+  // Get trace of restored study
+  SALOMEDS::SObject_var aSO = aStudy->FindComponent(ComponentDataType());
+  SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
+  SALOMEDS::GenericAttribute_var anAttr =
+    aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
+
+  char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
+  std::string aSavedTrace (oldValue);
+
+  // Add trace of API methods calls and replace study entries by names
+  std::string aScript =
+    "### This file is generated by SALOME automatically "
+    "by dump python functionality of MULTIPR component\n\n";
+  aScript += DumpPython_impl(aStudy->StudyId(), isPublished, isValidScript, aSavedTrace);
+
+  int aLen = aScript.length();
+  unsigned char* aBuffer = new unsigned char[aLen+1];
+  strcpy((char*)aBuffer, aScript.c_str());
+
+  CORBA::Octet* anOctetBuf = (CORBA::Octet*)aBuffer;
+  Engines::TMPFile_var aStreamFile = new Engines::TMPFile (aLen+1, aLen+1, anOctetBuf, 1);
+
+  //bool hasNotPublishedObjects = aScript.Location( NotPublishedObjectName(), 1, aLen);
+  //isValidScript = isValidScript && !hasNotPublishedObjects;
+
+  return aStreamFile._retn();
+}
+
+/*! DumpPython_impl
+ */
+std::string MULTIPR_Gen_i::DumpPython_impl (int theStudyID,
+                                            bool isPublished,
+                                            bool& aValidScript,
+                                            std::string theSavedTrace)
+{
+  std::string helper;
+  std::string aGen = MULTIPR::TPythonDump::MULTIPRGenName();
+
+  // set initial part of a script
+  std::string aScript ("import salome\n");
+  aScript += "import MULTIPR_ORB\n\n";
+  aScript += "def RebuildData(theStudy):\n";
+
+  aScript += helper + "\tmpr_comp = salome.lcc.FindOrLoadComponent(\"FactoryServer\", \"" +
+             ComponentDataType() + "\")\n";
+  aScript += helper + "\t" + aGen + " = mpr_comp._narrow(MULTIPR_ORB.MULTIPR_Gen)\n";
+
+  //if ( isPublished )
+  //  aScript += helper + "\t" + aGen + ".SetCurrentStudy(theStudy)";
+  //else
+  //  aScript += helper + "\t" + aGen + ".SetCurrentStudy(None)";
+  aScript += helper + "\t" + aGen + ".SetCurrentStudy(theStudy)\n";
+
+  // Dump trace of restored study
+  if (theSavedTrace.length() > 0)
+  {
+    aScript += helper + "\n" + theSavedTrace;
+  }
+
+  // Dump trace of API methods calls
+  std::string aNewLines = GetNewPythonLines(theStudyID);
+  if (aNewLines.length() > 0)
+  {
+    aScript += helper + "\n" + aNewLines;
+  }
+
+  // add final part of a script
+  //aScript += helper + "\n\tisGUIMode = " + isPublished;
+  //aScript += "\n\tif isGUIMode and salome.sg.hasDesktop():";
+  //aScript += "\n\t\tsalome.sg.updateObjBrowser(0)";
+  aScript += "\n\n\tpass\n";
+
+  aValidScript = true;
+
+  return aScript;
+}
+
+/*! GetNewPythonLines
+ */
+std::string MULTIPR_Gen_i::GetNewPythonLines (int theStudyID)
+{
+  std::string aScript;
+
+  // Dump trace of API methods calls
+  if (myPythonScripts.find(theStudyID) != myPythonScripts.end())
+  {
+    std::vector <std::string> aPythonScript = myPythonScripts[theStudyID];
+    int istr, aLen = aPythonScript.size();
+    for (istr = 0; istr < aLen; istr++)
+    {
+      aScript += "\n\t";
+      aScript += aPythonScript[istr];
+    }
+    aScript += "\n";
+  }
+
+  return aScript;
+}
+
+/*! CleanPythonTrace
+ */
+void MULTIPR_Gen_i::CleanPythonTrace (int theStudyID)
+{
+  // Clean trace of API methods calls
+  if (myPythonScripts.find(theStudyID) != myPythonScripts.end())
+  {
+    myPythonScripts[theStudyID].clear();
+  }
+}
+
+/*! AddToPythonScript
+ */
+void MULTIPR_Gen_i::AddToPythonScript (int theStudyID, std::string theString)
+{
+  //if (myPythonScripts.find(theStudyID) == myPythonScripts.end())
+  //{
+  //  myPythonScripts[theStudyID] = std::vector<std::string>;
+  //}
+  myPythonScripts[theStudyID].push_back(theString);
+}
+
+/*! SavePython
+ */
+void MULTIPR_Gen_i::SavePython (SALOMEDS::Study_ptr theStudy)
+{
+  // Dump trace of API methods calls
+  std::string aScript = GetNewPythonLines(theStudy->StudyId());
+
+  // Check contents of PythonObject attribute
+  SALOMEDS::SObject_var aSO = theStudy->FindComponent(ComponentDataType());
+  SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
+  SALOMEDS::GenericAttribute_var anAttr =
+    aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
+
+  char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
+  std::string oldScript (oldValue);
+
+  if (oldScript.length() > 0) {
+    oldScript += "\n";
+    oldScript += aScript;
+  }
+  else {
+    oldScript = aScript;
+  }
+
+  // Store in PythonObject attribute
+  SALOMEDS::AttributePythonObject::_narrow(anAttr)->SetObject(oldScript.c_str(), 1);
+
+  // Clean trace of API methods calls
+  CleanPythonTrace(theStudy->StudyId());
+}
+
+
+/*! Returns true if object can be published in the study
+ */
+bool MULTIPR_Gen_i::CanPublishInStudy (CORBA::Object_ptr theIOR)
+{
+  //if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::CanPublishInStudy - " << !CORBA::is_nil(myCurrentStudy));
+  if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::CanPublishInStudy");
+
+  //if (CORBA::is_nil(myCurrentStudy))
+  //  return false;
+
+  MULTIPR_ORB::MULTIPR_Obj_var anObj = MULTIPR_ORB::MULTIPR_Obj::_narrow(theIOR);
+  if (!anObj->_is_nil())
+    return true;
+
+  if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::CanPublishInStudy - CANNOT");
+  return false;
+}
+
+/*! Publish object in the study
+ */
+SALOMEDS::SObject_ptr MULTIPR_Gen_i::PublishInStudy (SALOMEDS::Study_ptr   theStudy,
+                                                     SALOMEDS::SObject_ptr theSObject,
+                                                     CORBA::Object_ptr     theIOR,
+                                                     const char*           theName)
+     throw (SALOME::SALOME_Exception)
+{
+  //Unexpect aCatch(SALOME_SalomeException);
+
+  if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::PublishInStudy");
+
+  //if (myCurrentStudy->_is_nil() || theStudy->StudyId() != myCurrentStudy->StudyId())
+  if (myCurrentStudy->_is_nil())
+    SetCurrentStudy(theStudy);
+
+  SALOMEDS::SObject_var aSO;
+  if (CORBA::is_nil(theStudy) || CORBA::is_nil(theIOR))
+    return aSO._retn();
+
+  // Publishing a MULTIPR_Object
+  MULTIPR_ORB::MULTIPR_Obj_var anObj = MULTIPR_ORB::MULTIPR_Obj::_narrow(theIOR);
+  if (!anObj->_is_nil())
+  {
+    aSO = theStudy->FindObjectIOR(_orb->object_to_string(anObj));
+    if (aSO->_is_nil())
+    {
+      SALOMEDS::GenericAttribute_var anAttr;
+      SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
+
+      SALOMEDS::SComponent_var aFather = theStudy->FindComponent(ComponentDataType());
+      if (aFather->_is_nil())
+      {
+        aFather = aStudyBuilder->NewComponent(ComponentDataType());
+        anAttr = aStudyBuilder->FindOrCreateAttribute(aFather, "AttributeName");
+        SALOMEDS::AttributeName_var aName = SALOMEDS::AttributeName::_narrow(anAttr);
+        aName->SetValue("MULTI-PR");
+        //anAttr = aStudyBuilder->FindOrCreateAttribute(aFather, "AttributePixMap");
+        //SALOMEDS::AttributePixMap::_narrow(anAttr)->SetPixMap("ICON_OBJBROWSER_MULTIPR");
+        //aStudyBuilder->DefineComponentInstance(aFather, MULTIPR_ORB::MULTIPR_Gen::_this());
+        aStudyBuilder->DefineComponentInstance(aFather, MULTIPR_Gen::_this());
+      }
+      if (aFather->_is_nil()) return aSO._retn();
+
+      if (CORBA::is_nil(theSObject))
+      {
+        aSO = aStudyBuilder->NewObject(aFather);
+      }
+      else
+      {
+        if (!theSObject->ReferencedObject(aSO))
+          aSO = SALOMEDS::SObject::_duplicate(theSObject);
+      }
+
+      anAttr = aStudyBuilder->FindOrCreateAttribute(aSO, "AttributeIOR");
+      SALOMEDS::AttributeIOR_var anIORAttr = SALOMEDS::AttributeIOR::_narrow(anAttr);
+      CORBA::String_var anIOR = _orb->object_to_string(anObj);
+      anIORAttr->SetValue(anIOR);
+
+      //anAttr = aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePixMap");
+      //SALOMEDS::AttributePixMap_var aPixmap = SALOMEDS::AttributePixMap::_narrow(anAttr);
+      //aPixmap->SetPixMap("ICON_OBJBROWSER_GROUP_PNT");
+
+      anAttr = aStudyBuilder->FindOrCreateAttribute(aSO, "AttributeName");
+      SALOMEDS::AttributeName_var aNameAttrib = SALOMEDS::AttributeName::_narrow(anAttr);
+      if (strlen(theName) == 0)
+        aNameAttrib->SetValue(anObj->getFilename());
+      else
+        aNameAttrib->SetValue(theName);
+
+      // Dump Python
+      MULTIPR::TPythonDump(this) << "sobj = " << this << ".PublishInStudy(theStudy, "
+                                 << theSObject << ", " << anObj << ", \"" << theName
+                                 << "\") # " << aSO->GetID();
+    }
+  }
+
+  if(MYDEBUG) MESSAGE("MULTIPR_Gen_i::PublishInStudy - END");
+
+  return aSO._retn();
+}
+
+/*
+SALOMEDS::SComponent_ptr _Gen_i::PublishComponent(SALOMEDS::Study_ptr theStudy)
+{
+  if ( CORBA::is_nil( theStudy ))
+    return SALOMEDS::SComponent::_nil();
+  if(MYDEBUG) MESSAGE("PublishComponent");
+
+  SALOMEDS::SComponent_var father =
+    SALOMEDS::SComponent::_narrow( theStudy->FindComponent( ComponentDataType() ) );
+  if ( !CORBA::is_nil( father ) )
+    return father._retn();
+
+  SALOME_ModuleCatalog::ModuleCatalog_var aCat =
+    SALOME_ModuleCatalog::ModuleCatalog::_narrow( GetNS()->Resolve("/Kernel/ModulCatalog") );
+  if ( CORBA::is_nil( aCat ) )
+    return father._retn();
+
+  SALOME_ModuleCatalog::Acomponent_var aComp = aCat->GetComponent( ComponentDataType() );
+  if ( CORBA::is_nil( aComp ) )
+    return father._retn();
+
+  SALOMEDS::StudyBuilder_var     aStudyBuilder = theStudy->NewBuilder();
+  SALOMEDS::GenericAttribute_var anAttr;
+  SALOMEDS::AttributePixMap_var  aPixmap;
+
+  father  = aStudyBuilder->NewComponent( ComponentDataType() );
+  aStudyBuilder->DefineComponentInstance( father, SMESH_Gen::_this() );
+  anAttr  = aStudyBuilder->FindOrCreateAttribute( father, "AttributePixMap" );
+  aPixmap = SALOMEDS::AttributePixMap::_narrow( anAttr );
+  aPixmap ->SetPixMap( "ICON_OBJBROWSER_SMESH" );
+  SetName( father, aComp->componentusername(), "MESH" );
+  if(MYDEBUG) MESSAGE("PublishComponent--END");
+
+  return father._retn();
+}
+//*/
+
+
+/*!
+ *  MULTIPREngine_factory
+ *
+ *  C factory, accessible with dlsym, after dlopen
+ */
 extern "C"
 {
     PortableServer::ObjectId* MULTIPREngine_factory(
         CORBA::ORB_ptr orb,
-        PortableServer::POA_ptr poa, 
+        PortableServer::POA_ptr poa,
         PortableServer::ObjectId * contId,
-        const char* instanceName, 
+        const char* instanceName,
         const char* interfaceName)
     {
         MESSAGE("PortableServer::ObjectId* MULTIPREngine_factory()");
index 23f567a80890288e2572d2ec02c85e81babd9b6e..7e1eaed10f0003ace5958ffcffc956b29caa98d6 100644 (file)
@@ -7,15 +7,15 @@
  * \brief   C++ implementation of the CORBA interface of the MULTIPR module.
  *
  * \author  Olivier LE ROUX - CS, Virtual Reality Dpt
- * 
+ *
  * \date    01/2007
  */
 
-  
+
 //*****************************************************************************
 // Includes section
 //*****************************************************************************
+
 #ifndef __MULTIPR_IMPLEMENTATION_CORBA__
 #define __MULTIPR_IMPLEMENTATION_CORBA__
 
 #include "SALOME_Component_i.hxx"
 #include "Utils_CorbaException.hxx"
 
+#include "SALOME_GenericObj_i.hh"
+
 #include "MULTIPR_Obj.hxx"
 
+#include <map>
+#include <vector>
+#include <string>
+
+class MULTIPR_Gen_i;
 
 //*****************************************************************************
 // Class MULTIPR_Obj_i
@@ -34,7 +41,8 @@
 //*****************************************************************************
 
 class MULTIPR_Obj_i :
-    public POA_MULTIPR_ORB::MULTIPR_Obj
+    public POA_MULTIPR_ORB::MULTIPR_Obj,
+    public virtual SALOME::GenericObj_i
 {
 
 public:
@@ -44,84 +52,120 @@ public:
      * Associate a MED file (sequential or distributed) with this object.
      * \param  pMEDFilename MED file to be associated with this object.
      */
-    MULTIPR_Obj_i(const char* pMEDFilename)
+    MULTIPR_Obj_i (PortableServer::POA_ptr thePOA,
+                   const char* pMEDFilename,
+                   bool isPersistence = false,
+                   bool isMultifile   = false)
         throw (SALOME::SALOME_Exception);
-        
+
     /**
      * Destructor.
      */
     virtual ~MULTIPR_Obj_i();
-    
+
     //---------------------------------------------------------------------
     // Basic accessors/mutators
     //--------------------------------------------------------------------
-    
+
+    /**
+     * Reset the object.
+     */
+    void    reset()
+        throw (SALOME::SALOME_Exception);
+
     /**
      * Returns true iff this obj represents a valid sequential MED file.
      * \return true iff this obj represents a valid sequential MED file.
      */
     CORBA::Boolean isValidSequentialMEDFile()
         throw (SALOME::SALOME_Exception);
-    
+
     /**
      * Returns true iff this obj represents a valid distributed MED file.
      * \return true iff this obj represents a valid distributed  MED file.
      */
     CORBA::Boolean isValidDistributedMEDFile()
         throw (SALOME::SALOME_Exception);
-    
+
     /**
      * Returns the name of the associated MED file.
      * \return the name of the associated MED file.
      */
     char* getFilename()
         throw (SALOME::SALOME_Exception);
-    
+
     /**
      * Returns the name of the associated sequential MED file (for a distributed MED file).
      * \return the name of the associated sequential MED file (for a distributed MED file).
-     */     
+     */
     char* getSeqFilename()
         throw (SALOME::SALOME_Exception);
+
     /**
      * Defines the mesh to be processed.
      * \param  pMeshName name of the mesh to be partitionned.
      */
     void setMesh(const char* pMeshName)
         throw (SALOME::SALOME_Exception);
-    
+
+    /**
+     * Returns a name of the mesh to be processed.
+     * \return a name of the mesh to be processed.
+     */
+    std::string getMeshName() const
+        throw (SALOME::SALOME_Exception);
+
     /**
      * Sets boxing parameters for decimation (100 by default).
-     * \param  pBoxing number of cells along each axis of the grid (= acceleration structure) ; should be in [1..200].
+     * \param  pBoxing number of cells along each axis of the grid
+     * (= acceleration structure) ; should be in [1..200].
      */
     void setBoxing(CORBA::Long pBoxing)
         throw (SALOME::SALOME_Exception);
 
+    /**
+     * Returns currently set boxing parameter for decimation.
+     * \return currently set boxing parameter for decimation.
+     */
+    int getBoxing() const { return mBoxing; }
+
     /**
      * Returns the list of meshes contained in the sequential MED file.
      * Assumes this object encapsulates a sequential MED file.
      * \return the list of meshes contained in the sequential MED file.
      */
-    MULTIPR_ORB::string_array* getMeshes() 
+    MULTIPR_ORB::string_array* getMeshes()
         throw (SALOME::SALOME_Exception);
 
     /**
      * Returns the list of fields contained in the sequential MED file.
      * Assumes this object encapsulates a sequential MED file.
+     * \param pPartList The list of parts to get the fields from (separator is '|').
      * \return the list of fields contained in the sequential MED file.
      */
-    MULTIPR_ORB::string_array* getFields(
+    MULTIPR_ORB::string_array* getFields(const char* pPartList)
         throw (SALOME::SALOME_Exception);
-    
+
     /**
      * Returns the number of timestamps for a given field.
      * Assumes this object encapsulates a sequential MED file.
+     * \param pPartList The list of parts to get the fields from (separator is '|').
      * \param  pFieldName name of any field.
      * \return the number of timestamps for a given field; 0 if field not found.
      */
-    CORBA::Long getTimeStamps(const char* pFieldName)
+    CORBA::Long getTimeStamps(const char* pPartList, const char* pFieldName)
         throw (SALOME::SALOME_Exception);
-    
+
+    /**
+     * Get the minimum and maximum value of a part's field.
+     * \param pPartName The name of the part.
+     * \param pFieldName The name of the field.
+     * \param pMin The mininum value to fill.
+     * \param pMax The maxinum value to fill.
+     */
+    void getFieldMinMax(const char* pPartName, const char* pFieldName, CORBA::Float& pMin, CORBA::Float& pMax)
+       throw (SALOME::SALOME_Exception);
+
     /**
      * Returns the name of all partitions.
      * Assumes this object encapsulates a distributed MED file.
@@ -138,11 +182,11 @@ public:
      */
     char* getPartInfo(const char* pPartName)
         throw (SALOME::SALOME_Exception);
-    
+
     //---------------------------------------------------------------------
     // Algorithms
     //---------------------------------------------------------------------
-    
+
     /**
      * Creates a distributed MED file (v2.3) by extracting all the groups from the current mesh of the current MED sequential MED file.
      *         Assumes:
@@ -154,8 +198,8 @@ public:
      */
     MULTIPR_ORB::string_array* partitionneDomaine()
         throw (SALOME::SALOME_Exception);
-    
-    /** 
+
+    /**
      * Creates a distributed MED file (V2.3) by splitting a group of a MED file previously created by partitionneDomaine.
      *         Assumes:
      *         - the file is a distributed MED file, previously created by partitionneDomaine()
@@ -166,12 +210,12 @@ public:
      * \param  pPartitionner use value 0=MULTIPR_METIS for Metis or 1=MULTIPR_SCOTCH for Scotch.
      * \return the name of each part.
      */
-    MULTIPR_ORB::string_array* partitionneGrain(
-        const char* pPartName, 
-        CORBA::Long pNbParts, 
+    MULTIPR_ORB::string_array* partitionneGroupe(
+        const char* pPartName,
+        CORBA::Long pNbParts,
         CORBA::Long pPartitionner)
         throw (SALOME::SALOME_Exception);
-    
+
     /**
      * Creates 3 resolutions of the given part of a distributed MED file (V2.3).
      *         Assumes:
@@ -191,11 +235,24 @@ public:
         const char*   pFieldName,
         CORBA::Long   pFieldIt,
         const char*   pFilterName,
-        CORBA::Double pTmed,
-        CORBA::Double pTlow,
-        CORBA::Double pRadius)
+        const char*   pFilterParams)
         throw (SALOME::SALOME_Exception);
-        
+
+    /**
+     * Works exactly like the above method, but returns not a list
+     * of all parts, but a list of empty obtained resolutions.
+     * \return the list of empty resolutions.
+     */
+  /*
+    MULTIPR_ORB::string_array* decimatePart(
+        const char*   pPartName,
+        const char*   pFieldName,
+        CORBA::Long   pFieldIt,
+        const char*   pFilterName,
+        const char*   pFilterParams)
+        throw (SALOME::SALOME_Exception);
+  */
+
     /**
      * Returns useful information to configure decimation parameters.
      * Depends on part, field and filter: generic operation.
@@ -206,13 +263,13 @@ public:
      * \param  pFilterParams params to be used with the filter (depends on filter; this string will be parsed).
      */
     char* evalDecimationParams(
-        const char* pPartName, 
-        const char* pFieldName, 
-        CORBA::Long pFieldIt, 
+        const char* pPartName,
+        const char* pFieldName,
+        CORBA::Long pFieldIt,
         const char* pFilterName,
         const char* pFilterParams)
         throw (SALOME::SALOME_Exception);
-        
+
     /*!
      * Removes all the parts starting with "pPrefixPartName" from the distributed MED file.
      * Example: if pPrefixPartName="PART_4" => remove "PART_4" and all sub-parts "PART_4_*", but not "PART41".
@@ -221,32 +278,77 @@ public:
      */
     void removeParts(const char* pPrefixPartName)
         throw (SALOME::SALOME_Exception);
-    
+
+    /**
+     * Get mesh statistics.
+     * \return Mesh statistics !
+     */
+    char* getMEDInfo(const char* pPartName)
+        throw (SALOME::SALOME_Exception);
+
     //---------------------------------------------------------------------
     // I/O
     //---------------------------------------------------------------------
-    
+
     /**
      * Saves the associated MED file if necessary.
      * \param  pPath path where to save the file.
      */
     void save(const char* pPath)
         throw (SALOME::SALOME_Exception);
-    
+
+    /**
+     * Check save progress.
+     * \return current save progress in percents.
+     */
+    CORBA::Long getSaveProgress();
+
+    /**
+     * Reset save progress to zero.
+     */
+    void resetSaveProgress();
+
+    //---------------------------------------------------------------------
+    // Persistence and Dump Python
+    //---------------------------------------------------------------------
+
+    /**
+     * Saves the associated MED file to the given location.
+     * \note To be used only for persistence.
+     * \param pPath path where to save the file.
+     */
+    void savePersistent (const char* pPath)
+      throw (SALOME::SALOME_Exception);
+
+    /**
+     * Set Engine.
+     */
+    //void setEngine (MULTIPR_ORB::MULTIPR_Gen_ptr theEngine);
+    void setEngine (MULTIPR_Gen_i* theEngine);
+
 private:
 
     /**
      * The associated MULTIPR object.
      */
     multipr::Obj* mObj;
-    
+
     /**
      * Boxing paremeter: number of cells along each axis.
      * E.g. if mBoxing=10 then total number of cells = 10*10*10 = 1000.
      * By default, mBoxing=100.
      */
     int mBoxing;
-    
+
+    /**
+     * Engine.
+     */
+    MULTIPR_Gen_i* _engine;
+
+    /**
+     * Is restored MED file (Used by Persistence to remove temporary files).
+     */
+    bool mIsTmp;
 };
 
 
@@ -257,7 +359,7 @@ private:
 
 class MULTIPR_Gen_i :
     public POA_MULTIPR_ORB::MULTIPR_Gen,
-    public Engines_Component_i 
+    public Engines_Component_i
 {
 
 public:
@@ -265,41 +367,143 @@ public:
     MULTIPR_Gen_i(
         CORBA::ORB_ptr orb,
         PortableServer::POA_ptr poa,
-        PortableServer::ObjectId* contId, 
-        const char* instanceName, 
+        PortableServer::ObjectId* contId,
+        const char* instanceName,
         const char* interfaceName);
-    
+
     virtual ~MULTIPR_Gen_i();
-    
+
     char* getVersion()
         throw (SALOME::SALOME_Exception);
-    
+
     void partitionneDomaine(
-        const char* medFilename, 
+        const char* medFilename,
         const char* meshName)
         throw (SALOME::SALOME_Exception);
-    
-    void partitionneGrain(
-        const char* medFilename, 
-        const char* partName, 
-        CORBA::Long nbParts, 
+
+    void partitionneGroupe(
+        const char* medFilename,
+        const char* partName,
+        CORBA::Long nbParts,
         CORBA::Long partitionner)
         throw (SALOME::SALOME_Exception);
-    
+
     void decimePartition(
-        const char*   medFilename, 
-        const char*   partName, 
+        const char*   medFilename,
+        const char*   partName,
         const char*   fieldName,
         CORBA::Long   fieldIt,
         const char*   filterName,
-        CORBA::Double tmed,
-        CORBA::Double tlow,
-        CORBA::Double radius,
-        CORBA::Long   boxing)
+        const char*   filterParams)
         throw (SALOME::SALOME_Exception);
+
     MULTIPR_ORB::MULTIPR_Obj_ptr getObject(const char* medFilename)
         throw (SALOME::SALOME_Exception);
+
+  // ****************************************************
+  // Set/Get current study for Persistence and Dump Python
+  // ****************************************************
+
+  // Set current study
+  void SetCurrentStudy (SALOMEDS::Study_ptr theStudy);
+  // Get current study
+  SALOMEDS::Study_ptr GetCurrentStudy();
+
+  // Mark current study as modified, if theObj is published in it
+  void ObjModified (MULTIPR_ORB::MULTIPR_Obj_ptr theObj);
+
+  // ****************************************************
+  // Interface inherited methods (from SALOMEDS::Driver)
+  // ****************************************************
+
+  // Save SMESH data
+  SALOMEDS::TMPFile* Save (SALOMEDS::SComponent_ptr theComponent,
+                           const char*              theURL,
+                           bool                     isMultiFile);
+  // Load SMESH data
+  bool Load (SALOMEDS::SComponent_ptr theComponent,
+            const SALOMEDS::TMPFile& theStream,
+            const char*              theURL,
+            bool                     isMultiFile);
+
+  // Save SMESH data in ASCII format
+  SALOMEDS::TMPFile* SaveASCII (SALOMEDS::SComponent_ptr theComponent,
+                               const char*              theURL,
+                               bool                     isMultiFile);
+  // Load SMESH data in ASCII format
+  bool LoadASCII (SALOMEDS::SComponent_ptr theComponent,
+                 const SALOMEDS::TMPFile& theStream,
+                 const char*              theURL,
+                 bool                     isMultiFile);
+
+  // Clears study-connected data when it is closed
+  void Close (SALOMEDS::SComponent_ptr theComponent);
+
+  // Get component data type
+  char* ComponentDataType();
+
+  // Transform data from transient form to persistent
+  char* IORToLocalPersistentID (SALOMEDS::SObject_ptr theSObject,
+                               const char*           IORString,
+                               CORBA::Boolean        isMultiFile,
+                               CORBA::Boolean        isASCII);
+  // Transform data from persistent form to transient
+  char* LocalPersistentIDToIOR (SALOMEDS::SObject_ptr theSObject,
+                               const char*           aLocalPersistentID,
+                               CORBA::Boolean        isMultiFile,
+                               CORBA::Boolean        isASCII);
+
+  // Returns true if object can be published in the study
+  bool CanPublishInStudy (CORBA::Object_ptr theIOR);
+  // Publish object in the study
+  SALOMEDS::SObject_ptr PublishInStudy (SALOMEDS::Study_ptr   theStudy,
+                                       SALOMEDS::SObject_ptr theSObject,
+                                       CORBA::Object_ptr     theObject,
+                                       const char*           theName)
+    throw (SALOME::SALOME_Exception);
+
+  // Copy-paste methods - returns true if object can be copied to the clipboard
+  CORBA::Boolean CanCopy (SALOMEDS::SObject_ptr theObject) { return false; }
+  // Copy-paste methods - copy object to the clipboard
+  SALOMEDS::TMPFile* CopyFrom (SALOMEDS::SObject_ptr theObject, CORBA::Long& theObjectID) { return false; }
+  // Copy-paste methods - returns true if object can be pasted from the clipboard
+  CORBA::Boolean CanPaste (const char* theComponentName, CORBA::Long theObjectID) { return false; }
+  // Copy-paste methods - paste object from the clipboard
+  SALOMEDS::SObject_ptr PasteInto (const SALOMEDS::TMPFile& theStream,
+                                  CORBA::Long              theObjectID,
+                                  SALOMEDS::SObject_ptr    theObject)
+  {
+    SALOMEDS::SObject_var aResultSO;
+    return aResultSO._retn();
+  }
+
+  // ============
+  // Dump python
+  // ============
+
+  virtual Engines::TMPFile* DumpPython (CORBA::Object_ptr theStudy,
+                                        CORBA::Boolean isPublished,
+                                        CORBA::Boolean& isValidScript);
+
+  void AddToPythonScript (int theStudyID, std::string theString);
+
+private:
+  std::string DumpPython_impl (int theStudyID,
+                               bool isPublished,
+                               bool& aValidScript,
+                               std::string theSavedTrace);
+
+  std::string GetNewPythonLines (int theStudyID);
+  void CleanPythonTrace (int theStudyID);
+  void SavePython (SALOMEDS::Study_ptr theStudy);
+
+private:
+  // Current study
+  SALOMEDS::Study_var myCurrentStudy;
+  // Dump Python: trace of API methods calls
+  std::map < int, std::vector <std::string> > myPythonScripts;
+  // Tmp directory. Used by Persistence.
+  std::string myTmpDir;
 };
 
 
@@ -313,4 +517,3 @@ extern "C" PortableServer::ObjectId* MULTIPREngine_factory(
 #endif // __MULTIPR_IMPLEMENTATION_CORBA__
 
 // EOF
-
index 0cdaf1e60449139bc46113fff8c7287b3a385de0..9b326c5fb06fa99bf47c8839769c7e094d3b4eda 100644 (file)
@@ -44,8 +44,20 @@ EXPORT_HEADERS =
 
 CPPFLAGS += $(KERNEL_CXXFLAGS) $(MED_CXXFLAGS) $(MED2_INCLUDES) -Wall -pthread  
 
-LDFLAGS += $(KERNEL_LDFLAGS) $(MED_LDFLAGS) $(MED2_LIBS) -lSalomeContainer -lOpUtil \
-          -lSALOMELocalTrace -lm -lmed -lmedsplitter -lmedmem -lmed_V2_1 -lMULTIPR_API
+LDFLAGS += \
+       $(KERNEL_LDFLAGS) \
+       -lSalomeContainer \
+       -lSalomeGenericObj \
+       -lOpUtil \
+       -lTOOLSDS \
+       -lSALOMELocalTrace \
+       $(MED2_LIBS) \
+       -lmed \
+       $(MED_LDFLAGS) \
+       -lmedsplitter \
+       -lmedmem \
+       -lmed_V2_1 \
+       -lMULTIPR_API
 
 # Executables targets
 
index d74519edac0f6e6aa644271469d96b5add1b8f07..586edc63e7291d8da65e23bd009871c57b0690fc 100644 (file)
 #include "MULTIPR_Utils.hxx"
 
 // Salome Includes
-#include <SUIT_MessageBox.h>
-#include <SUIT_ResourceMgr.h>
-#include <SUIT_Session.h>
 #include <SalomeApp_Application.h>
 #include <SalomeApp_DataModel.h>
 #include <SalomeApp_Study.h>
 #include <SalomeApp_CheckFileDlg.h>
+
 #include <LightApp_Study.h>
 #include <LightApp_DataModel.h>
 #include <LightApp_DataOwner.h>
 #include <LightApp_SelectionMgr.h>
+
 #include <CAM_DataModel.h>
 #include <CAM_Module.h>
 
+#include <SUIT_MessageBox.h>
+#include <SUIT_ResourceMgr.h>
+#include <SUIT_Session.h>
+
 #include <SALOME_LifeCycleCORBA.hxx>
+#include <SALOMEDS_Study.hxx>
+
+#include <SALOME_Event.hxx>
 
 #include <QtxPopupMgr.h>
 
@@ -58,7 +64,8 @@
 #include <qpixmap.h>
 #include <qmessagebox.h>
 #include <qaction.h>
-
+#include <qtimer.h>
+#include <qthread.h>
 
 #include <stdexcept>
 
@@ -69,49 +76,118 @@ using namespace std;
 // Global variable
 //*****************************************************************************
 
-namespace multipr
+//namespace multipr
+//{
+//    // progress callback used by the MULTIPR library
+//    extern MULTIPR_ProgressCallback*  gProgressCallback;
+//    extern MULTIPR_EmptyMeshCallback* gEmptyMeshCallback;
+//}
+class MULTIPR_GUI_FinishSaveEvent: public SALOME_Event
 {
-    // progress callback used by the MULTIPR library
-    extern MULTIPR_ProgressCallback*  gProgressCallback;
-    extern MULTIPR_EmptyMeshCallback* gEmptyMeshCallback;
-}
+  SalomeApp_Application* myApp;
+  bool myIsError;
+public:
+  MULTIPR_GUI_FinishSaveEvent (SalomeApp_Application* theApp,
+                               bool theIsError)
+    : myApp(theApp),
+      myIsError(theIsError)
+  {}
+  virtual void Execute()
+  {
+    if (myIsError) {
+      SUIT_MessageBox::error1(myApp->desktop(),
+                              "Save distributed MED file error", 
+                              "Error while writing distributed MED file", 
+                              myApp->tr("MULTIPR_BUT_OK"));
+    }
+    else {
+      myApp->updateObjectBrowser();
+      myApp->updateActions();
+    }
+    QApplication::restoreOverrideCursor();
+  }
+};
 
+class MULTIPR_GUI_SaveThread : public QThread
+{
+public:
+  MULTIPR_GUI_SaveThread (MULTIPR_GUI* pModule,
+                          MULTIPR_ORB::MULTIPR_Obj_ptr pObj,
+                          QString pPath)
+    : mModule(pModule)
+  {
+    mObj = MULTIPR_ORB::MULTIPR_Obj::_duplicate(pObj);
+    mPath = pPath;
+  }
+  virtual void run();
+
+private:
+  MULTIPR_GUI* mModule;
+  MULTIPR_ORB::MULTIPR_Obj_ptr mObj;
+  QString mPath;
+};
+
+void MULTIPR_GUI_SaveThread::run()
+{
+  try
+  {
+    mObj->save(mPath);
+  }
+  catch(...)
+  {
+    ProcessVoidEvent(new MULTIPR_GUI_FinishSaveEvent(mModule->getApp(), true));
+    return;
+  }
+
+  ProcessVoidEvent(new MULTIPR_GUI_FinishSaveEvent(mModule->getApp(), false));
+}
 
 //*****************************************************************************
 // Global function
 //*****************************************************************************
 
 // singleton
-MULTIPR_ORB::MULTIPR_Gen_ptr GetMultiprGen(const CAM_Module* theModule)
+MULTIPR_ORB::MULTIPR_Gen_ptr GetMultiprGen (const CAM_Module* theModule)
 {
     static MULTIPR_ORB::MULTIPR_Gen_ptr aGen = NULL;
-    
+
     if (!aGen)
     {
-        SALOME_LifeCycleCORBA aLCC(SalomeApp_Application::namingService());
+        SALOME_LifeCycleCORBA aLCC (SalomeApp_Application::namingService());
         Engines::Component_var aComponent = aLCC.FindOrLoad_Component("FactoryServer", "MULTIPR");
         aGen = MULTIPR_ORB::MULTIPR_Gen::_narrow(aComponent);
         if (!CORBA::is_nil(aGen))
         {
-            //aGen->SetCurrentStudy(GetDSStudy(GetCStudy(GetAppStudy(theModule))));
+          // Set current study
+          SalomeApp_Study* aSAStudy =
+            dynamic_cast<SalomeApp_Study*>(theModule->application()->activeStudy());
+          _PTR(Study) aStudy = aSAStudy->studyDS();
+          SALOMEDS::Study_ptr aStudyDS;
+          if (aStudy)
+            aStudyDS = _CAST(Study,aStudy)->GetStudy();
+          aGen->SetCurrentStudy(aStudyDS);
         }
     }
-    
+
     if (CORBA::is_nil(aGen))
         throw std::runtime_error("Can't find MULTIPR component");
-    
+
     return aGen;
 }
-  
+
 
 //*****************************************************************************
 // Class MULTIPR_GUI implementation
 //*****************************************************************************
 
-MULTIPR_GUI::MULTIPR_GUI() : SalomeApp_Module("MULTIPR")
+MULTIPR_GUI::MULTIPR_GUI()
+  : SalomeApp_Module("MULTIPR"),
+    mMULTIPRObj(NULL),
+    mMEDFileName(""),
+    mProgress(NULL)
 {
-    mMEDFileName = "";
-    mMULTIPRObj = NULL;
+  mTimer = new QTimer (this);
+  connect(mTimer, SIGNAL(timeout()), this, SLOT(timerDone()));
 }
 
 
@@ -129,6 +205,10 @@ MULTIPR_ORB::MULTIPR_Obj_ptr MULTIPR_GUI::getMULTIPRObj()
     return mMULTIPRObj;
 }
 
+void MULTIPR_GUI::setMULTIPRObj (MULTIPR_ORB::MULTIPR_Obj_ptr theObj)
+{
+  mMULTIPRObj = MULTIPR_ORB::MULTIPR_Obj::_duplicate(theObj);
+}
 
 SalomeApp_Application* MULTIPR_GUI::getAppli() const
 {
@@ -253,11 +333,13 @@ void MULTIPR_GUI::initialize(CAM_Application* app)
     //-------------------------------------------------------------------------
     // set progress dialog
     //-------------------------------------------------------------------------
-    MULTIPR_GUI_ProgressCallbackDlg* progressDlg = new MULTIPR_GUI_ProgressCallbackDlg(application()->desktop());
-    multipr::gProgressCallback = progressDlg;
+    //MULTIPR_GUI_ProgressCallbackDlg* progressDlg =
+    //  new MULTIPR_GUI_ProgressCallbackDlg(application()->desktop());
+    //multipr::gProgressCallback = progressDlg;
     
-    MULTIPR_GUI_EmptyMeshCallbackDlg* emptyMeshDlg = new MULTIPR_GUI_EmptyMeshCallbackDlg(application()->desktop());
-    multipr::gEmptyMeshCallback = emptyMeshDlg;
+    //MULTIPR_GUI_EmptyMeshCallbackDlg* emptyMeshDlg =
+    //  new MULTIPR_GUI_EmptyMeshCallbackDlg(application()->desktop());
+    //multipr::gEmptyMeshCallback = emptyMeshDlg;
 }
 
 
@@ -273,7 +355,6 @@ QString MULTIPR_GUI::engineIOR() const
     return QString(anIOR.in());
 }
 
-
 bool MULTIPR_GUI::activateModule(SUIT_Study* theStudy)
 {
     bool bOk = SalomeApp_Module::activateModule(theStudy);
@@ -357,15 +438,22 @@ void MULTIPR_GUI::OnImportFromMEDFile()
     // Check the file name
     if (!aFileInfo.exists())
         return;
-        
+
     mMEDFileName = aFileInfo.filePath();
-    
+
     QApplication::setOverrideCursor(Qt::waitCursor);
-    
+
+    // Delete previous MULTIPR object.
+    if (mMULTIPRObj != NULL)
+    {
+        mMULTIPRObj->reset();
+    }
+
+    MULTIPR_ORB::MULTIPR_Gen_ptr multiprgen = GetMultiprGen(this);
+
     try
     {
-        MULTIPR_ORB::MULTIPR_Gen_ptr multiprgen = GetMultiprGen(this);
-        mMULTIPRObj = multiprgen->getObject(mMEDFileName.latin1());
+      mMULTIPRObj = multiprgen->getObject(mMEDFileName.latin1());
     }
     catch(...)
     {
@@ -379,6 +467,12 @@ void MULTIPR_GUI::OnImportFromMEDFile()
     
     if (mMULTIPRObj != NULL)
     {
+        SALOMEDS::SObject_ptr aSObject = SALOMEDS::SObject::_nil();
+        SalomeApp_Study* aSAStudy = dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
+        _PTR(Study) aStudyDSClient = aSAStudy->studyDS();
+        SALOMEDS::Study_ptr aStudyDS = _CAST(Study,aStudyDSClient)->GetStudy();
+        multiprgen->PublishInStudy(aStudyDS, aSObject, mMULTIPRObj, "Mesh");
+
         try
         {
             if (mMULTIPRObj->isValidSequentialMEDFile())
@@ -389,8 +483,9 @@ void MULTIPR_GUI::OnImportFromMEDFile()
         catch (...)
         {
         }
-        
+
         getApp()->updateObjectBrowser();
+        getApp()->updateActions();
     }
 }
 
@@ -402,10 +497,51 @@ void MULTIPR_GUI::OnPartition1()
     {
         return;
     }
-    
+    // do the partition.   
     MULTIPR_GUI_Partition1Dlg* dialog = new MULTIPR_GUI_Partition1Dlg(this);
     dialog->exec();
     delete dialog;
+
+    // Now we need to save the file.
+    SalomeApp_CheckFileDlg* fd = new SalomeApp_CheckFileDlg(
+        this->application()->desktop(), 
+        true, 
+        tr("") );
+        
+    fd->setCaption(tr("Save distributed MED file - Destination directory"));
+    fd->setMode(QFileDialog::DirectoryOnly);
+    
+    if (fd->exec() == QDialog::Rejected)
+    {
+        delete fd;
+        mMULTIPRObj->reset();
+        getApp()->updateObjectBrowser();
+        return;
+    }
+    
+    QFileInfo aFileInfo(fd->selectedFile());
+    delete fd;
+        
+    QString path = aFileInfo.filePath();
+    
+    QApplication::setOverrideCursor(Qt::waitCursor);
+    mMULTIPRObj->resetSaveProgress();
+
+    MULTIPR_GUI_SaveThread* a = new MULTIPR_GUI_SaveThread (this, mMULTIPRObj, path);
+    a->start();
+    
+    // save progress
+    //mProgress = new MULTIPR_GUI_ProgressCallbackDlg (getApp()->desktop());
+    //mProgress->start("Save mesh", 100);
+    if (mProgress == NULL)
+        mProgress = new QProgressDialog ("Save mesh", "Cancel", /*totalSteps*/100, getApp()->desktop());
+    //mProgress->setProgress(0);
+    //mProgress->init(100);
+    //mTimer->start(500); // 0.5 seconds timer
+    //QApplication::restoreOverrideCursor();
+    //getApp()->updateObjectBrowser();
+    
 }
 
 
@@ -438,6 +574,7 @@ void MULTIPR_GUI::OnPartition2()
     dialog->exec();
     delete dialog;
     getApp()->updateObjectBrowser();
+    getApp()->updateActions();
 }
 
 
@@ -460,16 +597,30 @@ void MULTIPR_GUI::OnDecimate()
             tr("MULTIPR_BUT_OK") );
         return;
     }
-    
+
     if (!removeLowerResolution())
     {
         return;
     }
-    
+
+    const QStringList& partsList = this->getSelectedParts();
+    QString allParts = partsList.join("|");
+    MULTIPR_ORB::string_array* listFields = this->getMULTIPRObj()->getFields(allParts.latin1());
+    if (listFields->length() == 0)
+    {
+      SUIT_MessageBox::error1( 
+            this->getAppli()->desktop(),
+            "Decimation error", 
+            "No field for this part.", 
+            tr("OK") );
+      return ;
+    }
+
     MULTIPR_GUI_DecimateDlg* dialog = new MULTIPR_GUI_DecimateDlg(this);
     dialog->exec();
     delete dialog;
     getApp()->updateObjectBrowser();
+    getApp()->updateActions();
 }
 
 
@@ -504,16 +655,16 @@ void MULTIPR_GUI::OnRemove()
     }
 
     QApplication::setOverrideCursor(Qt::waitCursor);
-    
+
     try
     {
-        for (QStringList::const_iterator it = mSelectedParts.begin(), last = mSelectedParts.end(); it != last; it++)
-        {
-            const QString& partName = (*it);
-            cout << "Remove " << partName.latin1() << endl;
-            mMULTIPRObj->removeParts(partName.latin1());
-        }
-        
+      QStringList::const_iterator it = mSelectedParts.begin(), last = mSelectedParts.end();
+      for (; it != last; it++)
+      {
+        const QString& partName = (*it);
+        cout << "Remove " << partName.latin1() << endl;
+        mMULTIPRObj->removeParts(partName.latin1());
+      }
     }
     catch(...)
     {
@@ -523,66 +674,76 @@ void MULTIPR_GUI::OnRemove()
             "Error while removing selected part(s)", 
             tr("MULTIPR_BUT_OK") );
     }
-    
+
     QApplication::restoreOverrideCursor();
-    
+
     getApp()->updateObjectBrowser();
+    getApp()->updateActions();
 }
 
 
 void MULTIPR_GUI::OnSave()
 {
-    // check if MULTIPRObj exists
-    if (mMULTIPRObj == NULL)
-    {
-        return;
-    }
-    
-    SalomeApp_CheckFileDlg* fd = new SalomeApp_CheckFileDlg(
-        this->application()->desktop(), 
-        true, 
-        tr("") );
-        
-    fd->setCaption(tr("Save distributed MED file - Destination directory"));
-    fd->setMode(QFileDialog::DirectoryOnly);
-    
-    if (fd->exec() == QDialog::Rejected)
-    {
-        delete fd;
-        return;
-    }
-    
-    QFileInfo aFileInfo(fd->selectedFile());
+  // check if MULTIPRObj exists
+  if (mMULTIPRObj == NULL)
+  {
+    return;
+  }
+
+  SalomeApp_CheckFileDlg* fd =
+    new SalomeApp_CheckFileDlg(this->application()->desktop(),
+                               true,
+                               tr(""));
+
+  fd->setCaption(tr("Save distributed MED file - Destination directory"));
+  fd->setMode(QFileDialog::DirectoryOnly);
+
+  if (fd->exec() == QDialog::Rejected)
+  {
     delete fd;
-        
-    QString path = aFileInfo.filePath();
-    
-    QApplication::setOverrideCursor(Qt::waitCursor);
-    
-    try
-    {
-        mMULTIPRObj->save(path);
-        getApp()->updateObjectBrowser();
-    }
-    catch(...)
-    {
-        SUIT_MessageBox::error1( 
-            getApp()->desktop(),
-            "Save distributed MED file error", 
-            "Error while writing distributed MED file", 
-            tr("MULTIPR_BUT_OK") );
-    }
-    
-    QApplication::restoreOverrideCursor();
+    return;
+  }
+
+  QFileInfo aFileInfo(fd->selectedFile());
+  delete fd;
+
+  QApplication::setOverrideCursor(Qt::waitCursor);
+
+  QString path = aFileInfo.filePath();
+  mMULTIPRObj->resetSaveProgress();
+
+  MULTIPR_GUI_SaveThread* a = new MULTIPR_GUI_SaveThread (this, mMULTIPRObj, path);
+  a->start();
+
+  // save progress
+  //mProgress = new MULTIPR_GUI_ProgressCallbackDlg (getApp()->desktop());
+  //mProgress->start("Save mesh", 100);
+  if (mProgress == NULL)
+    mProgress = new QProgressDialog ("Save mesh", "Cancel", /*totalSteps*/100, getApp()->desktop());
+  //mProgress->setProgress(0);
+  //mProgress->init(100);
+  mTimer->start(500); // 0.5 seconds timer
+
+  //QApplication::restoreOverrideCursor();
 }
 
+void MULTIPR_GUI::timerDone()
+{
+  int progress = mMULTIPRObj->getSaveProgress();
+  if (mProgress != NULL) {
+    mProgress->setProgress(progress);
 
+    if (progress >= 100) {
+      mTimer->stop();
+    }
+  }
+}
 
 void MULTIPR_GUI::retrieveSelectedParts()
 {
     mSelectedParts.clear();
 
-    QStringList userSelection;    
+    QStringList userSelection;
     selected(userSelection, true);
     for (QStringList::const_iterator it = userSelection.begin(), last = userSelection.end(); it != last; it++)
     {
@@ -621,7 +782,8 @@ bool MULTIPR_GUI::removeLowerResolution()
     // for each selected part, check if there are lower resolution
     // and then propose to remove them before performing new process
     QStringList partNameLowerResolution;
-    for (QStringList::const_iterator it = mSelectedParts.begin(), last = mSelectedParts.end(); it != last; it++)
+    for (QStringList::const_iterator it = mSelectedParts.begin(), last = mSelectedParts.end();
+         it != last; it++)
     {
         const QString& partName = (*it);
         QString partNameLow = partName + "_LOW";
@@ -658,7 +820,8 @@ bool MULTIPR_GUI::removeLowerResolution()
         
         try
         {
-            for (QStringList::const_iterator it = partNameLowerResolution.begin(), last = partNameLowerResolution.end(); it != last; it++)
+            for (QStringList::const_iterator it = partNameLowerResolution.begin(),
+                   last = partNameLowerResolution.end(); it != last; it++)
             {
                 const QString& partName = (*it);
                 cout << "Remove " << partName.latin1() << endl;
@@ -678,6 +841,7 @@ bool MULTIPR_GUI::removeLowerResolution()
         QApplication::restoreOverrideCursor();
         
         getApp()->updateObjectBrowser();
+        getApp()->updateActions();
     }
     
     return true;
@@ -688,8 +852,8 @@ bool MULTIPR_GUI::removeLowerResolution()
 // Super class Data Object implementation
 //*****************************************************************************
 
-MULTIPR_GUI_DataObject::MULTIPR_GUI_DataObject(SUIT_DataObject* parent, const char* name) : 
-    LightApp_DataObject(parent),
+MULTIPR_GUI_DataObject::MULTIPR_GUI_DataObject (SUIT_DataObject* parent, const char* name)
+  : LightApp_DataObject(parent),
     CAM_DataObject(parent)
 {
     mName = name;
@@ -733,8 +897,10 @@ QString MULTIPR_GUI_DataObject::toolTip() const
 // Class Data Object Module implementation
 //*****************************************************************************
 
-MULTIPR_GUI_DataObject_Module::MULTIPR_GUI_DataObject_Module(CAM_DataModel* dm, SUIT_DataObject* parent, const char* name) : 
-    MULTIPR_GUI_DataObject(parent, name),
+MULTIPR_GUI_DataObject_Module::MULTIPR_GUI_DataObject_Module (CAM_DataModel* dm,
+                                                              SUIT_DataObject* parent,
+                                                              const char* name)
+  : MULTIPR_GUI_DataObject(parent, name),
     LightApp_ModuleObject(dm, parent),
     CAM_DataObject(parent)
 {
@@ -776,8 +942,8 @@ QString MULTIPR_GUI_DataObject_Module::toolTip() const
 // Class Data Object Mesh implementation
 //*****************************************************************************
 
-MULTIPR_GUI_DataObject_Mesh::MULTIPR_GUI_DataObject_Mesh(SUIT_DataObject* parent, const char* name) : 
-    MULTIPR_GUI_DataObject(parent, name),
+MULTIPR_GUI_DataObject_Mesh::MULTIPR_GUI_DataObject_Mesh (SUIT_DataObject* parent, const char* name)
+  : MULTIPR_GUI_DataObject(parent, name),
     CAM_DataObject(parent)
 {
     // do nothing!
@@ -812,8 +978,9 @@ QString MULTIPR_GUI_DataObject_Mesh::toolTip() const
 // Class Data Object Part implementation
 //*****************************************************************************
 
-MULTIPR_GUI_DataObject_Part::MULTIPR_GUI_DataObject_Part(SUIT_DataObject* parent, const char* name, const char* info) : 
-    MULTIPR_GUI_DataObject(parent, name),
+MULTIPR_GUI_DataObject_Part::MULTIPR_GUI_DataObject_Part (SUIT_DataObject* parent,
+                                                          const char* name, const char* info)
+  : MULTIPR_GUI_DataObject(parent, name),
     CAM_DataObject(parent)
 {
     mMeshName    = "";
@@ -875,8 +1042,9 @@ QString MULTIPR_GUI_DataObject_Part::toolTip() const
 // Class Data Object Resolution implementation
 //*****************************************************************************
 
-MULTIPR_GUI_DataObject_Resolution::MULTIPR_GUI_DataObject_Resolution(SUIT_DataObject* parent, const char* name, const char* info) : 
-    MULTIPR_GUI_DataObject_Part(parent, name, info),
+MULTIPR_GUI_DataObject_Resolution::MULTIPR_GUI_DataObject_Resolution (SUIT_DataObject* parent,
+                                                                      const char* name, const char* info)
+  : MULTIPR_GUI_DataObject_Part(parent, name, info),
     CAM_DataObject(parent)
 {
     // do nothing!
@@ -911,98 +1079,201 @@ QString MULTIPR_GUI_DataObject_Resolution::toolTip() const
 // Data Model
 //*****************************************************************************
 
-MULTIPR_GUI_DataModel::MULTIPR_GUI_DataModel(CAM_Module* module) : 
-    LightApp_DataModel(module)
+MULTIPR_GUI_DataModel::MULTIPR_GUI_DataModel(CAM_Module* module)
+  //: LightApp_DataModel(module)
+  : SalomeApp_DataModel(module)
 {
     mMULTIPR_GUI = dynamic_cast<MULTIPR_GUI*>(module);
 }
 
-
 MULTIPR_GUI_DataModel::~MULTIPR_GUI_DataModel()
 {
     // do nothing!
 }
 
 
+void MULTIPR_GUI_DataModel::update (LightApp_DataObject*, LightApp_Study* theStudy)
+{
+  LightApp_ModuleObject* modelRoot = dynamic_cast<LightApp_ModuleObject*>( root() );
+  DataObjectList ch;
+  QMap<SUIT_DataObject*,int> aMap;
+  if( modelRoot )
+  {
+    ch = modelRoot->children();
+    for ( DataObjectListIterator it( ch ); it.current(); ++it )
+      it.current()->setParent( 0 );
+  }
+
+  buildAll(theStudy);
+
+  modelRoot = dynamic_cast<LightApp_ModuleObject*>( root() );
+  if( modelRoot )
+  {
+    DataObjectList new_ch = modelRoot->children();
+    for ( DataObjectListIterator it1( new_ch ); it1.current(); ++it1 )
+      aMap.insert( it1.current(), 0 );
+  }
+
+  updateWidgets();
+
+  for( DataObjectListIterator it( ch ); it.current(); ++it )
+    if( !aMap.contains( it.current() ) )
+      delete it.current();
+}
+
 void MULTIPR_GUI_DataModel::build()
 {
-    try
+}
+
+void MULTIPR_GUI_DataModel::buildAll (LightApp_Study* theStudy)
+{
+  try
+  {
+    SalomeApp_Study* aSAStudy = dynamic_cast<SalomeApp_Study*>(theStudy);
+    if (!aSAStudy)
+      aSAStudy = dynamic_cast<SalomeApp_Study*>(getModule()->getApp()->activeStudy());
+
+    if (!aSAStudy) return;
+
+    MULTIPR_GUI_DataObject_Module* modelRoot = dynamic_cast<MULTIPR_GUI_DataObject_Module*>(root());
+    if (!modelRoot)  
+    {  
+      // root is not set yet
+      modelRoot = new MULTIPR_GUI_DataObject_Module(this, NULL, "MULTIPR");
+      setRoot(modelRoot);
+    }
+
+    // find SObject in Study
+    MULTIPR_ORB::MULTIPR_Obj_ptr obj = MULTIPR_ORB::MULTIPR_Obj::_nil();
+
+    _PTR(SComponent) aSComp = aSAStudy->studyDS()->FindComponent(module()->name());
+    if (aSComp)
     {
-        MULTIPR_GUI_DataObject_Module* modelRoot = dynamic_cast<MULTIPR_GUI_DataObject_Module*>(root());
-        
-        if (!modelRoot)  
-        {  
-            // root is not set yet
-            modelRoot = new MULTIPR_GUI_DataObject_Module(this, NULL, "MULTIPR");
-            setRoot(modelRoot);
+      _PTR(ChildIterator) it (aSAStudy->studyDS()->NewChildIterator(aSComp));
+      if (it->More())
+      {
+        _PTR(SObject) aSObj = it->Value();
+        string anIOR = aSObj->GetIOR();
+        if (!anIOR.empty())
+        {
+          CORBA::Object_var anObj = mMULTIPR_GUI->getApp()->orb()->string_to_object(anIOR.c_str());
+          obj = MULTIPR_ORB::MULTIPR_Obj::_narrow(anObj);
+
+          // set Object to MULTIPR_GUI
+          mMULTIPR_GUI->setMULTIPRObj(obj);
         }
-        
-        MULTIPR_ORB::MULTIPR_Obj_ptr obj = mMULTIPR_GUI->getMULTIPRObj();
-        
-        if (obj != NULL)
+        //CORBA::Object_var anObj = aSObj->GetObject();
+        //obj = MULTIPR_ORB::MULTIPR_Obj::_narrow(anObj);
+        //if (!CORBA::is_nil(obj))
+        //{
+        //  // set Object to MULTIPR_GUI
+        //  mMULTIPR_GUI->setMULTIPRObj(obj);
+        //}
+      }
+
+      // remove Data Objects, automatically built for not loaded MULTIPR module
+      // by SalomeApp_Application::updateObjectBrowser
+      if (aSAStudy->root())
+      {
+        DataObjectList ch_comp;
+        aSAStudy->root()->children(ch_comp);
+        DataObjectList::const_iterator anIt_comp = ch_comp.begin(), aLast_comp = ch_comp.end();
+        for (; anIt_comp != aLast_comp; anIt_comp++)
         {
-            MULTIPR_ORB::string_array* listParts = obj->getParts();
-            
-            if (listParts->length() >= 1)
-            {
-                const char* strPartName0 = (*listParts)[0];
-                char* strPartInfo0 = obj->getPartInfo(strPartName0);
-                
-                char   lMeshName[256];
-                int    lId;
-                char   lPartName[256];
-                char   lPath[256];
-                char   lMEDFileName[256];    
-                
-                // parse infos
-                int ret = sscanf(strPartInfo0, "%s %d %s %s %s", 
-                    lMeshName,
-                    &lId,
-                    lPartName,
-                    lPath,
-                    lMEDFileName);
-                    
-                if (ret != 5) 
-                {
-                    cout << "MULTIPR: build() tree; error while parsing part info" << endl;
-                    std::runtime_error("MULTIPR: build() tree; error while parsing part info");
-                    return;
-                }
-                
-                MULTIPR_GUI_DataObject_Mesh* dataObjectMesh = new MULTIPR_GUI_DataObject_Mesh(modelRoot, lMeshName);
-                
-                MULTIPR_GUI_DataObject_Part* dataObjectPart_prev = NULL;
-                
-                for (int i = 0 ; i < listParts->length() ; i++)
-                {
-                    const char* strItem = (*listParts)[i];
-                    char* strPartInfo = obj->getPartInfo(strItem);
-                    
-                    // parse infos
-                    int ret = sscanf(strPartInfo, "%s %d %s %s %s", 
-                        lMeshName,
-                        &lId,
-                        lPartName,
-                        lPath,
-                        lMEDFileName);
-                    
-                    if (ret != 5) return;
-                
-                    if ((strstr(lPartName,"_MED") != NULL) || (strstr(lPartName,"_LOW") != NULL))
-                    {
-                        new MULTIPR_GUI_DataObject_Resolution(dataObjectPart_prev, strItem, strPartInfo);
-                    }
-                    else
-                    {
-                        dataObjectPart_prev = new MULTIPR_GUI_DataObject_Part(dataObjectMesh, strItem, strPartInfo);
-                    }
-                }
-            }
+          LightApp_DataObject* dobj = dynamic_cast<LightApp_DataObject*>(*anIt_comp);
+          if (dobj && dobj->name() == aSComp->GetName().c_str())
+          {
+            //SalomeApp_DataModelSync sync (aSAStudy->studyDS(), aSAStudy->root());
+            //sync.deleteItemWithChildren(dobj);
+            DataObjectList ch_obj;
+            dobj->children(ch_obj);
+            DataObjectList::const_iterator anIt_obj = ch_obj.begin(), aLast_obj = ch_obj.end();
+            for (; anIt_obj != aLast_obj; anIt_obj++)
+              // delete data object of each SObject
+              delete (*anIt_obj);
+
+            // delete data object of SComponent itself
+            delete dobj;
+            break;
+          }
         }
+      }
     }
-    catch (...)
+
+    // build data tree
+    if (!CORBA::is_nil(obj))
     {
+      // MED file object
+      std::string lMEDFile = obj->getFilename();
+      std::string lMEDFileName = multipr::getFilenameWithoutPath(lMEDFile.c_str());
+      MULTIPR_GUI_DataObject_Mesh* dataObjectMED =
+        new MULTIPR_GUI_DataObject_Mesh(modelRoot, lMEDFileName.c_str());
+
+      // MESH object
+      MULTIPR_ORB::string_array* listParts = obj->getParts();
+
+      if (listParts->length() >= 1)
+      {
+        const char* strPartName0 = (*listParts)[0];
+        char* strPartInfo0 = obj->getPartInfo(strPartName0);
+
+        char   lMeshName[256];
+        int    lId;
+        char   lPartName[256];
+        char   lPath[256];
+        char   lMEDFileName[256];    
+
+        // parse infos
+        int ret = sscanf(strPartInfo0, "%s %d %s %s %s", 
+                         lMeshName,
+                         &lId,
+                         lPartName,
+                         lPath,
+                         lMEDFileName);
+
+        if (ret != 5) 
+        {
+          cout << "MULTIPR: build() tree; error while parsing part info" << endl;
+          std::runtime_error("MULTIPR: build() tree; error while parsing part info");
+          return;
+        }
+
+        MULTIPR_GUI_DataObject_Mesh* dataObjectMesh =
+          new MULTIPR_GUI_DataObject_Mesh(dataObjectMED, lMeshName);
+
+        // PART and RESOLUTION objects
+        MULTIPR_GUI_DataObject_Part* dataObjectPart_prev = NULL;
+
+        for (int i = 0 ; i < listParts->length() ; i++)
+        {
+          const char* strItem = (*listParts)[i];
+          char* strPartInfo = obj->getPartInfo(strItem);
+
+          // parse infos
+          int ret = sscanf(strPartInfo, "%s %d %s %s %s", 
+                           lMeshName,
+                           &lId,
+                           lPartName,
+                           lPath,
+                           lMEDFileName);
+
+          if (ret != 5) return;
+
+          if ((strstr(lPartName,"_MED") != NULL) || (strstr(lPartName,"_LOW") != NULL))
+          {
+            new MULTIPR_GUI_DataObject_Resolution(dataObjectPart_prev, strItem, strPartInfo);
+          }
+          else
+          {
+            dataObjectPart_prev = new MULTIPR_GUI_DataObject_Part(dataObjectMesh, strItem, strPartInfo);
+          }
+        }
+      }
     }
+  }
+  catch (...)
+  {
+  }
 }
 
 
index bab9f4a18e021f54a355e3599bf9bed027009e06..a63dfec53e5d068ecd61dadf239b22123efd43c2 100644 (file)
@@ -21,7 +21,8 @@
 
 #include <SalomeApp_Module.h>
 #include <LightApp_DataObject.h>
-#include <LightApp_DataModel.h>
+//#include <LightApp_DataModel.h>
+#include <SalomeApp_DataModel.h>
 
 #include <SALOMEconfig.h>
 #include CORBA_CLIENT_HEADER(MULTIPR)
@@ -47,6 +48,9 @@ class QLineEdit;
 class QSpinBox;
 class QPushButton;
 
+class QTimer;
+//class MULTIPR_GUI_ProgressCallbackDlg;
+class QProgressDialog;
 
 //*****************************************************************************
 // Class MULTIPR_GUI
@@ -70,6 +74,7 @@ public:
     void windows(QMap<int, int>&) const;
     
     MULTIPR_ORB::MULTIPR_Obj_ptr getMULTIPRObj();
+    void setMULTIPRObj (MULTIPR_ORB::MULTIPR_Obj_ptr theObj);
     
     SalomeApp_Application* getAppli() const;
     
@@ -90,11 +95,13 @@ protected slots:
     void OnDecimate();
     void OnRemove();
     void OnSave();
-    
+
+    void timerDone(); // update saving progress dialog
+
 protected:
 
     virtual CAM_DataModel* createDataModel();
-    
+
     void retrieveSelectedParts();
     bool isPartExist(const char* partName);
     bool removeLowerResolution();
@@ -115,7 +122,11 @@ private:
     QString                      mMEDFileName;
     QStringList                  mSelectedParts;
     MULTIPR_ORB::MULTIPR_Obj_ptr mMULTIPRObj;
-  
+
+    QProgressDialog*             mProgress;
+    //MULTIPR_GUI_ProgressCallbackDlg* mProgress;
+    QTimer*                      mTimer;
+
 }; // class MULTIPR_GUI
 
 
@@ -223,17 +234,21 @@ public:
 // Class MULTIPR_GUI_DataModel
 //*****************************************************************************
 
-class MULTIPR_GUI_DataModel : public LightApp_DataModel
+//class MULTIPR_GUI_DataModel : public LightApp_DataModel
+class MULTIPR_GUI_DataModel : public SalomeApp_DataModel
 {
 public:
 
     MULTIPR_GUI_DataModel(CAM_Module*);
     virtual ~MULTIPR_GUI_DataModel();
 
+    virtual void update (LightApp_DataObject* = 0, LightApp_Study* = 0);
+
 protected:
 
     virtual void build();
-    
+    void buildAll (LightApp_Study* = 0);
+
 private:
 
     MULTIPR_GUI* mMULTIPR_GUI;
@@ -244,4 +259,3 @@ private:
 
 
 // EOF
-
index 0e2667b4f51d826472cd127171d8f2453007a8eb..1549a4df3415619a8814cc5763d536a49ef17560 100644 (file)
 #include <qimage.h>
 #include <qpixmap.h>
 
+// MED include
+extern "C"
+{
+    #include "med.h"
+}
 
 using namespace std;
 
@@ -227,7 +232,7 @@ void MULTIPR_GUI_Partition2Dlg::accept()
         {
             const QString& partName = (*it);
             //cout << "Split " << partName.latin1() << " #parts=" << nbParts << " splitter=" << strSplitter << endl;
-            mModule->getMULTIPRObj()->partitionneGrain(partName.latin1(), nbParts, partitionner);
+            mModule->getMULTIPRObj()->partitionneGroupe(partName.latin1(), nbParts, partitionner);
         }
         
     }
@@ -259,9 +264,8 @@ MULTIPR_GUI_DecimateDlg::MULTIPR_GUI_DecimateDlg(MULTIPR_GUI* theModule) :
         WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu)
 {
     mModule = theModule;
-    
     buttonGroupSelectField = new QButtonGroup( this, "buttonGroupSelectField" );
-    buttonGroupSelectField->setGeometry( QRect( 10, 10, 450, 140 ) );
+    buttonGroupSelectField->setGeometry( QRect( 10, 10, 710, 140 ) );
 
     textLabelSelectFieldName = new QLabel( buttonGroupSelectField, "textLabelSelectFieldName" );
     textLabelSelectFieldName->setGeometry( QRect( 30, 30, 141, 31 ) );
@@ -269,27 +273,34 @@ MULTIPR_GUI_DecimateDlg::MULTIPR_GUI_DecimateDlg(MULTIPR_GUI* theModule) :
     textLabelSelectFieldIteration = new QLabel( buttonGroupSelectField, "textLabelSelectFieldIteration" );
     textLabelSelectFieldIteration->setGeometry( QRect( 30, 80, 111, 31 ) );
 
-    MULTIPR_ORB::string_array* listFields = theModule->getMULTIPRObj()->getFields();
+    const QStringList& partsList = mModule->getSelectedParts();
+    // Lets get the fields !.
+    QString allParts = partsList.join("|");
+    MULTIPR_ORB::string_array* listFields = theModule->getMULTIPRObj()->getFields(allParts.latin1());
     int maxIteration = 0;
-    for (int i=0 ; i<listFields->length() ; i++)
+    int i, j;
+    for (i = 0 ; i < listFields->length() ; ++i)
     {
-        const char* strItem = (*listFields)[i];
-        CORBA::Long nbIteration = theModule->getMULTIPRObj()->getTimeStamps(strItem);
+        char* strItem = (*listFields)[i];
+        for (j = 0; strItem[j] && strItem[j] != ' '; ++j);
+        strItem[j] = 0;
+        CORBA::Long nbIteration = theModule->getMULTIPRObj()->getTimeStamps(allParts.latin1(), strItem);
+        strItem[j] = ' ';
         if (nbIteration > maxIteration) 
         {
             maxIteration = nbIteration;
         }
     }
-    
+
     comboBoxSelectFieldIteration = new QComboBox( FALSE, buttonGroupSelectField, "comboBoxSelectFieldIteration" );
-    comboBoxSelectFieldIteration->setGeometry( QRect( 150, 80, 280, 40 ) );
+    comboBoxSelectFieldIteration->setGeometry( QRect( 150, 80, 540, 40 ) );
     for (int i=1 ; i<=maxIteration ; i++)
     {
         comboBoxSelectFieldIteration->insertItem(QString::number(i));
     }
 
     comboBoxSelectFieldName = new QComboBox( FALSE, buttonGroupSelectField, "comboBoxSelectFieldName" );
-    comboBoxSelectFieldName->setGeometry( QRect( 150, 30, 280, 40 ) );
+    comboBoxSelectFieldName->setGeometry( QRect( 150, 30, 540, 40 ) );
     for (int i=0 ; i<listFields->length() ; i++)
     {
         const char* strItem = (*listFields)[i];
@@ -299,17 +310,18 @@ MULTIPR_GUI_DecimateDlg::MULTIPR_GUI_DecimateDlg(MULTIPR_GUI* theModule) :
     QToolTip::add( comboBoxSelectFieldName, tr( "only scalar fields are listed (multi-component fields are not displayed)" ) );
 
     buttonGroupSelectFilter = new QButtonGroup( this, "buttonGroupSelectFilter" );
-    buttonGroupSelectFilter->setGeometry( QRect( 10, 160, 450, 90 ) );
+    buttonGroupSelectFilter->setGeometry( QRect( 10, 160, 710, 90 ) );
 
     textLabelSelectFilter = new QLabel( buttonGroupSelectFilter, "textLabelSelectFilter" );
     textLabelSelectFilter->setGeometry( QRect( 30, 30, 101, 31 ) );
 
     comboBoxSelectFilter = new QComboBox( FALSE, buttonGroupSelectFilter, "comboBoxSelectFilter" );
-    comboBoxSelectFilter->setGeometry( QRect( 150, 30, 280, 40 ) );
+    comboBoxSelectFilter->setGeometry( QRect( 150, 30, 540, 40 ) );
     comboBoxSelectFilter->insertItem("Filtre_GradientMoyen");
+       comboBoxSelectFilter->insertItem("Filtre_Direct");
 
     buttonGroupParameters = new QButtonGroup( this, "buttonGroupParameters" );
-    buttonGroupParameters->setGeometry( QRect( 10, 260, 450, 210 ) );
+    buttonGroupParameters->setGeometry( QRect( 10, 260, 710, 210 ) );
 
     textLabelTMed = new QLabel( buttonGroupParameters, "textLabelTMed" );
     textLabelTMed->setGeometry( QRect( 20, 40, 242, 30 ) );
@@ -324,29 +336,54 @@ MULTIPR_GUI_DecimateDlg::MULTIPR_GUI_DecimateDlg(MULTIPR_GUI* theModule) :
     textLabelBoxing->setGeometry( QRect( 20, 160, 241, 30 ) );
 
     lineEditTMed = new QLineEdit( buttonGroupParameters, "lineEditTMed" );
-    lineEditTMed->setGeometry( QRect( 320, 40, 111, 30 ) );
+    lineEditTMed->setGeometry( QRect( 580, 40, 111, 30 ) );
 
     lineEditTLow = new QLineEdit( buttonGroupParameters, "lineEditTLow" );
-    lineEditTLow->setGeometry( QRect( 320, 80, 111, 30 ) );
+    lineEditTLow->setGeometry( QRect( 580, 80, 111, 30 ) );
 
     lineEditRadius = new QLineEdit( buttonGroupParameters, "lineEditRadius" );
-    lineEditRadius->setGeometry( QRect( 320, 120, 111, 30 ) );
+    lineEditRadius->setGeometry( QRect( 580, 120, 111, 30 ) );
 
     spinBoxBoxing = new QSpinBox( buttonGroupParameters, "spinBoxBoxing" );
-    spinBoxBoxing->setGeometry( QRect( 320, 160, 111, 30 ) );
+    spinBoxBoxing->setGeometry( QRect( 580, 160, 111, 30 ) );
     spinBoxBoxing->setMaxValue( 200 );
     spinBoxBoxing->setMinValue( 2 );
     spinBoxBoxing->setValue( 100 );
     QToolTip::add( spinBoxBoxing, tr( "grid: number of cells along each axis" ) );
 
+       infoGroup = new QButtonGroup(this, "infoGroup");
+       infoGroup->setGeometry( QRect( 10, 480, 710, 60 ) );
+
+       char* stats;
+       int tmp;
+       // Accumulator used to display the number of meshes in the current selection.
+       int acum = 0;
+    for (QStringList::const_iterator it = partsList.begin(), last = partsList.end(); it != last; it++)
+    {
+               const QString& partName = (*it);
+               stats = theModule->getMULTIPRObj()->getMEDInfo(partName.latin1());
+               sscanf(stats, "%d", &tmp);
+               acum += tmp;
+    }
+       
+       char buf[512];
+       sprintf(buf, "%d", acum);
+       textLabelInfo = new QLabel( infoGroup, "textLabelInfo");
+       textLabelInfo->setText("Number of cells:");
+    textLabelInfo->setGeometry( QRect( 20, 10, 242, 30 ) );    
+       textLabelInfoValue = new QLabel( infoGroup, "textLabelInfoValue");
+       textLabelInfoValue->setAlignment(AlignRight);
+       textLabelInfoValue->setText(buf);
+    textLabelInfoValue->setGeometry( QRect( 400, 10, 290, 30 ) );      
+                       
     buttonGroupProcess = new QButtonGroup( this, "buttonGroupProcess" );
-    buttonGroupProcess->setGeometry( QRect( 10, 480, 450, 60 ) );
+    buttonGroupProcess->setGeometry( QRect( 10, 580, 710, 60 ) );
 
     pushButtonOK = new QPushButton( buttonGroupProcess, "pushButtonOK" );
     pushButtonOK->setGeometry( QRect( 10, 10, 110, 41 ) );
     
     pushButtonCancel = new QPushButton( buttonGroupProcess, "pushButtonCancel" );
-    pushButtonCancel->setGeometry( QRect( 321, 10, 110, 41 ) );
+    pushButtonCancel->setGeometry( QRect( 581, 10, 110, 41 ) );
     pushButtonCancel->setAccel( QKeySequence( tr( "Esc" ) ) );
     
     setCaption( tr( "Decimation" ) );
@@ -370,7 +407,7 @@ MULTIPR_GUI_DecimateDlg::MULTIPR_GUI_DecimateDlg(MULTIPR_GUI* theModule) :
     pushButtonOK->setText( tr("OK") );
     
     pushButtonThresholdAuto = new QPushButton( buttonGroupParameters, "pushButtonThresholdAuto" );
-    pushButtonThresholdAuto->setGeometry( QRect( 260, 80, 50, 30 ) );
+    pushButtonThresholdAuto->setGeometry( QRect( 520, 80, 50, 30 ) );
     QFont pushButtonThresholdAuto_font(  pushButtonThresholdAuto->font() );
     pushButtonThresholdAuto_font.setPointSize( 11 );
     pushButtonThresholdAuto->setFont( pushButtonThresholdAuto_font ); 
@@ -378,20 +415,21 @@ MULTIPR_GUI_DecimateDlg::MULTIPR_GUI_DecimateDlg(MULTIPR_GUI* theModule) :
     QToolTip::add( pushButtonThresholdAuto, tr( "compute extremum for gradient (set medium=MIN and low=MAX)" ) );
 
     pushButtonRadiusAuto = new QPushButton( buttonGroupParameters, "pushButtonRadiusAuto" );
-    pushButtonRadiusAuto->setGeometry( QRect( 260, 120, 50, 30 ) );
+    pushButtonRadiusAuto->setGeometry( QRect( 520, 120, 50, 30 ) );
     QFont pushButtonRadiusAuto_font(  pushButtonRadiusAuto->font() );
     pushButtonRadiusAuto_font.setPointSize( 11 );
     pushButtonRadiusAuto->setFont( pushButtonRadiusAuto_font ); 
     pushButtonRadiusAuto->setText( tr( "auto" ) );
     QToolTip::add( pushButtonRadiusAuto, tr( "set radius automatically (average #neighbours equal to 8)" ) );
     
-    resize( QSize(470, 554).expandedTo(minimumSizeHint()) );
+    resize( QSize(730, 654).expandedTo(minimumSizeHint()) );
     clearWState( WState_Polished );
     
     connect(pushButtonOK,            SIGNAL(clicked()), this, SLOT(accept()));
     connect(pushButtonCancel,        SIGNAL(clicked()), this, SLOT(reject()));
     connect(pushButtonRadiusAuto,    SIGNAL(clicked()), this, SLOT(OnRadiusAuto()));
     connect(pushButtonThresholdAuto, SIGNAL(clicked()), this, SLOT(OnThresholdAuto()));
+    connect(comboBoxSelectFilter,    SIGNAL(activated(const QString &)), this, SLOT(selectField(const QString &)));
 }
 
 
@@ -405,11 +443,87 @@ MULTIPR_GUI_DecimateDlg::~MULTIPR_GUI_DecimateDlg()
 
 
 void MULTIPR_GUI_DecimateDlg::accept()
-{    
-    const char* strFieldName = comboBoxSelectFieldName->currentText().latin1();
-    const char* strFieldIt   = comboBoxSelectFieldIteration->currentText().latin1();
+{
+    const char*        strFieldNameTmp = comboBoxSelectFieldName->currentText().latin1();
+    const char*        strFieldIt   = comboBoxSelectFieldIteration->currentText().latin1();
     int fieldIteration = atoi(strFieldIt);
-    
+
+    char               strFieldName[MED_TAILLE_NOM + 1];
+    const              char* filterName = comboBoxSelectFilter->currentText().latin1();
+    char               params[MULTIPR_GUI_MAX_PARAMS_LENGTH];
+    int                        i;
+
+    // Get the field name.
+    strncpy(strFieldName, strFieldNameTmp, MED_TAILLE_NOM);
+    strFieldName[MED_TAILLE_NOM] = '\0';
+    for (i = 0; strFieldName[i] && strFieldName[i] != ' '; ++i);
+    strFieldName[i] = 0;
+
+    // Fill the corresponding filter parameters string.
+    if (strcmp(filterName, "Filtre_GradientMoyen") == 0)
+    {
+      if (this->setGradAvgFilterParams(params) == false)
+      {
+        return ;
+      }
+    }
+    else if (strcmp(filterName, "Filtre_Direct") == 0)
+    {
+      if (this->setDirectFilterParams(params) == false)
+      {
+        return ;
+      }
+    }
+    else
+    {
+      SUIT_MessageBox::error1(mModule->getAppli()->desktop(),
+                              "Decimation error", 
+                              "Unknown filter name.", 
+                              tr("OK") );
+    }
+
+    QApplication::setOverrideCursor(Qt::waitCursor);
+
+    MULTIPR_ORB::string_array* list = NULL;
+    try
+    {
+      const QStringList& partsList = mModule->getSelectedParts();
+      for (QStringList::const_iterator it = partsList.begin(), last = partsList.end(); it != last; it++)
+      {
+        const QString& partName = (*it);
+
+        list = mModule->getMULTIPRObj()->decimePartition(partName.latin1(),
+                                                         strFieldName,
+                                                         fieldIteration,
+                                                         filterName,
+                                                         params);
+      }
+    }
+    catch(...)
+    {
+        SUIT_MessageBox::error1( 
+            mModule->getAppli()->desktop(),
+            "Decimation error",
+            "Error while decimating selected part(s)",
+            tr("OK") );
+    }
+
+    if (list != NULL && list->length() >= 4)
+    {
+      const char* rate = (*list)[list->length() - 1];
+      SUIT_MessageBox::info1(mModule->getAppli()->desktop(),
+                             "Compression rate", 
+                             rate,
+                             tr("OK") );
+    }
+    QApplication::restoreOverrideCursor();
+    QDialog::accept();
+}
+
+bool MULTIPR_GUI_DecimateDlg::setGradAvgFilterParams(char* pParams)
+{
+    int boxing = spinBoxBoxing->value();
+
     double thresholdMed;
     int ret = sscanf(lineEditTMed->text().latin1(), "%lf", &thresholdMed);
     if ((ret != 1) || (thresholdMed <= 0.0f))
@@ -420,7 +534,7 @@ void MULTIPR_GUI_DecimateDlg::accept()
             "Invalid medium threshold (should be > 0.0)", 
             tr("OK") );
             
-        return;
+        return false;
     }
 
     double thresholdLow;
@@ -433,7 +547,7 @@ void MULTIPR_GUI_DecimateDlg::accept()
             "Invalid low threshold (should be > 0.0)", 
             tr("OK") );
             
-        return;
+        return false;
     }
     
     if (thresholdMed >= thresholdLow)
@@ -444,7 +558,7 @@ void MULTIPR_GUI_DecimateDlg::accept()
             "Medium threshold must be < low threshold", 
             tr("OK") );
             
-        return;
+        return false;
     }
 
     double radius;
@@ -457,43 +571,89 @@ void MULTIPR_GUI_DecimateDlg::accept()
             "Invalid radius (should be > 0.0)", 
             tr("OK") );
             
-        return;
+        return false;
     }
-    
-    QApplication::setOverrideCursor(Qt::waitCursor);
-    
-    try
+
+    sprintf(pParams, "%lf %lf %lf %d", thresholdMed, thresholdLow, radius, boxing);
+
+    return true;
+}
+
+bool MULTIPR_GUI_DecimateDlg::setDirectFilterParams(char* pParams)
+{
+    int boxing = spinBoxBoxing->value();
+
+    double thresholdMed;
+    int ret = sscanf(lineEditTMed->text().latin1(), "%lf", &thresholdMed);
+    if (ret != 1)
     {
-        const QStringList& partsList = mModule->getSelectedParts();
-        for (QStringList::const_iterator it = partsList.begin(), last = partsList.end(); it != last; it++)
-        {
-            const QString& partName = (*it);
-            
-            mModule->getMULTIPRObj()->setBoxing(spinBoxBoxing->value());
+        SUIT_MessageBox::error1( 
+            mModule->getAppli()->desktop(),
+            "Decimation parameters error", 
+            "Invalid medium threshold.", 
+            tr("OK") );
             
-            mModule->getMULTIPRObj()->decimePartition(
-                partName.latin1(),
-                strFieldName,
-                fieldIteration,
-                comboBoxSelectFilter->currentText().latin1(),
-                thresholdMed,
-                thresholdLow,
-                radius);
-        }
+        return false;
     }
-    catch(...)
+
+    double thresholdLow;
+    ret = sscanf(lineEditTLow->text().latin1(), "%lf", &thresholdLow);
+    if (ret != 1)
     {
         SUIT_MessageBox::error1( 
             mModule->getAppli()->desktop(),
-            "Decimation error", 
-            "Error while decimating selected part(s)", 
+            "Decimation parameters error", 
+            "Invalid low threshold.",
             tr("OK") );
+            
+        return false;
     }
     
-    QApplication::restoreOverrideCursor();
-    QDialog::accept();
+    if (thresholdMed >= thresholdLow)
+    {
+        SUIT_MessageBox::error1( 
+            mModule->getAppli()->desktop(),
+            "Decimation parameters error", 
+            "Medium threshold must be < low threshold", 
+            tr("OK") );
+            
+        return false;
+    }
+
+       sprintf(pParams, "%lf %lf", thresholdMed, thresholdLow);
+       
+       return true;
 }
 
+void MULTIPR_GUI_DecimateDlg::selectField(const QString& valueText)
+{
+       if (valueText == "Filtre_GradientMoyen")
+       {
+               lineEditRadius->show();
+               spinBoxBoxing->show();
+               pushButtonRadiusAuto->show();
+               textLabelRadius->show();
+       textLabelBoxing->show();
+               //pushButtonThresholdAuto->show();
+       }
+       else if (valueText == "Filtre_Direct")
+       {
+               lineEditRadius->hide();
+               spinBoxBoxing->hide();
+               pushButtonRadiusAuto->hide();
+               textLabelRadius->hide();
+       textLabelBoxing->hide();
+               //pushButtonThresholdAuto->hide();
+       }
+       else
+       {
+        SUIT_MessageBox::error1(
+            mModule->getAppli()->desktop(),
+            "Decimation error", 
+            "Unknown filter name.", 
+            tr("OK") );
+       }
+}
 
 void MULTIPR_GUI_DecimateDlg::reject()
 {
@@ -560,7 +720,8 @@ void MULTIPR_GUI_DecimateDlg::OnThresholdAuto()
     const char* strFieldIt  = comboBoxSelectFieldIteration->currentText().latin1();
     int fieldIteration = atoi(strFieldIt);
     char* strPartInfo0 = mModule->getMULTIPRObj()->getPartInfo(partsList[0].latin1());
-    
+    QString filterName = comboBoxSelectFilter->currentText();
+
     char   lMeshName[256];
     int    lId;
     char   lPartName[256];
@@ -576,46 +737,63 @@ void MULTIPR_GUI_DecimateDlg::OnThresholdAuto()
         lMEDFileName);
     
     QApplication::setOverrideCursor(Qt::waitCursor);
-
-    try
+    if (filterName == "Filtre_GradientMoyen")
     {
-        float radius;
-        ret = sscanf(lineEditRadius->text().latin1(), "%f", &radius);
-        if ((ret != 1) || (radius <= 0.0f))
+        try
+        {
+            float radius;
+            ret = sscanf(lineEditRadius->text().latin1(), "%f", &radius);
+            if ((ret != 1) || (radius <= 0.0f))
+            {
+                SUIT_MessageBox::error1( 
+                    mModule->getAppli()->desktop(),
+                    "Decimation parameters error", 
+                    "Invalid radius (should be > 0.0)", 
+                    tr("OK") );
+                    
+                return;
+            }
+            
+            char strParams[256];        
+            sprintf(strParams, "1 %f %d", radius, spinBoxBoxing->value());
+            
+            char* res = mModule->getMULTIPRObj()->evalDecimationParams(
+                lPartName,
+                comboBoxSelectFieldName->currentText().latin1(),
+                fieldIteration,
+                comboBoxSelectFilter->currentText().latin1(),
+                strParams);
+            
+            float gradMin, gradAvg, gradMax;
+            sscanf(res, "%f %f %f", &gradMin, &gradAvg, &gradMax);
+            
+            lineEditTMed->setText( QString::number(gradMin) );
+            lineEditTLow->setText( QString::number(gradMax) );
+        }
+        catch (...)
         {
-            SUIT_MessageBox::error1( 
-                mModule->getAppli()->desktop(),
-                "Decimation parameters error", 
-                "Invalid radius (should be > 0.0)", 
-                tr("OK") );
-                
-            return;
         }
-        
-        char strParams[256];        
-        sprintf(strParams, "1 %f %d", radius, spinBoxBoxing->value());
-        
-        char* res = mModule->getMULTIPRObj()->evalDecimationParams(
-            lPartName,
-            comboBoxSelectFieldName->currentText().latin1(),
-            fieldIteration,
-            comboBoxSelectFilter->currentText().latin1(),
-            strParams);
-        
-        float gradMin, gradAvg, gradMax;
-        sscanf(res, "%f %f %f", &gradMin, &gradAvg, &gradMax);
-        
-        lineEditTMed->setText( QString::number(gradMin) );
-        lineEditTLow->setText( QString::number(gradMax) );
     }
-    catch (...)
+    else if (filterName == "Filtre_Direct")
     {
+        float   lMin = 1.0f;
+        float   lMax = 2.0f;
+        
+        mModule->getMULTIPRObj()->getFieldMinMax(lPartName, comboBoxSelectFieldName->currentText().latin1(), lMin, lMax);
+        lineEditTMed->setText(QString::number(lMin));
+        lineEditTLow->setText(QString::number(lMax));
     }
-    
+    else
+       {
+        SUIT_MessageBox::error1(
+            mModule->getAppli()->desktop(),
+            "Decimation error", 
+            "Unknown filter name.", 
+            tr("OK") );
+       }
     QApplication::restoreOverrideCursor();
 }
 
-
 //*****************************************************************************
 // MULTIPR_GUI_ProgressCallbackDlg
 // QT dialog box used to display progress in time consuming task (e.g. save)
index 888cad70cbd8eb475c2814a50356011ee9fbeb9d..2b0c7f86441069c340e7836e6bbc587baba7e052 100644 (file)
@@ -45,7 +45,10 @@ class QPushButton;
 
 class MULTIPR_GUI;
 
-
+/**
+ * Max length for filter parameters string.
+ */
+#define MULTIPR_GUI_MAX_PARAMS_LENGTH 1024
 
 //*****************************************************************************
 // Class MULTIPR_GUI_Partition1Dlg
@@ -143,7 +146,10 @@ public:
     QPushButton* pushButtonOK;
     QPushButton* pushButtonThresholdAuto;
     QPushButton* pushButtonRadiusAuto;
-
+    QButtonGroup* infoGroup;
+    QLabel* textLabelInfo;
+    QLabel* textLabelInfoValue;
+       
 protected:
 
 protected slots:
@@ -151,10 +157,24 @@ protected slots:
     void reject();
     void OnRadiusAuto();
     void OnThresholdAuto();
+    void selectField(const QString & valueText);
 
 private:
     MULTIPR_GUI* mModule;
 
+    /**
+     * Create the parameter string for gradient average filter.
+     * \param pParams The parameter string to fill.
+     * \return True if the operation is successfull, false otherwise.
+     */
+    bool setGradAvgFilterParams(char* pParams);
+
+    /**
+     * Create the parameter string for direct filter.
+     * \param pParams The parameter string to fill.
+     * \return True if the operation is successfull, false otherwise.
+     */
+    bool setDirectFilterParams(char* pParams);
 };