Salome HOME
Copyright update 2021
[modules/med.git] / src / MEDCalc / gui / WorkspaceController.cxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // Author : Guillaume Boulant (EDF)
21
22 #include "WorkspaceController.hxx"
23 #include "QtHelper.hxx"
24 #include "MEDFactoryClient.hxx"
25 #include "MEDModule.hxx"
26 #include "XmedDataModel.hxx"
27 #include "DlgAlias.hxx"
28
29 #include <SALOMEconfig.h>
30 #include CORBA_CLIENT_HEADER(MEDEventListener)
31
32 #include <SalomeApp_Application.h>
33 #include <SALOME_LifeCycleCORBA.hxx>
34 #include <SUIT_FileDlg.h>
35 #include <SUIT_Desktop.h>
36 #include <SUIT_ResourceMgr.h>
37
38 #include <QTimer>
39 #include <QMessageBox>
40
41 #include "MEDLoader.hxx"
42 using namespace MEDCoupling;
43 #include "MEDDataManager_i.hxx"
44
45 /*!
46  * This class defines a DockWidget plugged in the SALOME application,
47  * and containing a tree view for rendering a hierarchical data
48  * model. This datamodel contains the objects used in the workspace.
49  */
50 WorkspaceController::WorkspaceController(MEDModule* salomeModule)
51   : TreeGuiManager(salomeModule->getApp(), "Workspace")
52 {
53   _salomeModule = salomeModule;
54   getDockWidgets()->getDockWidget()->setObjectName("medWorkspaceDock");
55
56   this->tabifyDockWidgets(false);
57
58   // -------------------------------------------------------------
59   // Setup the MEDEventListener to manage notification from the
60   // python console.
61
62   // We create a MEDEventListener CORBA object inside this GUI class
63   // with the role of listening events coming from the python console
64   // (or even the components if needed). The events arising in the
65   // python console are send as CORBA request to this CORBA
66   // servant. Then this object can process the event by notifying the
67   // GUI of something to update for example (using signals and slots
68   // of course).
69   _medEventListener = MEDEventListener_i::getInstance();
70   MEDCALC::MEDEventListener_ptr medEventListenerServant = _medEventListener->_this();
71
72   // We store the IOR inside the MEDDataManager to share this data
73   // with other parts of the application, in particular the python
74   // console that could retrieve this IOR using the
75   // getEventListenerIOR() function of the MEDDataManager.
76   SalomeApp_Application* salomeApp = salomeModule->getApp();
77   const char* medEventListenerIOR =
78     salomeApp->orb()->object_to_string(medEventListenerServant);
79   MEDFactoryClient::getDataManager()->setEventListenerIOR(medEventListenerIOR);
80
81   // Connect the signals emitted from the MEDEventListener to slot of
82   // this class.
83   connect(_medEventListener, SIGNAL(medEventSignal(const MEDCALC::MedEvent*)),
84     this, SLOT(processMedEvent(const MEDCALC::MedEvent*)));
85   // >>> WARN:
86   // Note that this class must be mocked (Q_OBJECT + moc file
87   // generated from header file) so that to be able to connect a
88   // signal to a slot of this class.
89
90   // -------------------------------------------------------------
91   // Customize the treeview rendering the datamodel with specific
92   // action for the popup menu
93   this->getDataTreeView()->clearActions();
94   _actionIds.display    = this->getDataTreeView()->addAction(tr("VISUALIZE_SCALAR_MAP"));
95   _actionIds.useInTui   = this->getDataTreeView()->addAction(tr("USE_IN_CONSOLE"));
96   _actionIds.exportToPv = this->getDataTreeView()->addAction(tr("EXPORT_TO_PARAVIS"));
97   _actionIds.save       = this->getDataTreeView()->addAction(tr("SAVE_AS_MED"));
98   _actionIds.remove     = this->getDataTreeView()->addAction(tr("REMOVE_FROM_WORKSPACE"));
99
100   // -------------------------------------------------------------
101   // Initialize the python console. Note that this must be done at
102   // last because the setup will try to initiate a connection to the
103   // event listener.
104   _consoleDriver = new XmedConsoleDriver(salomeModule);
105   _consoleDriver->setup();
106 }
107
108 WorkspaceController::~WorkspaceController() {
109   STDLOG("WorkspaceController::~WorkspaceController()");
110   MEDEventListener_i::release();
111 }
112
113 /**
114  * This creates the GUI actions for driving the Workspace. The
115  * WorkspaceController creates itself this actions and implements the
116  * connected slots.
117  */
118 void WorkspaceController::createActions() {
119   // QWidget* dsk = _salomeModule->getApp()->desktop(); // todo: unused
120   // SUIT_ResourceMgr* resMgr = _salomeModule->getApp()->resourceMgr(); // todo: unused
121   int toolbarId = _salomeModule->createTool("Workspace", "WorkspaceToolbar");
122
123   QString label   = tr("LAB_SAVE_WORKSPACE");
124   QString tooltip = tr("TIP_SAVE_WORKSPACE");
125   QString icon    = tr("ICO_WORKSPACE_SAVE");
126   int actionId = _salomeModule->createStandardAction(label,this,SLOT(OnSaveWorkspace()),icon,tooltip);
127   _salomeModule->createTool(actionId, toolbarId);
128
129   label   = tr("LAB_CLEAN_WORKSPACE");
130   tooltip = tr("TIP_CLEAN_WORKSPACE");
131   icon    = tr("ICO_WORKSPACE_CLEAN");
132   actionId = _salomeModule->createStandardAction(label,this,SLOT(OnCleanWorkspace()),icon,tooltip);
133   _salomeModule->createTool(actionId, toolbarId);
134 }
135
136 /*!
137  * Implementation of the slot processItemList inherited from TreeGuiManager
138  */
139 void WorkspaceController::processItemList(QStringList itemNameIdList, int actionId) {
140   if ( actionId == _actionIds.display ) {
141     STDLOG("WorkspaceController::processItemList: display");
142     this->_viewItemList(itemNameIdList);
143   }
144   else if ( actionId == _actionIds.useInTui ) {
145     STDLOG("WorkspaceController::processItemList: use");
146     this->_importItemList(itemNameIdList);
147   }
148   else if ( actionId == _actionIds.exportToPv ) {
149     STDLOG("WorkspaceController::processItemList: export");
150     this->_exportItemList(itemNameIdList);
151   }
152   else if ( actionId == _actionIds.save ) {
153     STDLOG("WorkspaceController::processItemList: save");
154     this->_saveItemList(itemNameIdList);
155   }
156   else if ( actionId == _actionIds.remove ) {
157     STDLOG("WorkspaceController::processItemList: remove");
158     this->_removeItemList(itemNameIdList);
159   }
160   else {
161     STDLOG("WorkspaceController::processItemList: ERR : action unknown ");
162   }
163 }
164
165 /*!
166  * This function import in the console all the fields associated to
167  * the model items of the specified list. "Import a fields" means
168  * "define a field proxy variable in the python context to manipulate
169  * the real field in the database".
170  */
171 void WorkspaceController::_importItemList(QStringList itemNameIdList) {
172   LOG("WorkspaceController: signal received : display item list "<<itemNameIdList);
173   QStringList::const_iterator it;
174   for (it = itemNameIdList.constBegin(); it != itemNameIdList.constEnd(); ++it) {
175     QString itemNameId = *it;
176     this->_importItem(itemNameId);
177   }
178 }
179
180 /*!
181  * This function is the unit function used to import field in the
182  * console (see _importItemList).
183  */
184 void WorkspaceController::_importItem(QString itemNameId) {
185   XmedDataModel* dataModel = (XmedDataModel*)this->getDataModel();
186   if ( dataModel == NULL ) {
187     LOG("No data model associated to this tree view");
188     return;
189   }
190
191   // We can request the dataModel to obtain the dataObject associated
192   // to this item (iteNameId is a TreeView id, Qt stuff only).
193   XmedDataObject* dataObject =
194     (XmedDataObject*)dataModel->getDataObject(QS2S(itemNameId));
195
196   if ( dataObject == NULL ) {
197     LOG("WorkspaceController: WARN! No data object associated to the item "<<itemNameId);
198     return;
199   }
200
201   // Then, we can request this data object to obtain the associated
202   // FieldHandler.
203   MEDCALC::FieldHandler* fieldHandler = dataObject->getFieldHandler();
204   STDLOG("Field: mesh="<<fieldHandler->meshname<<" name="<<fieldHandler->fieldname);
205
206   // Finally, we can import the field
207   bool askForOptions = true;
208   _importFieldIntoConsole(fieldHandler, askForOptions);
209 }
210
211 /**
212  * This function import the specified field into the tui console. This
213  * means to define a field proxy variable in the python context to
214  * manipulate the field. We can raise a gui to specify some import
215  * options or simply specify the alias (i.e. the name of the python
216  * variable).
217  */
218 void WorkspaceController::_importFieldIntoConsole(MEDCALC::FieldHandler* fieldHandler,
219               bool askForOptions,
220               const char* alias)
221 {
222   STDLOG("alias="<<alias);
223
224   // By default, the alias is the name of the field
225   QString*effectiveAlias;
226   if ( alias == NULL ) {
227     effectiveAlias = new QString(fieldHandler->fieldname);
228   }
229   else {
230     effectiveAlias = new QString(alias);
231   }
232
233   // We can propose to the user to specify some additional
234   // information concerning what must be imported.
235   //
236   // In this version, we just ask the alias the field will be
237   // manipulated with. The default alias is the field name. This alias
238   // should be asked to the user to get a short name to manipulate.
239   if ( askForOptions ) {
240     DlgAlias dialog;
241     dialog.setAlias(*effectiveAlias);
242     int choice = dialog.exec();
243     if ( choice == QDialog::Rejected ) {
244       // The user decides to cancel the operation
245       return;
246     }
247     *effectiveAlias = dialog.getAlias();
248   }
249
250   //
251   // Then, the list of python commands can be written and executed to
252   // define the field in the console
253   //
254   QStringList commands;
255   commands+=QString("%1=medcalc.newFieldProxy(fieldHandlerId=%2)")
256     .arg(*effectiveAlias)
257     .arg(fieldHandler->id);
258
259   _consoleDriver->exec(commands);
260 }
261
262 /*!
263  * This function is a Qt slot connected to the signal medEventSignal
264  * emitted from the MEDEventListener. It processes events coming from
265  * the python console.
266  */
267 void WorkspaceController::processMedEvent(const MEDCALC::MedEvent* event) {
268   STDLOG("WorkspaceController::processMedEvent");
269   STDLOG("dataId  :"<<event->dataId);
270
271   XmedDataModel* dataModel = (XmedDataModel*)this->getDataModel();
272   if ( dataModel == NULL ) {
273     STDLOG("No data model associated to this tree view");
274     return;
275   }
276
277   if ( event->type == MEDCALC::EVENT_UPDATE_FIELD ) {
278     std::cout << "WorkspaceController::processMedEvent[MEDCALC::EVENT_UPDATE_FIELD]: Not implemented yet";
279   }
280   else if ( event->type == MEDCALC::EVENT_PUT_IN_WORKSPACE ) {
281     STDLOG("add new field");
282     MEDCALC::FieldHandler* fieldHandler =
283       MEDFactoryClient::getDataManager()->getFieldHandler(event->dataId);
284
285     XmedDataObject* dataObject = (XmedDataObject*)dataModel->newDataObject();
286     dataObject->setFieldHandler(*fieldHandler);
287     this->getDataTreeModel()->addData(dataObject);
288   }
289   else if ( event->type == MEDCALC::EVENT_REMOVE_FROM_WORKSPACE ) {
290     STDLOG("remove field");
291     std::map<std::string, DataObject*>::iterator itr = dataModel->begin();
292     for ( ; itr != dataModel->end(); ++itr) {
293       XmedDataObject* obj = dynamic_cast<XmedDataObject*>(itr->second);
294       if (obj->getFieldHandler()->id == event->dataId) {
295         std::string itemNameId = obj->getNameId();
296         this->getDataTreeModel()->removeData(obj);
297         dataModel->removeDataObject(itemNameId);
298         return;
299       }
300     }
301   }
302   else if ( event->type == MEDCALC::EVENT_CLEAN_WORKSPACE ) {
303     STDLOG("clean workspace");
304     std::map<std::string, DataObject*>::iterator itr = dataModel->begin();
305     for ( ; itr != dataModel->end(); ++itr) {
306       XmedDataObject* obj = dynamic_cast<XmedDataObject*>(itr->second);
307       std::string itemNameId = obj->getNameId();
308       this->getDataTreeModel()->removeData(obj);
309       dataModel->removeDataObject(itemNameId);
310     }
311   }
312   else if ( event->type == MEDCALC::EVENT_ADD_DATASOURCE ) {
313     emit workspaceSignal(event); // forward to DatasourceController
314   }
315   else if ( event->type == MEDCALC::EVENT_ADD_PRESENTATION ) {
316     emit workspaceSignal(event); // forward to PresentationController
317   }
318   else if ( event->type == MEDCALC::EVENT_REMOVE_PRESENTATION ) {
319     emit workspaceSignal(event); // forward to PresentationController
320   }
321   else if ( event->type == MEDCALC::EVENT_MODIFY_PRESENTATION ) {
322       emit workspaceSignal(event); // forward to PresentationController
323   }
324   else if ( event->type == MEDCALC::EVENT_CHANGE_UNDERLYING_MESH
325             || event->type == MEDCALC::EVENT_INTERPOLATE_FIELD ) {
326     int fieldId = event->dataId;
327     MEDCALC::FieldHandler* fieldHandler = MEDFactoryClient::getDataManager()->getFieldHandler(fieldId);
328     XmedDataObject* dataObject = new XmedDataObject();
329     dataObject->setFieldHandler(*fieldHandler);
330     std::cout << "IMPORT object in workspace: " << dataObject->toString() << std::endl;
331     STDLOG("IMPORT object in workspace:\n"<<dataObject->toString());
332     // _GBO_ QUESTION: tag automatically the object as a peristant object ??
333     // We first add the data object to the internal data model
334     dataModel->addDataObject(dataObject);
335     // Then we request the tree view to consider this new object
336     this->getDataTreeModel()->addData(dataObject);
337
338     // Workaround to visualize the result
339     MEDCouplingFieldDouble* fieldDouble = MEDDataManager_i::getInstance()->getFieldDouble(fieldHandler);
340     std::string filename = std::tmpnam(NULL);
341     WriteField(filename.c_str(), fieldDouble, true);
342
343     QStringList commands;
344     commands += QString("source_id = medcalc.LoadDataSource('%1')").arg(filename.c_str());
345     commands += QString("source_id");
346     commands += QString("mesh_id = medcalc.GetFirstMeshFromDataSource(source_id)");
347     commands += QString("mesh_id");
348     commands += QString("field_id = medcalc.GetFirstFieldFromMesh(mesh_id)");
349     commands += QString("field_id");
350     commands += QString("presentation_id = medcalc.MakeScalarMap(accessField(field_id), viewMode=MEDCALC.VIEW_MODE_REPLACE)");
351     commands += QString("presentation_id");
352     _consoleDriver->exec(commands);
353   }
354   else if ( event->type == MEDCALC::EVENT_PLAY_TEST ) {
355     emit workspaceSignal(event); // forward to TestController
356   }
357   else if ( event->type == MEDCALC::EVENT_QUIT_SALOME ) {
358     emit workspaceSignal(event); // forward to TestController
359   }
360   else if ( event->type == MEDCALC::EVENT_ERROR ) {
361       std::string msg(event->msg);
362       QMessageBox::warning(_salomeModule->getApp()->desktop(), "Error", QString::fromStdString(msg));
363   }
364   else {
365     STDLOG("WorkspaceController::processMedEvent(): Unhandled event!!!");
366   }
367 }
368
369 /*!
370  * This function save a list of fields in a med file. The med file
371  * name is requested to the user using a file chooser dialog box
372  */
373 void WorkspaceController::_saveItemList(QStringList itemNameIdList) {
374   XmedDataProcessor* dataProcessor = new XmedDataProcessor(this->getDataModel());
375   dataProcessor->process(itemNameIdList);
376   MEDCALC::FieldIdList_var fieldIdList = dataProcessor->getResultingFieldIdList();
377   delete dataProcessor;
378
379   QStringList filter;
380   filter.append(tr("FILE_FILTER_MED"));
381   QString filename = SUIT_FileDlg::getFileName(_salomeModule->getApp()->desktop(),
382                                                "",
383                                                filter,
384                                                tr("SAVE_SELECTED_FIELDS"),
385                                                false);
386
387   if ( filename.isEmpty() ) return;
388
389   MEDFactoryClient::getDataManager()->saveFields(QCHARSTAR(filename), fieldIdList);
390 }
391
392 /*!
393  * This function remove the selected item from workspace.
394  */
395 void WorkspaceController::_removeItemList(QStringList itemNameIdList) {
396   XmedDataModel* dataModel = (XmedDataModel*)this->getDataModel();
397   if ( dataModel == NULL ) {
398     LOG("No data model associated to this tree view");
399     return;
400   }
401
402   // __GBO__: In this version, we consider only the first field in the selection
403   QString itemNameId = itemNameIdList[0];
404
405   // We can request the dataModel to obtain the dataObject associated
406   // to this item (iteNameId is a TreeView id, Qt stuff only).
407   XmedDataObject* dataObject =
408     (XmedDataObject*)dataModel->getDataObject(QS2S(itemNameId));
409
410   if ( dataObject == NULL ) {
411     LOG("WorkspaceController: WARN! No data object associated to the item "<<itemNameId);
412     return;
413   }
414
415   // Then, we can request this data object to obtain the associated
416   // FieldHandler.
417   MEDCALC::FieldHandler* fieldHandler = dataObject->getFieldHandler();
418   STDLOG("Field: mesh="<<fieldHandler->meshname<<" name="<<fieldHandler->fieldname);
419
420   // Remove the field variable from console
421   QStringList commands;
422   commands+=QString("removeFromWorkspace(accessField(%1))").arg(fieldHandler->id);
423   _consoleDriver->exec(commands);
424
425   // Finally, we can remove the field from tree data model and tree view
426   this->getDataTreeModel()->removeData(dataObject);
427   dataModel->removeDataObject(QS2S(itemNameId));
428 }
429
430 /**
431  * This function export the list of specified field item to PARAVIS
432  * module. This consists in create a med file gathering the selected
433  * items, then to import this file in PARAVIS, and finally to create a
434  * scalar map of the first item to start the job.
435  */
436 void WorkspaceController::_exportItemList(QStringList itemNameIdList) {
437   XmedDataProcessor* dataProcessor = new XmedDataProcessor(this->getDataModel());
438   dataProcessor->process(itemNameIdList);
439   MEDCALC::FieldIdList_var fieldIdList = dataProcessor->getResultingFieldIdList();
440   delete dataProcessor;
441
442   // _GBO_ We use a temporary file to proceed with this export to
443   // paravis. I'm sure it could be better in a futur version or when I
444   // will get a better understanding of paravis API.
445   const char* tmpfilename = "/tmp/medcalc_export2paravis.med";
446   MEDFactoryClient::getDataManager()->saveFields(tmpfilename, fieldIdList);
447
448   // We import the whole file but create a scalar map for the first
449   // selected field only (it's just an export to continue the job in
450   // paravis)
451   XmedDataModel* dataModel = (XmedDataModel*)this->getDataModel();
452   if ( dataModel == NULL ) {
453     STDLOG("No data model associated to this tree view");
454     return;
455   }
456   QString itemNameId = itemNameIdList[0];
457   XmedDataObject* dataObject = (XmedDataObject*)dataModel->getDataObject(QS2S(itemNameId));
458   if ( dataObject == NULL ) {
459     LOG("WorkspaceController: WARN! No data object associated to the item "<<itemNameId);
460     return;
461   }
462   QStringList commands;
463   /*
464   MEDCALC::FieldHandler* fieldHandler = dataObject->getFieldHandler(); // todo: unused
465   commands+=QString("from xmed.driver_pvis import pvis_scalarmap");
466   commands+=QString("pvis_scalarmap('%1','%2','%3',%4,%5)")
467     .arg(tmpfilename)
468     .arg(QString(fieldHandler->meshname))
469     .arg(QString(fieldHandler->fieldname))
470     .arg(fieldHandler->type)
471     .arg(fieldHandler->iteration);
472   */
473   commands += "print('Not implemented yet')";
474   _consoleDriver->exec(commands);
475
476 }
477
478 /*!
479  * This function sends a request to the SALOME data visualisation
480  * (module VISU or PARAVIS) for displaying a scalar map of the fields
481  * associated to the model items in the specified list.
482  *
483  */
484 void WorkspaceController::_viewItemList(QStringList itemNameIdList) {
485
486   // __GBO__: In this version, we consider only the first field in the selection
487   QString itemNameId = itemNameIdList[0];
488
489   XmedDataModel* dataModel = (XmedDataModel*)this->getDataModel();
490   if ( dataModel == NULL ) {
491     LOG("No data model associated to this tree view");
492     return;
493   }
494
495   // We can request the dataModel to obtain the dataObject associated
496   // to this item (iteNameId is a TreeView id, Qt stuff only).
497   XmedDataObject* dataObject =
498     (XmedDataObject*)dataModel->getDataObject(QS2S(itemNameId));
499   if ( dataObject == NULL ) {
500     LOG("WorkspaceController: WARN! No data object associated to the item "<<itemNameId);
501     return;
502   }
503
504   // Then, we can request this data object to obtain the associated
505   // FieldHandler.
506   //MEDCALC::FieldHandler* fieldHandler = dataObject->getFieldHandler(); // todo: unused
507
508   // And finally, we can create the set of medcalc instructions to
509   // generate the scalar map on this field.
510   QStringList commands;
511   //commands+=QString("view(accessField(%1))").arg(fieldHandler->id);
512   commands += "print('Not implemented yet')";
513   _consoleDriver->exec(commands);
514 }
515
516 /**
517  * This slot can process the event coming from the
518  * DatasourceController. The connection between the datasource signal
519  * and this slot is realized by the main class MEDModule.
520  */
521 void WorkspaceController::processDatasourceEvent(const DatasourceEvent* event) {
522   XmedDataModel* dataModel = (XmedDataModel*)this->getDataModel();
523   if ( dataModel == NULL ) {
524     STDLOG("No data model associated to this tree view");
525     return;
526   }
527
528   // >>>
529   // __GBO__ To know what to do we should test the type, because the
530   // object could be a mesh, a timeseries or a single field. We test
531   // here the case of a single field. Moreover, there could have
532   // options such that "change the underlying mesh".
533   // <<<
534
535   XmedDataObject* dataObject = event->objectdata;
536
537   if ( event->eventtype == DatasourceEvent::EVENT_IMPORT_OBJECT ) {
538     std::cout << "IMPORT object in workspace: " << dataObject->toString() << std::endl;
539     STDLOG("IMPORT object in workspace:\n"<<dataObject->toString());
540     // _GBO_ QUESTION: tag automatically the object as a peristant object ??
541     // We first add the data object to the internal data model
542     dataModel->addDataObject(dataObject);
543     // Then we request the tree view to consider this new object
544     this->getDataTreeModel()->addData(dataObject);
545   }
546   else if ( event->eventtype == DatasourceEvent::EVENT_USE_OBJECT ) {
547     STDLOG("USE object in workspace:\n"<<dataObject->toString());
548     // We first add the data object to the internal data model
549     dataModel->addDataObject(dataObject);
550     // Then we request the tree view to consider this new object
551     this->getDataTreeModel()->addData(dataObject);
552
553     // We define a proxy for this object in the tui console.
554     STDLOG("Define a proxy variable in the console with name : "<<QCHARSTAR(event->objectalias));
555     bool askForOptions = false;
556     _importFieldIntoConsole(dataObject->getFieldHandler(),
557           askForOptions,
558           QCHARSTAR(event->objectalias));
559   }
560   else if ( event->eventtype == DatasourceEvent::EVENT_ADD_DATASOURCE ) {
561     QStringList commands;
562     commands += QString("source_id = medcalc.LoadDataSource('%1')").arg(event->objectalias);
563     commands += QString("source_id");
564     _consoleDriver->exec(commands);
565
566     // Create a default presentation when loading a file
567     MEDCALC::MedEvent* evt = new MEDCALC::MedEvent();
568     evt->type = MEDCALC::EVENT_ADD_PRESENTATION;
569     evt->dataId = -1;
570     emit workspaceSignal(evt); // forward to PresentationController
571   }
572   else if ( event->eventtype == DatasourceEvent::EVENT_ADD_IMAGE_AS_DATASOURCE ) {
573     QStringList commands;
574     commands += QString("source_id = medcalc.LoadImageAsDataSource('%1')").arg(event->objectalias);
575     commands += QString("source_id");
576     _consoleDriver->exec(commands);
577   }
578   else {
579     STDLOG("The event "<<event->eventtype<<" is not implemented yet");
580   }
581 }
582
583 void
584 WorkspaceController::processProcessingEvent(const ProcessingEvent* event)
585 {
586   XmedDataModel* dataModel = (XmedDataModel*)this->getDataModel();
587   if ( dataModel == NULL ) {
588     STDLOG("No data model associated to this tree view");
589     return;
590   }
591
592   int fieldId = event->fieldId;
593   int meshId = event->meshId;
594
595   if ( event->eventtype == ProcessingEvent::EVENT_CHANGE_UNDERLYING_MESH ) {
596     QStringList commands;
597     commands += QString("result_id = medcalc.ChangeUnderlyingMesh(fieldId=%1,meshId=%2)").arg(fieldId).arg(meshId);
598     commands += QString("result_id");
599     _consoleDriver->exec(commands);
600   }
601   else if ( event->eventtype == ProcessingEvent::EVENT_INTERPOLATE_FIELD ) {
602     MEDCALC::InterpolationParameters params = event->interpParams;
603     QString method = QString(params.method);
604     QString nature = QString(params.nature);
605     QString intersectionType = QString(params.intersectionType);
606
607     QStringList commands;
608     commands += QString("result_id = medcalc.InterpolateField(fieldId=%1,meshId=%2,precision=%3,defaultValue=%4,reverse=%5,method='%6',nature='%7',intersectionType='%8')").arg(fieldId).arg(meshId).arg(params.precision).arg(params.defaultValue).arg(params.reverse).arg(method).arg(nature).arg(intersectionType);
609     commands += QString("result_id");
610     _consoleDriver->exec(commands);
611   }
612 }
613
614 void WorkspaceController::OnSaveWorkspace() {
615
616   // Dialog to get the filename where the workspace must be saved into
617   QStringList filter;
618   filter.append(tr("FILE_FILTER_MED"));
619
620   QString filename = SUIT_FileDlg::getFileName(_salomeModule->getApp()->desktop(),
621                                                "",
622                                                filter,
623                                                tr("SAVE_WORKSPACE_DATA"),
624                                                false);
625
626   if ( filename.isEmpty() ) return;
627
628   STDLOG("OnWorkspaceSave: save the workspace in the file " << QCHARSTAR(filename));
629   QStringList commands;
630   commands+=QString("saveWorkspace('%1')").arg(filename);
631   _consoleDriver->exec(commands);
632 }
633
634 #include <QMessageBox>
635 void WorkspaceController::OnCleanWorkspace() {
636   // Remove field from console
637   QStringList commands;
638   commands += QString("cleanWorkspace()");
639   _consoleDriver->exec(commands);
640 }