]> SALOME platform Git repositories - modules/med.git/blob - src/MEDOP/gui/DatasourceController.cxx
Salome HOME
Fix bug mantis 22193
[modules/med.git] / src / MEDOP / gui / DatasourceController.cxx
1 // Copyright (C) 2007-2013  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.
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   _dlgChangeUnderlyingMesh = new DlgChangeUnderlyingMesh(_studyEditor);
48
49   connect(_dlgChangeUnderlyingMesh,SIGNAL(inputValidated()),
50           this, SLOT(OnChangeUnderlyingMeshInputValidated()));
51
52 }
53
54 DatasourceController::~DatasourceController() {
55   STDLOG("Deleting the DatasourceController");
56   delete _studyEditor;
57 }
58
59 void DatasourceController::createActions() {
60   // 
61   // Main actions (toolbar and menubar)
62   //
63   QString label   = QString("Add Data Source");
64   QString tooltip = QString("Add a file data source (file providing med data)");
65   QString icon    = QString("datasource_add.png");
66   int actionId;
67   actionId = _salomeModule->createStandardAction(label,this, SLOT(OnAddDatasource()),icon,tooltip);
68   _salomeModule->addActionInToolbar(actionId);
69
70   label   = QString("Add Image Source");
71   tooltip = QString("Create a Data Source from an image file");
72   icon    = QString("image_add.png");
73   actionId = _salomeModule->createStandardAction(label,this, SLOT(OnAddImagesource()),icon,tooltip);
74   _salomeModule->addActionInToolbar(actionId);
75     
76   //
77   // Actions for popup menu only
78   //
79   // Expand field timeseries
80   label = QString("Expand field timeseries");
81   icon  = QString("datasource_expandfield.png");
82   actionId = _salomeModule->createStandardAction(label,this,SLOT(OnExpandField()),icon);
83   _salomeModule->addActionInPopupMenu(actionId);
84   
85   // Create a control view
86   label = QString("Visualize");
87   icon  = QString("datasource_view.png");
88   actionId = _salomeModule->createStandardAction(label,this,SLOT(OnVisualize()),icon);
89   _salomeModule->addActionInPopupMenu(actionId);
90
91   // Use in workspace
92   label = QString("Use in workspace");
93   icon  = QString("datasource_use.png");
94   actionId = _salomeModule->createStandardAction(label,this,SLOT(OnUseInWorkspace()),icon);
95   _salomeModule->addActionInPopupMenu(actionId);
96
97   // Change underlying mesh (note that this action creates a new field in
98   // the workspace that corresponds to a copy of the selected field
99   // modified by the change of the underlying mesh.
100   label = QString("Change underlying mesh");
101   icon  = QString("datasource_changeUnderlyingMesh.png");
102   actionId = _salomeModule->createStandardAction(label,this,SLOT(OnChangeUnderlyingMesh()),icon);
103   _salomeModule->addActionInPopupMenu(actionId);
104 }
105
106 /**
107  * This function adds the specified MED file as a datasource in the
108  * dataspace. Technically speaking, the engine loads the
109  * meta-information concerning med data from the file, gives this
110  * informations to the GUI, and the GUI creates a tree view of these
111  * data in the study object browser.
112  */
113 MEDOP::DatasourceHandler * DatasourceController::addDatasource(const char * filename) {
114
115   MEDOP::DatasourceHandler * datasourceHandler =
116     MEDOPFactoryClient::getDataManager()->addDatasource(filename);
117
118   // We need a studyEditor updated on the active study
119   _studyEditor->updateActiveStudy();
120
121   // Create a datasource SObject as a father of the module root
122   SALOMEDS::SComponent_var root = _studyEditor->findRoot(QCHARSTAR(_salomeModule->moduleName()));
123   SALOMEDS::SObject_var soDatasource = _studyEditor->newObject(root);
124   _studyEditor->setName(soDatasource,datasourceHandler->name);
125   _studyEditor->setIcon(soDatasource,"datasource.png");
126   _studyEditor->setParameterInt(soDatasource,OBJECT_ID,datasourceHandler->id);
127   
128
129   // We can add the meshes as children of the datasource
130   MEDOP::MeshHandlerList * meshHandlerList = 
131     MEDOPFactoryClient::getDataManager()->getMeshList(datasourceHandler->id);
132   
133   for(CORBA::ULong iMesh=0; iMesh<meshHandlerList->length(); iMesh++) {
134     MEDOP::MeshHandler meshHandler = (*meshHandlerList)[iMesh];
135     SALOMEDS::SObject_var soMesh = _studyEditor->newObject(soDatasource);
136     _studyEditor->setName(soMesh,meshHandler.name);
137     _studyEditor->setIcon(soMesh,"datasource_mesh.png");
138     _studyEditor->setParameterInt(soMesh,OBJECT_ID,meshHandler.id);
139     _studyEditor->setParameterBool(soMesh,OBJECT_IS_IN_WORKSPACE,false);
140     
141
142     // We add the field timeseries defined on this mesh, as children
143     // of the mesh SObject
144     MEDOP::FieldseriesHandlerList * fieldseriesHandlerList =
145       MEDOPFactoryClient::getDataManager()->getFieldseriesListOnMesh(meshHandler.id);
146     
147     for(CORBA::ULong iFieldseries=0; iFieldseries<fieldseriesHandlerList->length(); iFieldseries++) {
148       MEDOP::FieldseriesHandler fieldseriesHandler = (*fieldseriesHandlerList)[iFieldseries];
149       SALOMEDS::SObject_var soFieldseries = _studyEditor->newObject(soMesh);
150
151       std::string label(fieldseriesHandler.name);
152       label +=" ("+std::string(XmedDataObject::mapTypeOfFieldLabel[fieldseriesHandler.type])+")";
153       _studyEditor->setName(soFieldseries,label.c_str());
154
155       _studyEditor->setIcon(soFieldseries,"datasource_field.png");
156       _studyEditor->setParameterInt(soFieldseries,OBJECT_ID,fieldseriesHandler.id);
157       _studyEditor->setParameterBool(soFieldseries,OBJECT_IS_IN_WORKSPACE,false);
158     }
159   }
160
161   return datasourceHandler;
162 }
163
164
165 void DatasourceController::OnAddDatasource()
166 {
167   // Dialog to get the filename where the input data are read from
168   QStringList filter;
169   filter.append(QObject::tr("MED files (*.med)"));
170
171   QString filename = SUIT_FileDlg::getFileName(_salomeModule->getApp()->desktop(),
172                                                "",
173                                                filter,
174                                                QObject::tr("Import MED fields"),
175                                                true);
176
177   if ( filename.isEmpty() ) return;
178
179   this->addDatasource(QCHARSTAR(filename));
180   _salomeModule->updateObjBrowser(true);
181 }
182
183 #include "DlgImageToMed.hxx"
184 #include <stdio.h>
185 #include <stdlib.h>
186 void DatasourceController::OnAddImagesource()
187 {
188
189   DlgImageToMed dialog;
190   dialog.setAutoLoaded(true);
191   int choice = dialog.exec();
192   if ( choice == QDialog::Rejected ) {
193     // The user decides to cancel the operation
194     return;
195   }
196
197   QString imageFilename = dialog.getImageFilepath();
198   QString medFilename   = dialog.getMedFilepath();
199   bool autoLoad         = dialog.isAutoLoaded();
200   
201   std::string ROOT_DIR(getenv("MED_ROOT_DIR"));
202   std::string command(ROOT_DIR+"/bin/salome/med/image2med.py");
203   command += " -i "+QS2S(imageFilename);
204   command += " -m "+QS2S(medFilename);
205   int error = system(command.c_str());
206   if ( error != 0 ) {
207     QMessageBox::critical(_salomeModule->getApp()->desktop(),
208            tr("Operation failed"),
209            tr("The creation of med data from the image file failed"));
210     return;
211   }
212
213   if ( autoLoad ) {
214     this->addDatasource(QCHARSTAR(medFilename));
215     _salomeModule->updateObjBrowser(true);
216   }
217
218 }
219
220 void DatasourceController::OnExpandField()
221 {
222   // We need a studyEditor updated on the active study
223   _studyEditor->updateActiveStudy();
224
225   // Get the selected objects in the study (SObject)
226   SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects();
227   for (int i=0; i<listOfSObject->size(); i++) {  
228     SALOMEDS::SObject_var soFieldseries = listOfSObject->at(i);
229
230     // First retrieve the fieldseries id associated to this study object 
231     long fieldseriesId = _studyEditor->getParameterInt(soFieldseries,OBJECT_ID);
232     STDLOG("Expand the field timeseries "<<fieldseriesId);
233
234     // If fieldseriesId equals -1, then it means that it is not a
235     // fieldseries managed by the MED module, and we stop this
236     // function process.
237     if ( fieldseriesId < 0 )
238       continue;
239     // _GBO_ A better correction should be to no display the
240     // contextual menu if the selected object is not conform
241
242     // Then retrieve the list of fields in this timeseries
243     MEDOP::FieldHandlerList * fieldHandlerList =
244       MEDOPFactoryClient::getDataManager()->getFieldListInFieldseries(fieldseriesId);
245
246     // Finally, create an entry for each of the field
247     for(CORBA::ULong iField=0; iField<fieldHandlerList->length(); iField++) {
248       MEDOP::FieldHandler fieldHandler = (*fieldHandlerList)[iField];
249       SALOMEDS::SObject_var soField = _studyEditor->newObject(soFieldseries);
250       std::string label("it="); label += ToString(fieldHandler.iteration);
251       _studyEditor->setName(soField,label.c_str());
252       _studyEditor->setParameterInt(soField, OBJECT_ID, fieldHandler.id);
253       _studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,false);
254     }
255   }
256   _salomeModule->updateObjBrowser(true);
257 }
258
259 void DatasourceController::OnVisualize() {
260   STDLOG("OnVisualize: To Be Implemented");
261
262   // We need a _studyEditor updated on the active study
263   _studyEditor->updateActiveStudy();
264
265   // Get the selected objects in the study (SObject)
266   SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects();
267
268   // For each object, emit a signal to the workspace to request a
269   // visualisation using the tui command (so that the user can see how
270   // to make a view of an object from the tui console).
271   for (int i=0; i<listOfSObject->size(); i++) {
272     SALOMEDS::SObject_var soField = listOfSObject->at(i);
273     int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID);
274     // If fieldId equals -1, then it means that it is not a field
275     // managed by the MED module, and we stop this function process.
276     if ( fieldId < 0 )
277       continue;
278
279     MEDOP::FieldHandler * fieldHandler = MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
280
281     DatasourceEvent * event = new DatasourceEvent();
282     event->eventtype = DatasourceEvent::EVENT_VIEW_OBJECT;
283     XmedDataObject * dataObject = new XmedDataObject();
284     dataObject->setFieldHandler(*fieldHandler);
285     event->objectdata  = dataObject;
286     emit datasourceSignal(event);    
287   }
288
289 }
290
291 void DatasourceController::OnUseInWorkspace() {
292   // We need a studyEditor updated on the active study
293   _studyEditor->updateActiveStudy();
294
295   // Get the selected objects in the study (SObject)
296   SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects();
297   if ( listOfSObject->size() == 1 ) {
298     // In this case we ask the name of the variable for the python
299     // console
300
301     // >>>
302     // _GBO_ Note that it works only for a single field but the
303     // XmedDataObject will be improved to deal with mesh, timeseries
304     // and single field in a futur version. We suppose here that a
305     // single field has been selected. 
306     // <<<
307
308     SALOMEDS::SObject_var soField = listOfSObject->at(0);
309
310     bool isInWorkspace = _studyEditor->getParameterBool(soField,OBJECT_IS_IN_WORKSPACE);
311     if ( isInWorkspace ) {
312       QMessageBox::warning(_salomeModule->getApp()->desktop(),
313          tr("Operation not allowed"),
314          tr("This field is already defined in the workspace"));
315       return;
316     }
317
318     int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID);
319
320     // If fieldId equals -1, then it means that it is not a field
321     // managed by the MED module, and we stop this function process.
322     if ( fieldId < 0 ) {
323       QMessageBox::warning(_salomeModule->getApp()->desktop(),
324          tr("Operation not allowed"),
325          tr("This element is not a field object"));
326       return;
327     }
328
329     MEDOP::FieldHandler * fieldHandler =
330       MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
331
332     QString alias(fieldHandler->fieldname);
333     DlgAlias dialog;
334     dialog.setAlias(alias);
335     int choice = dialog.exec();
336     if ( choice == QDialog::Rejected ) {
337       // The user decides to cancel the operation
338       return;
339     }
340     alias = dialog.getAlias();
341
342     DatasourceEvent * event = new DatasourceEvent();
343     event->eventtype = DatasourceEvent::EVENT_USE_OBJECT;
344     XmedDataObject * dataObject = new XmedDataObject();
345     dataObject->setFieldHandler(*fieldHandler);
346     event->objectdata  = dataObject;
347     event->objectalias = alias;
348     emit datasourceSignal(event);
349     // Tag the item to prevent double import
350     _studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,true);
351     // Tag the field as persistent on the server. It means that a
352     // saving of the workspace will save at least this field (maybe it
353     // should be an option?)
354     MEDOPFactoryClient::getDataManager()->markAsPersistent(fieldId, true);
355   }
356   else {
357     // In this case, we don't ask the user to specify an alias for
358     // each item, we just import the whole set of items.
359     for (int i=0; i<listOfSObject->size(); i++) {
360       SALOMEDS::SObject_var soField = listOfSObject->at(i);
361
362       bool isInWorkspace = _studyEditor->getParameterBool(soField,OBJECT_IS_IN_WORKSPACE);
363       if ( !isInWorkspace ) {
364   int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID);
365   MEDOP::FieldHandler * fieldHandler =
366     MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
367   DatasourceEvent * event = new DatasourceEvent();
368   event->eventtype = DatasourceEvent::EVENT_IMPORT_OBJECT;
369   XmedDataObject * dataObject = new XmedDataObject();
370   dataObject->setFieldHandler(*fieldHandler);
371   event->objectdata  = dataObject;
372   emit datasourceSignal(event);
373   // Note that this signal is processed by the WorkspaceController
374
375   // Tag the item to prevent double import
376   _studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,true);
377   // Tag the field as persistent on the server. It means that a
378   // saving of the workspace will save at least this field (maybe it
379   // should be an option?)
380   MEDOPFactoryClient::getDataManager()->markAsPersistent(fieldId, true);
381       }
382       else {
383   STDLOG("The field "<<_studyEditor->getName(soField)<<
384          " is already defined in the workspace");
385       }
386     }
387   }
388 }
389
390
391 void DatasourceController::OnChangeUnderlyingMesh() {
392   // We need a studyEditor updated on the active study
393   _studyEditor->updateActiveStudy();
394
395   // Get the selected objects in the study (SObject). In cas of a
396   // multiple selection, we consider only the first item. At least one
397   // item must be selected.
398   SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects();
399   if ( listOfSObject->size() > 0 ) {
400     SALOMEDS::SObject_var soField = listOfSObject->at(0);
401     int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID);    
402     // _GBO_ : the dialog should not be modal, so that we can choose a
403     // mesh in the browser. Then we have to emit a signal from the
404     // dialog.accept, connected to a slot of the DatasourceControler
405     _dlgChangeUnderlyingMesh->setFieldId(fieldId);
406     Qt::WindowFlags flags = _dlgChangeUnderlyingMesh->windowFlags();
407     _dlgChangeUnderlyingMesh->setWindowFlags(flags | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint);
408     _dlgChangeUnderlyingMesh->open();
409   }
410 }
411
412 void DatasourceController::OnChangeUnderlyingMeshInputValidated() {
413   int meshId = _dlgChangeUnderlyingMesh->getMeshId();
414   STDLOG("meshId = " << ToString(meshId));
415   int fieldId = _dlgChangeUnderlyingMesh->getFieldId();
416   MEDOP::FieldHandler * fieldHandler =
417     MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
418   
419   // We don't modify the original field but create first a duplicate
420   MEDOP::FieldHandler * duplicate = MEDOPFactoryClient::getCalculator()->dup(*fieldHandler);
421   MEDOPFactoryClient::getDataManager()->changeUnderlyingMesh(duplicate->id, meshId);
422
423   // Request once more the duplicate to update the meta-data on this
424   // client side
425   duplicate = MEDOPFactoryClient::getDataManager()->getFieldHandler(duplicate->id);
426
427   // >>>
428   // WARN: the following is a temporary code for test purpose
429   // Automatically add in ws
430   DatasourceEvent * event = new DatasourceEvent();
431   event->eventtype = DatasourceEvent::EVENT_IMPORT_OBJECT;
432   XmedDataObject * dataObject = new XmedDataObject();
433   dataObject->setFieldHandler(*duplicate);
434   event->objectdata  = dataObject;
435   emit datasourceSignal(event);
436   // Note that this signal is processed by the WorkspaceController
437   
438   // Tag the item to prevent double import
439   //_studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,true);
440   
441   
442 }