Salome HOME
Add field interpolation to GUI
[modules/med.git] / src / MEDOP / gui / DatasourceController.cxx
1 // Copyright (C) 2007-2014  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 "DatasourceController.hxx"
23 #include "DatasourceConstants.hxx"
24
25 #include "MEDOPFactoryClient.hxx"
26 #include "QtHelper.hxx"
27
28 #include CORBA_CLIENT_HEADER(SALOMEDS)
29 #include <SUIT_FileDlg.h>
30 #include <SUIT_Desktop.h>
31
32 #include <QStringList>
33 #include <QString>
34 #include <QMessageBox>
35
36 #include "DlgAlias.hxx"
37
38 //
39 // ==============================================================
40 // Datasource controller
41 // ==============================================================
42 //
43 DatasourceController::DatasourceController(StandardApp_Module * salomeModule) {
44   STDLOG("Creating a DatasourceController");
45   _salomeModule = salomeModule;
46   _studyEditor = new SALOME_AppStudyEditor(_salomeModule->getApp());
47
48   _dlgChangeUnderlyingMesh = new DlgChangeUnderlyingMesh(_studyEditor);
49   connect(_dlgChangeUnderlyingMesh,SIGNAL(inputValidated()),
50           this, SLOT(OnChangeUnderlyingMeshInputValidated()));
51
52   _dlgInterpolateField = new DlgInterpolateField(_studyEditor);
53   connect(_dlgInterpolateField,SIGNAL(inputValidated()),
54           this, SLOT(OnInterpolateFieldInputValidated()));
55
56 }
57
58 DatasourceController::~DatasourceController() {
59   STDLOG("Deleting the DatasourceController");
60   delete _studyEditor;
61 }
62
63 void DatasourceController::createActions() {
64   //
65   // Main actions (toolbar and menubar)
66   //
67   QString label   = tr("LAB_ADD_DATA_SOURCE");
68   QString tooltip = tr("TIP_ADD_DATA_SOURCE");
69   QString icon    = tr("ICO_DATASOURCE_ADD");
70   int actionId;
71   actionId = _salomeModule->createStandardAction(label,this, SLOT(OnAddDatasource()),icon,tooltip);
72   _salomeModule->addActionInToolbar(actionId);
73
74   // This action has to be placed in the general file menu with the label "Import MED file"
75   int menuId = _salomeModule->createMenu( tr( "MEN_FILE" ), -1,  1 );
76   _salomeModule->addActionInMenubar(actionId, menuId);
77
78   label   = tr("LAB_ADD_IMAGE_SOURCE");
79   tooltip = tr("TIP_ADD_IMAGE_SOURCE");
80   icon    = tr("ICO_IMAGE_ADD");
81   actionId = _salomeModule->createStandardAction(label,this, SLOT(OnAddImagesource()),icon,tooltip);
82   _salomeModule->addActionInToolbar(actionId);
83
84   //
85   // Actions for popup menu only
86   //
87   // Expand field timeseries
88   label = tr("LAB_EXPAND_FIELD");
89   icon  = tr("ICO_DATASOURCE_EXPAND_FIELD");
90   actionId = _salomeModule->createStandardAction(label,this,SLOT(OnExpandField()),icon);
91   _salomeModule->addActionInPopupMenu(actionId);
92
93   // Create a control view
94   label = tr("LAB_VISUALIZE");
95   icon  = tr("ICO_DATASOURCE_VIEW");
96   actionId = _salomeModule->createStandardAction(label,this,SLOT(OnVisualize()),icon);
97   _salomeModule->addActionInPopupMenu(actionId);
98
99   // Use in workspace
100   label = tr("LAB_USE_IN_WORKSPACE");
101   icon  = tr("ICO_DATASOURCE_USE");
102   actionId = _salomeModule->createStandardAction(label,this,SLOT(OnUseInWorkspace()),icon);
103   _salomeModule->addActionInPopupMenu(actionId);
104
105   // Change underlying mesh (note that this action creates a new field in
106   // the workspace that corresponds to a copy of the selected field
107   // modified by the change of the underlying mesh.
108   label = tr("LAB_CHANGE_MESH");
109   icon  = tr("ICO_DATASOURCE_CHANGE_MESH");
110   actionId = _salomeModule->createStandardAction(label,this,SLOT(OnChangeUnderlyingMesh()),icon);
111   _salomeModule->addActionInPopupMenu(actionId);
112
113   label = tr("LAB_INTERPOLATE_FIELD");
114   icon  = tr("ICO_DATASOURCE_INTERPOLATE_FIELD");
115   actionId = _salomeModule->createStandardAction(label,this,SLOT(OnInterpolateField()),icon);
116   _salomeModule->addActionInPopupMenu(actionId);
117
118 }
119
120 /**
121  * This function adds the specified MED file as a datasource in the
122  * dataspace. Technically speaking, the engine loads the
123  * meta-information concerning med data from the file, gives this
124  * informations to the GUI, and the GUI creates a tree view of these
125  * data in the study object browser.
126  */
127 MEDOP::DatasourceHandler * DatasourceController::addDatasource(const char * filename) {
128
129   MEDOP::DatasourceHandler * datasourceHandler =
130     MEDOPFactoryClient::getDataManager()->addDatasource(filename);
131
132   // We need a studyEditor updated on the active study
133   _studyEditor->updateActiveStudy();
134
135   // Create a datasource SObject as a father of the module root
136   SALOMEDS::SComponent_var root = _studyEditor->findRoot(QCHARSTAR(_salomeModule->moduleName()));
137   SALOMEDS::SObject_var soDatasource = _studyEditor->newObject(root);
138   _studyEditor->setName(soDatasource,datasourceHandler->name);
139   _studyEditor->setIcon(soDatasource,tr("ICO_DATASOURCE").toStdString().c_str());
140   _studyEditor->setParameterInt(soDatasource,OBJECT_ID,datasourceHandler->id);
141
142
143   // We can add the meshes as children of the datasource
144   MEDOP::MeshHandlerList * meshHandlerList =
145     MEDOPFactoryClient::getDataManager()->getMeshList(datasourceHandler->id);
146
147   for(CORBA::ULong iMesh=0; iMesh<meshHandlerList->length(); iMesh++) {
148     MEDOP::MeshHandler meshHandler = (*meshHandlerList)[iMesh];
149     SALOMEDS::SObject_var soMesh = _studyEditor->newObject(soDatasource);
150     _studyEditor->setName(soMesh,meshHandler.name);
151     _studyEditor->setIcon(soMesh,tr("ICO_DATASOURCE_MESH").toStdString().c_str());
152     _studyEditor->setParameterInt(soMesh,OBJECT_ID,meshHandler.id);
153     _studyEditor->setParameterBool(soMesh,OBJECT_IS_IN_WORKSPACE,false);
154
155
156     // We add the field timeseries defined on this mesh, as children
157     // of the mesh SObject
158     MEDOP::FieldseriesHandlerList * fieldseriesHandlerList =
159       MEDOPFactoryClient::getDataManager()->getFieldseriesListOnMesh(meshHandler.id);
160
161     for(CORBA::ULong iFieldseries=0; iFieldseries<fieldseriesHandlerList->length(); iFieldseries++) {
162       MEDOP::FieldseriesHandler fieldseriesHandler = (*fieldseriesHandlerList)[iFieldseries];
163       SALOMEDS::SObject_var soFieldseries = _studyEditor->newObject(soMesh);
164
165       std::string label(fieldseriesHandler.name);
166       label +=" ("+std::string(XmedDataObject::mapTypeOfFieldLabel[fieldseriesHandler.type])+")";
167       _studyEditor->setName(soFieldseries,label.c_str());
168
169       _studyEditor->setIcon(soFieldseries,tr("ICO_DATASOURCE_FIELD").toStdString().c_str());
170       _studyEditor->setParameterInt(soFieldseries,OBJECT_ID,fieldseriesHandler.id);
171       _studyEditor->setParameterBool(soFieldseries,OBJECT_IS_IN_WORKSPACE,false);
172     }
173   }
174
175   return datasourceHandler;
176 }
177
178
179 void DatasourceController::OnAddDatasource()
180 {
181   // Dialog to get the filename where the input data are read from
182   QStringList filter;
183   filter.append(tr("FILE_FILTER_MED"));
184
185   QString anInitialPath = "";
186   if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
187     anInitialPath = QDir::currentPath();
188
189   /*
190   QString filename = SUIT_FileDlg::getFileName(_salomeModule->getApp()->desktop(),
191                                                "",
192                                                filter,
193                                                tr("IMPORT_MED_FIELDS"),
194                                                true);
195   */
196
197   QStringList filenames = SUIT_FileDlg::getOpenFileNames( _salomeModule->getApp()->desktop(),
198                                                           anInitialPath,
199                                                           filter,
200                                                           tr("IMPORT_MED_FIELDS") );
201
202   if ( filenames.count() <= 0 ) return;
203   for ( QStringList::ConstIterator itFile = filenames.begin();
204         itFile != filenames.end(); ++itFile ) {
205     QString filename = *itFile;
206     this->addDatasource(QCHARSTAR(filename));
207     _salomeModule->updateObjBrowser(true);
208   }
209 }
210
211 #include "DlgImageToMed.hxx"
212 #include <stdio.h>
213 #include <stdlib.h>
214 void DatasourceController::OnAddImagesource()
215 {
216
217   DlgImageToMed dialog;
218   dialog.setAutoLoaded(true);
219   int choice = dialog.exec();
220   if ( choice == QDialog::Rejected ) {
221     // The user decides to cancel the operation
222     return;
223   }
224
225   QString imageFilename = dialog.getImageFilepath();
226   QString medFilename   = dialog.getMedFilepath();
227   bool autoLoad         = dialog.isAutoLoaded();
228
229   std::string ROOT_DIR(getenv("MED_ROOT_DIR"));
230   std::string command(ROOT_DIR+"/bin/salome/med/image2med.py");
231   command += " -i "+QS2S(imageFilename);
232   command += " -m "+QS2S(medFilename);
233   int error = system(command.c_str());
234   if ( error != 0 ) {
235     QMessageBox::critical(_salomeModule->getApp()->desktop(),
236            tr("Operation failed"),
237            tr("The creation of med data from the image file failed"));
238     return;
239   }
240
241   if ( autoLoad ) {
242     this->addDatasource(QCHARSTAR(medFilename));
243     _salomeModule->updateObjBrowser(true);
244   }
245
246 }
247
248 void DatasourceController::OnExpandField()
249 {
250   // We need a studyEditor updated on the active study
251   _studyEditor->updateActiveStudy();
252
253   // Get the selected objects in the study (SObject)
254   SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects();
255   for (int i=0; i<listOfSObject->size(); i++) {
256     SALOMEDS::SObject_var soFieldseries = listOfSObject->at(i);
257
258     // First retrieve the fieldseries id associated to this study object
259     long fieldseriesId = _studyEditor->getParameterInt(soFieldseries,OBJECT_ID);
260     STDLOG("Expand the field timeseries "<<fieldseriesId);
261
262     // If fieldseriesId equals -1, then it means that it is not a
263     // fieldseries managed by the MED module, and we stop this
264     // function process.
265     if ( fieldseriesId < 0 )
266       continue;
267     // _GBO_ A better correction should be to no display the
268     // contextual menu if the selected object is not conform
269
270     // Then retrieve the list of fields in this timeseries
271     MEDOP::FieldHandlerList * fieldHandlerList =
272       MEDOPFactoryClient::getDataManager()->getFieldListInFieldseries(fieldseriesId);
273
274     // Finally, create an entry for each of the field
275     for(CORBA::ULong iField=0; iField<fieldHandlerList->length(); iField++) {
276       MEDOP::FieldHandler fieldHandler = (*fieldHandlerList)[iField];
277       SALOMEDS::SObject_var soField = _studyEditor->newObject(soFieldseries);
278       std::string label("it="); label += ToString(fieldHandler.iteration);
279       _studyEditor->setName(soField,label.c_str());
280       _studyEditor->setParameterInt(soField, OBJECT_ID, fieldHandler.id);
281       _studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,false);
282     }
283   }
284   _salomeModule->updateObjBrowser(true);
285 }
286
287 void DatasourceController::OnVisualize() {
288   STDLOG("OnVisualize: To Be Implemented");
289
290   // We need a _studyEditor updated on the active study
291   _studyEditor->updateActiveStudy();
292
293   // Get the selected objects in the study (SObject)
294   SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects();
295
296   // For each object, emit a signal to the workspace to request a
297   // visualisation using the tui command (so that the user can see how
298   // to make a view of an object from the tui console).
299   for (int i=0; i<listOfSObject->size(); i++) {
300     SALOMEDS::SObject_var soField = listOfSObject->at(i);
301     int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID);
302     // If fieldId equals -1, then it means that it is not a field
303     // managed by the MED module, and we stop this function process.
304     if ( fieldId < 0 )
305       continue;
306
307     MEDOP::FieldHandler * fieldHandler = MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
308
309     DatasourceEvent * event = new DatasourceEvent();
310     event->eventtype = DatasourceEvent::EVENT_VIEW_OBJECT;
311     XmedDataObject * dataObject = new XmedDataObject();
312     dataObject->setFieldHandler(*fieldHandler);
313     event->objectdata  = dataObject;
314     emit datasourceSignal(event);
315   }
316
317 }
318
319 void DatasourceController::OnUseInWorkspace() {
320   // We need a studyEditor updated on the active study
321   _studyEditor->updateActiveStudy();
322
323   // Get the selected objects in the study (SObject)
324   SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects();
325   if ( listOfSObject->size() == 1 ) {
326     // In this case we ask the name of the variable for the python
327     // console
328
329     // >>>
330     // _GBO_ Note that it works only for a single field but the
331     // XmedDataObject will be improved to deal with mesh, timeseries
332     // and single field in a futur version. We suppose here that a
333     // single field has been selected.
334     // <<<
335
336     SALOMEDS::SObject_var soField = listOfSObject->at(0);
337
338     bool isInWorkspace = _studyEditor->getParameterBool(soField,OBJECT_IS_IN_WORKSPACE);
339     if ( isInWorkspace ) {
340       QMessageBox::warning(_salomeModule->getApp()->desktop(),
341          tr("Operation not allowed"),
342          tr("This field is already defined in the workspace"));
343       return;
344     }
345
346     int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID);
347
348     // If fieldId equals -1, then it means that it is not a field
349     // managed by the MED module, and we stop this function process.
350     if ( fieldId < 0 ) {
351       QMessageBox::warning(_salomeModule->getApp()->desktop(),
352          tr("Operation not allowed"),
353          tr("This element is not a field object"));
354       return;
355     }
356
357     MEDOP::FieldHandler * fieldHandler =
358       MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
359
360     if (! fieldHandler) {
361       QMessageBox::warning(_salomeModule->getApp()->desktop(),
362          tr("Operation not allowed"),
363          tr("No field is defined"));
364       return;
365     }
366
367     QString alias(fieldHandler->fieldname);
368     DlgAlias dialog;
369     dialog.setAlias(alias);
370     int choice = dialog.exec();
371     if ( choice == QDialog::Rejected ) {
372       // The user decides to cancel the operation
373       return;
374     }
375     alias = dialog.getAlias();
376
377     DatasourceEvent * event = new DatasourceEvent();
378     event->eventtype = DatasourceEvent::EVENT_USE_OBJECT;
379     XmedDataObject * dataObject = new XmedDataObject();
380     dataObject->setFieldHandler(*fieldHandler);
381     event->objectdata  = dataObject;
382     event->objectalias = alias;
383     emit datasourceSignal(event);
384     // Tag the item to prevent double import
385     _studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,true);
386     // Tag the field as persistent on the server. It means that a
387     // saving of the workspace will save at least this field (maybe it
388     // should be an option?)
389     MEDOPFactoryClient::getDataManager()->markAsPersistent(fieldId, true);
390   }
391   else {
392     // In this case, we don't ask the user to specify an alias for
393     // each item, we just import the whole set of items.
394     for (int i=0; i<listOfSObject->size(); i++) {
395       SALOMEDS::SObject_var soField = listOfSObject->at(i);
396
397       bool isInWorkspace = _studyEditor->getParameterBool(soField,OBJECT_IS_IN_WORKSPACE);
398       if ( !isInWorkspace ) {
399   int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID);
400   MEDOP::FieldHandler * fieldHandler =
401     MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
402   DatasourceEvent * event = new DatasourceEvent();
403   event->eventtype = DatasourceEvent::EVENT_IMPORT_OBJECT;
404   XmedDataObject * dataObject = new XmedDataObject();
405   dataObject->setFieldHandler(*fieldHandler);
406   event->objectdata  = dataObject;
407   emit datasourceSignal(event);
408   // Note that this signal is processed by the WorkspaceController
409
410   // Tag the item to prevent double import
411   _studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,true);
412   // Tag the field as persistent on the server. It means that a
413   // saving of the workspace will save at least this field (maybe it
414   // should be an option?)
415   MEDOPFactoryClient::getDataManager()->markAsPersistent(fieldId, true);
416       }
417       else {
418   STDLOG("The field "<<_studyEditor->getName(soField)<<
419          " is already defined in the workspace");
420       }
421     }
422   }
423 }
424
425 void DatasourceController::OnChangeUnderlyingMesh() {
426   // We need a studyEditor updated on the active study
427   _studyEditor->updateActiveStudy();
428
429   // Get the selected objects in the study (SObject). In cas of a
430   // multiple selection, we consider only the first item. At least one
431   // item must be selected.
432   SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects();
433   if ( listOfSObject->size() > 0 ) {
434     SALOMEDS::SObject_var soField = listOfSObject->at(0);
435     int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID);
436     // _GBO_ : the dialog should not be modal, so that we can choose a
437     // mesh in the browser. Then we have to emit a signal from the
438     // dialog.accept, connected to a slot of the DatasourceControler
439     _dlgChangeUnderlyingMesh->setFieldId(fieldId);
440     Qt::WindowFlags flags = _dlgChangeUnderlyingMesh->windowFlags();
441     _dlgChangeUnderlyingMesh->setWindowFlags(flags | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint);
442     _dlgChangeUnderlyingMesh->open();
443   }
444 }
445
446 void DatasourceController::OnChangeUnderlyingMeshInputValidated() {
447   int meshId = _dlgChangeUnderlyingMesh->getMeshId();
448   STDLOG("meshId = " << ToString(meshId));
449   int fieldId = _dlgChangeUnderlyingMesh->getFieldId();
450   MEDOP::FieldHandler * fieldHandler =
451     MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
452
453   // We don't modify the original field but create first a duplicate
454   MEDOP::FieldHandler * duplicate = MEDOPFactoryClient::getCalculator()->dup(*fieldHandler);
455   MEDOPFactoryClient::getDataManager()->changeUnderlyingMesh(duplicate->id, meshId);
456
457   // Request once more the duplicate to update the meta-data on this
458   // client side
459   duplicate = MEDOPFactoryClient::getDataManager()->getFieldHandler(duplicate->id);
460
461   // >>>
462   // WARN: the following is a temporary code for test purpose
463   // Automatically add in ws
464   DatasourceEvent * event = new DatasourceEvent();
465   event->eventtype = DatasourceEvent::EVENT_IMPORT_OBJECT;
466   XmedDataObject * dataObject = new XmedDataObject();
467   dataObject->setFieldHandler(*duplicate);
468   event->objectdata  = dataObject;
469   emit datasourceSignal(event);
470   // Note that this signal is processed by the WorkspaceController
471
472   // Tag the item to prevent double import
473   //_studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,true);
474 }
475
476 void DatasourceController::OnInterpolateField() {
477   // We need a studyEditor updated on the active study
478   _studyEditor->updateActiveStudy();
479
480   // Get the selected objects in the study (SObject). In case of a
481   // multiple selection, we consider only the first item. At least one
482   // item must be selected.
483   SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects();
484   if ( listOfSObject->size() > 0 ) {
485     SALOMEDS::SObject_var soField = listOfSObject->at(0);
486     int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID);
487     // _GBO_ : the dialog should not be modal, so that we can choose a
488     // mesh in the browser. Then we have to emit a signal from the
489     // dialog.accept, connected to a slot of the DatasourceControler
490     _dlgInterpolateField->setFieldId(fieldId);
491     Qt::WindowFlags flags = _dlgInterpolateField->windowFlags();
492     _dlgInterpolateField->setWindowFlags(flags | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint);
493     _dlgInterpolateField->open();
494   }
495 }
496
497 void DatasourceController::OnInterpolateFieldInputValidated() {
498   MEDOP::InterpolationParameters params;
499   params.precision = _dlgInterpolateField->getPrecision();
500   STDLOG("precision = " << params.precision);
501   params.defaultValue = _dlgInterpolateField->getDefaultValue();
502   STDLOG("defaultValue = " << params.defaultValue);
503   params.reverse = _dlgInterpolateField->getReverse();
504   STDLOG("reverse = " << params.reverse);
505   params.intersectionType = _dlgInterpolateField->getIntersectionType().c_str();
506   STDLOG("intersectionType = " << params.intersectionType);
507   params.method = _dlgInterpolateField->getMethod().c_str();
508   STDLOG("method = " << params.method);
509   params.nature = _dlgInterpolateField->getFieldNature().c_str();
510   STDLOG("nature = " << params.nature);
511
512   int meshId = _dlgInterpolateField->getMeshId();
513   STDLOG("meshId = " << ToString(meshId));
514   int fieldId = _dlgInterpolateField->getFieldId();
515   MEDOP::FieldHandler* fieldHandler = MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
516
517   // We don't modify the original field but create first a duplicate
518   // MEDOP::FieldHandler* duplicate = MEDOPFactoryClient::getCalculator()->dup(*fieldHandler);
519   //MEDOPFactoryClient::getDataManager()->changeUnderlyingMesh(duplicate->id, meshId);
520   MEDOP::FieldHandler* result = NULL;
521   try {
522     result = MEDOPFactoryClient::getDataManager()->interpolateField(fieldId, meshId, params);
523   }
524   catch(...) {
525     STDLOG("Unable to process field interpolation; please check interpolation parameters");
526     QMessageBox::critical(_salomeModule->getApp()->desktop(),
527                           tr("Operation failed"),
528                           tr("Unable to process field interpolation; please check interpolation parameters"));
529     return;
530   }
531
532   // Request once more the duplicate to update the meta-data on this
533   // client side
534   // duplicate = MEDOPFactoryClient::getDataManager()->getFieldHandler(duplicate->id);
535
536   // >>>
537   // WARN: the following is a temporary code for test purpose
538   // Automatically add in ws
539   DatasourceEvent * event = new DatasourceEvent();
540   event->eventtype = DatasourceEvent::EVENT_IMPORT_OBJECT;
541   XmedDataObject * dataObject = new XmedDataObject();
542   dataObject->setFieldHandler(*result);
543   event->objectdata = dataObject;
544   emit datasourceSignal(event);
545   // Note that this signal is processed by the WorkspaceController
546
547   // // Tag the item to prevent double import
548   // //_studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,true);
549 }