Salome HOME
updated copyright message
[modules/med.git] / src / MEDCalc / gui / WorkspaceController.cxx
1 // Copyright (C) 2007-2023  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_VISIBILITY_CHANGED ) {
322     emit workspaceSignal(event); // forward to PresentationController
323   }
324   else if ( event->type == MEDCALC::EVENT_MODIFY_PRESENTATION ) {
325       emit workspaceSignal(event); // forward to PresentationController
326   }
327   else if ( event->type == MEDCALC::EVENT_CHANGE_UNDERLYING_MESH
328             || event->type == MEDCALC::EVENT_INTERPOLATE_FIELD ) {
329     int fieldId = event->dataId;
330     MEDCALC::FieldHandler* fieldHandler = MEDFactoryClient::getDataManager()->getFieldHandler(fieldId);
331     XmedDataObject* dataObject = new XmedDataObject();
332     dataObject->setFieldHandler(*fieldHandler);
333     std::cout << "IMPORT object in workspace: " << dataObject->toString() << std::endl;
334     STDLOG("IMPORT object in workspace:\n"<<dataObject->toString());
335     // _GBO_ QUESTION: tag automatically the object as a peristant object ??
336     // We first add the data object to the internal data model
337     dataModel->addDataObject(dataObject);
338     // Then we request the tree view to consider this new object
339     this->getDataTreeModel()->addData(dataObject);
340
341     // Workaround to visualize the result
342     MEDCouplingFieldDouble* fieldDouble = MEDDataManager_i::getInstance()->getFieldDouble(fieldHandler);
343     std::string filename = std::tmpnam(NULL);
344     WriteField(filename.c_str(), fieldDouble, true);
345
346     QStringList commands;
347     commands += QString("source_id = medcalc.LoadDataSource('%1')").arg(filename.c_str());
348     commands += QString("source_id");
349     commands += QString("mesh_id = medcalc.GetFirstMeshFromDataSource(source_id)");
350     commands += QString("mesh_id");
351     commands += QString("field_id = medcalc.GetFirstFieldFromMesh(mesh_id)");
352     commands += QString("field_id");
353     commands += QString("presentation_id = medcalc.MakeScalarMap(accessField(field_id), viewMode=MEDCALC.VIEW_MODE_REPLACE)");
354     commands += QString("presentation_id");
355     _consoleDriver->exec(commands);
356   }
357   else if ( event->type == MEDCALC::EVENT_PLAY_TEST ) {
358     emit workspaceSignal(event); // forward to TestController
359   }
360   else if ( event->type == MEDCALC::EVENT_QUIT_SALOME ) {
361     emit workspaceSignal(event); // forward to TestController
362   }
363   else if ( event->type == MEDCALC::EVENT_ERROR ) {
364       std::string msg(event->msg);
365       QMessageBox::warning(_salomeModule->getApp()->desktop(), "Error", QString::fromStdString(msg));
366   }
367   else {
368     STDLOG("WorkspaceController::processMedEvent(): Unhandled event!!!");
369   }
370 }
371
372 /*!
373  * This function save a list of fields in a med file. The med file
374  * name is requested to the user using a file chooser dialog box
375  */
376 void WorkspaceController::_saveItemList(QStringList itemNameIdList) {
377   XmedDataProcessor* dataProcessor = new XmedDataProcessor(this->getDataModel());
378   dataProcessor->process(itemNameIdList);
379   MEDCALC::FieldIdList_var fieldIdList = dataProcessor->getResultingFieldIdList();
380   delete dataProcessor;
381
382   QStringList filter;
383   filter.append(tr("FILE_FILTER_MED"));
384   QString filename = SUIT_FileDlg::getFileName(_salomeModule->getApp()->desktop(),
385                                                "",
386                                                filter,
387                                                tr("SAVE_SELECTED_FIELDS"),
388                                                false);
389
390   if ( filename.isEmpty() ) return;
391
392   MEDFactoryClient::getDataManager()->saveFields(QCHARSTAR(filename), fieldIdList);
393 }
394
395 /*!
396  * This function remove the selected item from workspace.
397  */
398 void WorkspaceController::_removeItemList(QStringList itemNameIdList) {
399   XmedDataModel* dataModel = (XmedDataModel*)this->getDataModel();
400   if ( dataModel == NULL ) {
401     LOG("No data model associated to this tree view");
402     return;
403   }
404
405   // __GBO__: In this version, we consider only the first field in the selection
406   QString itemNameId = itemNameIdList[0];
407
408   // We can request the dataModel to obtain the dataObject associated
409   // to this item (iteNameId is a TreeView id, Qt stuff only).
410   XmedDataObject* dataObject =
411     (XmedDataObject*)dataModel->getDataObject(QS2S(itemNameId));
412
413   if ( dataObject == NULL ) {
414     LOG("WorkspaceController: WARN! No data object associated to the item "<<itemNameId);
415     return;
416   }
417
418   // Then, we can request this data object to obtain the associated
419   // FieldHandler.
420   MEDCALC::FieldHandler* fieldHandler = dataObject->getFieldHandler();
421   STDLOG("Field: mesh="<<fieldHandler->meshname<<" name="<<fieldHandler->fieldname);
422
423   // Remove the field variable from console
424   QStringList commands;
425   commands+=QString("removeFromWorkspace(accessField(%1))").arg(fieldHandler->id);
426   _consoleDriver->exec(commands);
427
428   // Finally, we can remove the field from tree data model and tree view
429   this->getDataTreeModel()->removeData(dataObject);
430   dataModel->removeDataObject(QS2S(itemNameId));
431 }
432
433 /**
434  * This function export the list of specified field item to PARAVIS
435  * module. This consists in create a med file gathering the selected
436  * items, then to import this file in PARAVIS, and finally to create a
437  * scalar map of the first item to start the job.
438  */
439 void WorkspaceController::_exportItemList(QStringList itemNameIdList) {
440   XmedDataProcessor* dataProcessor = new XmedDataProcessor(this->getDataModel());
441   dataProcessor->process(itemNameIdList);
442   MEDCALC::FieldIdList_var fieldIdList = dataProcessor->getResultingFieldIdList();
443   delete dataProcessor;
444
445   // _GBO_ We use a temporary file to proceed with this export to
446   // paravis. I'm sure it could be better in a futur version or when I
447   // will get a better understanding of paravis API.
448   const char* tmpfilename = "/tmp/medcalc_export2paravis.med";
449   MEDFactoryClient::getDataManager()->saveFields(tmpfilename, fieldIdList);
450
451   // We import the whole file but create a scalar map for the first
452   // selected field only (it's just an export to continue the job in
453   // paravis)
454   XmedDataModel* dataModel = (XmedDataModel*)this->getDataModel();
455   if ( dataModel == NULL ) {
456     STDLOG("No data model associated to this tree view");
457     return;
458   }
459   QString itemNameId = itemNameIdList[0];
460   XmedDataObject* dataObject = (XmedDataObject*)dataModel->getDataObject(QS2S(itemNameId));
461   if ( dataObject == NULL ) {
462     LOG("WorkspaceController: WARN! No data object associated to the item "<<itemNameId);
463     return;
464   }
465   QStringList commands;
466   /*
467   MEDCALC::FieldHandler* fieldHandler = dataObject->getFieldHandler(); // todo: unused
468   commands+=QString("from xmed.driver_pvis import pvis_scalarmap");
469   commands+=QString("pvis_scalarmap('%1','%2','%3',%4,%5)")
470     .arg(tmpfilename)
471     .arg(QString(fieldHandler->meshname))
472     .arg(QString(fieldHandler->fieldname))
473     .arg(fieldHandler->type)
474     .arg(fieldHandler->iteration);
475   */
476   commands += "print('Not implemented yet')";
477   _consoleDriver->exec(commands);
478
479 }
480
481 /*!
482  * This function sends a request to the SALOME data visualisation
483  * (module VISU or PARAVIS) for displaying a scalar map of the fields
484  * associated to the model items in the specified list.
485  *
486  */
487 void WorkspaceController::_viewItemList(QStringList itemNameIdList) {
488
489   // __GBO__: In this version, we consider only the first field in the selection
490   QString itemNameId = itemNameIdList[0];
491
492   XmedDataModel* dataModel = (XmedDataModel*)this->getDataModel();
493   if ( dataModel == NULL ) {
494     LOG("No data model associated to this tree view");
495     return;
496   }
497
498   // We can request the dataModel to obtain the dataObject associated
499   // to this item (iteNameId is a TreeView id, Qt stuff only).
500   XmedDataObject* dataObject =
501     (XmedDataObject*)dataModel->getDataObject(QS2S(itemNameId));
502   if ( dataObject == NULL ) {
503     LOG("WorkspaceController: WARN! No data object associated to the item "<<itemNameId);
504     return;
505   }
506
507   // Then, we can request this data object to obtain the associated
508   // FieldHandler.
509   //MEDCALC::FieldHandler* fieldHandler = dataObject->getFieldHandler(); // todo: unused
510
511   // And finally, we can create the set of medcalc instructions to
512   // generate the scalar map on this field.
513   QStringList commands;
514   //commands+=QString("view(accessField(%1))").arg(fieldHandler->id);
515   commands += "print('Not implemented yet')";
516   _consoleDriver->exec(commands);
517 }
518
519 /**
520  * This slot can process the event coming from the
521  * DatasourceController. The connection between the datasource signal
522  * and this slot is realized by the main class MEDModule.
523  */
524 void WorkspaceController::processDatasourceEvent(const DatasourceEvent* event) {
525   XmedDataModel* dataModel = (XmedDataModel*)this->getDataModel();
526   if ( dataModel == NULL ) {
527     STDLOG("No data model associated to this tree view");
528     return;
529   }
530
531   // >>>
532   // __GBO__ To know what to do we should test the type, because the
533   // object could be a mesh, a timeseries or a single field. We test
534   // here the case of a single field. Moreover, there could have
535   // options such that "change the underlying mesh".
536   // <<<
537
538   XmedDataObject* dataObject = event->objectdata;
539
540   if ( event->eventtype == DatasourceEvent::EVENT_IMPORT_OBJECT ) {
541     std::cout << "IMPORT object in workspace: " << dataObject->toString() << std::endl;
542     STDLOG("IMPORT object in workspace:\n"<<dataObject->toString());
543     // _GBO_ QUESTION: tag automatically the object as a peristant object ??
544     // We first add the data object to the internal data model
545     dataModel->addDataObject(dataObject);
546     // Then we request the tree view to consider this new object
547     this->getDataTreeModel()->addData(dataObject);
548   }
549   else if ( event->eventtype == DatasourceEvent::EVENT_USE_OBJECT ) {
550     STDLOG("USE object in workspace:\n"<<dataObject->toString());
551     // We first add the data object to the internal data model
552     dataModel->addDataObject(dataObject);
553     // Then we request the tree view to consider this new object
554     this->getDataTreeModel()->addData(dataObject);
555
556     // We define a proxy for this object in the tui console.
557     STDLOG("Define a proxy variable in the console with name : "<<QCHARSTAR(event->objectalias));
558     bool askForOptions = false;
559     _importFieldIntoConsole(dataObject->getFieldHandler(),
560           askForOptions,
561           QCHARSTAR(event->objectalias));
562   }
563   else if ( event->eventtype == DatasourceEvent::EVENT_ADD_DATASOURCE ) {
564     QStringList commands;
565     commands += QString("source_id = medcalc.LoadDataSource('%1')").arg(event->objectalias);
566     commands += QString("source_id");
567     _consoleDriver->exec(commands);
568
569     // Create a default presentation when loading a file
570     MEDCALC::MedEvent* evt = new MEDCALC::MedEvent();
571     evt->type = MEDCALC::EVENT_ADD_PRESENTATION;
572     evt->dataId = -1;
573     emit workspaceSignal(evt); // forward to PresentationController
574   }
575   else if ( event->eventtype == DatasourceEvent::EVENT_ADD_IMAGE_AS_DATASOURCE ) {
576     QStringList commands;
577     commands += QString("source_id = medcalc.LoadImageAsDataSource('%1')").arg(event->objectalias);
578     commands += QString("source_id");
579     _consoleDriver->exec(commands);
580   }
581   else {
582     STDLOG("The event "<<event->eventtype<<" is not implemented yet");
583   }
584 }
585
586 void
587 WorkspaceController::processProcessingEvent(const ProcessingEvent* event)
588 {
589   XmedDataModel* dataModel = (XmedDataModel*)this->getDataModel();
590   if ( dataModel == NULL ) {
591     STDLOG("No data model associated to this tree view");
592     return;
593   }
594
595   int fieldId = event->fieldId;
596   int meshId = event->meshId;
597
598   if ( event->eventtype == ProcessingEvent::EVENT_CHANGE_UNDERLYING_MESH ) {
599     QStringList commands;
600     commands += QString("result_id = medcalc.ChangeUnderlyingMesh(fieldId=%1,meshId=%2)").arg(fieldId).arg(meshId);
601     commands += QString("result_id");
602     _consoleDriver->exec(commands);
603   }
604   else if ( event->eventtype == ProcessingEvent::EVENT_INTERPOLATE_FIELD ) {
605     MEDCALC::InterpolationParameters params = event->interpParams;
606     QString method = QString(params.method);
607     QString nature = QString(params.nature);
608     QString intersectionType = QString(params.intersectionType);
609
610     QStringList commands;
611     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);
612     commands += QString("result_id");
613     _consoleDriver->exec(commands);
614   }
615 }
616
617 void WorkspaceController::OnSaveWorkspace() {
618
619   // Dialog to get the filename where the workspace must be saved into
620   QStringList filter;
621   filter.append(tr("FILE_FILTER_MED"));
622
623   QString filename = SUIT_FileDlg::getFileName(_salomeModule->getApp()->desktop(),
624                                                "",
625                                                filter,
626                                                tr("SAVE_WORKSPACE_DATA"),
627                                                false);
628
629   if ( filename.isEmpty() ) return;
630
631   STDLOG("OnWorkspaceSave: save the workspace in the file " << QCHARSTAR(filename));
632   QStringList commands;
633   commands+=QString("saveWorkspace('%1')").arg(filename);
634   _consoleDriver->exec(commands);
635 }
636
637 #include <QMessageBox>
638 void WorkspaceController::OnCleanWorkspace() {
639   // Remove field from console
640   QStringList commands;
641   commands += QString("cleanWorkspace()");
642   _consoleDriver->exec(commands);
643 }