Salome HOME
fix of typos by kunda http://www.salome-platform.org/forum/forum_10/789486812
[modules/med.git] / src / MEDCalc / gui / DatasourceController.cxx
1 // Copyright (C) 2007-2016  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 <MEDCalcConstants.hxx>
24
25 #include <SalomeApp_Application.h>
26 #include <SalomeApp_Study.h>
27 #include <SalomeApp_DataObject.h>
28
29 #include <SALOME_ListIO.hxx>
30 #include <LightApp_SelectionMgr.h>
31
32 #include <SALOME_LifeCycleCORBA.hxx>
33 #include <SALOMEDS_SObject.hxx>
34 #include <SALOMEDS_Study.hxx>
35
36 #include "MEDFactoryClient.hxx"
37 #include "MEDModule.hxx"
38 #include "QtHelper.hxx"
39
40 #include CORBA_CLIENT_HEADER(SALOMEDS)
41 #include CORBA_CLIENT_HEADER(SALOMEDS_Attributes)
42 #include <SUIT_FileDlg.h>
43 #include <SUIT_Desktop.h>
44
45 #include <QStringList>
46 #include <QString>
47 #include <QMessageBox>
48 #include <QFileDialog>
49
50 #include "DlgAlias.hxx"
51
52 //
53 // ==============================================================
54 // Datasource controller
55 // ==============================================================
56 //
57 DatasourceController::DatasourceController(MEDModule* salomeModule)
58 {
59   STDLOG("Creating a DatasourceController");
60   _salomeModule = salomeModule;
61   _studyEditor = _salomeModule->getStudyEditor();
62 }
63
64 DatasourceController::~DatasourceController() {
65   STDLOG("Deleting the DatasourceController");
66 }
67
68 void DatasourceController::createActions() {
69   int toolbarId = _salomeModule->createTool("Datasource", "DatasourceToolbar");
70
71   //
72   // Main actions (toolbar and menubar)
73   //
74   QString label   = tr("LAB_ADD_DATA_SOURCE");
75   QString tooltip = tr("TIP_ADD_DATA_SOURCE");
76   QString icon    = tr("ICO_DATASOURCE_ADD");
77   int actionId;
78   actionId = _salomeModule->createStandardAction(label,this, SLOT(OnAddDatasource()),icon,tooltip);
79   _salomeModule->createTool(actionId, toolbarId);
80
81   // This action has to be placed in the general file menu with the label "Import MED file"
82   int menuId = _salomeModule->createMenu( tr( "MEN_FILE" ), -1,  1 );
83   _salomeModule->action(actionId)->setIconVisibleInMenu(true);
84   _salomeModule->createMenu(actionId, menuId, 10);
85
86   label   = tr("LAB_ADD_IMAGE_SOURCE");
87   tooltip = tr("TIP_ADD_IMAGE_SOURCE");
88   icon    = tr("ICO_IMAGE_ADD");
89   actionId = _salomeModule->createStandardAction(label,this, SLOT(OnAddImagesource()),icon,tooltip);
90   _salomeModule->createTool(actionId, toolbarId);
91   _salomeModule->action(actionId)->setIconVisibleInMenu(true);
92   _salomeModule->createMenu(actionId, menuId, 20);
93
94   //
95   // Actions for popup menu only
96   //
97   // Expand field timeseries
98   label = tr("LAB_EXPAND_FIELD");
99   icon  = tr("ICO_DATASOURCE_EXPAND_FIELD");
100   actionId = _salomeModule->createStandardAction(label,this,SLOT(OnExpandField()),icon);
101   _salomeModule->addActionInPopupMenu(actionId);
102
103   // Use in workspace
104   label = tr("LAB_USE_IN_WORKSPACE");
105   icon  = tr("ICO_DATASOURCE_USE");
106   actionId = _salomeModule->createStandardAction(label,this,SLOT(OnUseInWorkspace()),icon);
107   _salomeModule->addActionInPopupMenu(actionId);
108
109 }
110
111 /**
112  * This function adds the specified MED file as a datasource in the
113  * dataspace. Technically speaking, the engine loads the
114  * meta-information concerning med data from the file, gives this
115  * information to the GUI, and the GUI creates a tree view of these
116  * data in the study object browser.
117  */
118 // This function emits a signal that will be caught by workspace to delegate command (datasource creation) to python console.
119 void
120 DatasourceController::addDatasource(const char* filename)
121 {
122   DatasourceEvent* event = new DatasourceEvent();
123   event->eventtype = DatasourceEvent::EVENT_ADD_DATASOURCE;
124   event->objectalias = filename;
125   emit datasourceSignal(event);  // --> WorkspaceController::processDatasourceEvent()
126 //#ifdef MED_WITH_QTTESTING
127 //  _dirtyAddDataSource = true;
128 //  while(_dirtyAddDataSource)
129 //    QApplication::processEvents();
130 //#endif
131 }
132
133 // After above data source creation, python console emits a signal, forwarded by workspace, to update the GUI
134 void
135 DatasourceController::updateTreeViewWithNewDatasource(const MEDCALC::DatasourceHandler* datasourceHandler)
136 {
137   if (!datasourceHandler) {
138     return;
139   }
140
141   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(_salomeModule->application()->activeStudy());
142   _PTR(Study) studyDS = study->studyDS();
143
144   _salomeModule->engine()->addDatasourceToStudy(_CAST(Study, studyDS)->GetStudy(), *datasourceHandler);
145
146   // update Object browser
147   _salomeModule->getApp()->updateObjectBrowser(true);
148
149 //#ifdef MED_WITH_QTTESTING
150 //  _dirtyAddDataSource = false;
151 //#endif
152 }
153
154 void DatasourceController::OnAddDatasource()
155 {
156   // Dialog to get the filename where the input data are read from
157   QStringList filter;
158   filter.append(tr("FILE_FILTER_MED"));
159
160   QString anInitialPath = "";
161   if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
162     anInitialPath = QDir::currentPath();
163
164 //  QStringList filenames = SUIT_FileDlg::getOpenFileNames( _salomeModule->getApp()->desktop(),
165 //                                                          anInitialPath,
166 //                                                          filter,
167 //                                                          tr("IMPORT_MED_FIELDS") );
168   // [ABN] the below to be compatible with QtTesting:
169   QStringList filenames = QFileDialog::getOpenFileNames( _salomeModule->getApp()->desktop(),
170                                                           tr("IMPORT_MED_FIELDS"),
171                                                           anInitialPath,
172                                                           tr("FILE_FILTER_MED") );
173
174   if ( filenames.count() <= 0 ) return;
175   for ( QStringList::ConstIterator itFile = filenames.begin();
176         itFile != filenames.end(); ++itFile ) {
177     QString filename = *itFile;
178     this->addDatasource(QCHARSTAR(filename));
179     _salomeModule->updateObjBrowser(true);
180   }
181 }
182
183 #include "DlgImageToMed.hxx"
184 void DatasourceController::OnAddImagesource()
185 {
186
187   DlgImageToMed dialog;
188   dialog.setAutoLoaded(true);
189   int choice = dialog.exec();
190   if ( choice == QDialog::Rejected ) {
191     // The user decides to cancel the operation
192     return;
193   }
194
195   QString imageFilename = dialog.getImageFilepath();
196   /*
197   QString medFilename   = dialog.getMedFilepath();
198   bool autoLoad         = dialog.isAutoLoaded();
199
200   std::string ROOT_DIR(getenv("MED_ROOT_DIR"));
201   std::string command(ROOT_DIR+"/bin/salome/med/image2med.py");
202   command += " -i "+QS2S(imageFilename);
203   command += " -m "+QS2S(medFilename);
204   int error = system(command.c_str());
205   if ( error != 0 ) {
206     QMessageBox::critical(_salomeModule->getApp()->desktop(),
207            tr("Operation failed"),
208            tr("The creation of med data from the image file failed"));
209     return;
210   }
211
212   if ( autoLoad ) {
213     this->addDatasource(QCHARSTAR(medFilename));
214     _salomeModule->updateObjBrowser(true);
215   }
216   */
217
218   DatasourceEvent* event = new DatasourceEvent();
219   event->eventtype = DatasourceEvent::EVENT_ADD_IMAGE_AS_DATASOURCE;
220   event->objectalias = imageFilename;
221   emit datasourceSignal(event); // --> WorkspaceController::processDatasourceEvent()
222 }
223
224 void DatasourceController::OnExpandField()
225 {
226   // We need a studyEditor updated on the active study
227   _studyEditor->updateActiveStudy();
228
229   // Get the selected objects in the study (SObject)
230   SALOME_StudyEditor::SObjectList* listOfSObject = _studyEditor->getSelectedObjects();
231   for (int i=0; i<listOfSObject->size(); i++) {
232     SALOMEDS::SObject_var soFieldseries = listOfSObject->at(i);
233     std::string name(_studyEditor->getName(soFieldseries));
234     if (soFieldseries->_is_nil() || name == "MEDCalc")
235       return;
236
237     // First retrieve the fieldseries id associated to this study object
238     SALOMEDS::GenericAttribute_var anAttr;
239     SALOMEDS::AttributeParameter_var aParam;
240     if ( soFieldseries->FindAttribute(anAttr,"AttributeParameter") ) {
241       aParam = SALOMEDS::AttributeParameter::_narrow(anAttr);
242       if (! aParam->IsSet(FIELD_SERIES_ID, PT_INTEGER))
243         return;
244     }
245     long fieldseriesId = aParam->GetInt(FIELD_SERIES_ID);
246     STDLOG("Expand the field timeseries "<<fieldseriesId);
247
248     // If fieldseriesId equals -1, then it means that it is not a
249     // fieldseries managed by the MED module, and we stop this
250     // function process.
251     if ( fieldseriesId < 0 )
252       continue;
253     // _GBO_ A better correction should be to no display the
254     // contextual menu if the selected object is not conform
255
256     // Then retrieve the list of fields in this timeseries
257     MEDCALC::FieldHandlerList* fieldHandlerList =
258       MEDFactoryClient::getDataManager()->getFieldListInFieldseries(fieldseriesId);
259
260     // Finally, create an entry for each of the field
261     for(CORBA::ULong iField=0; iField<fieldHandlerList->length(); iField++) {
262       MEDCALC::FieldHandler fieldHandler = (*fieldHandlerList)[iField];
263       SALOMEDS::SObject_var soField = _studyEditor->newObject(soFieldseries);
264       std::string label("it="); label += ToString(fieldHandler.iteration);
265       _studyEditor->setName(soField,label.c_str());
266       _studyEditor->setParameterInt(soField, FIELD_ID, fieldHandler.id);
267       _studyEditor->setParameterBool(soField,IS_IN_WORKSPACE,false);
268     }
269   }
270   _salomeModule->updateObjBrowser(true);
271 }
272
273 void DatasourceController::OnUseInWorkspace() {
274   // We need a studyEditor updated on the active study
275   _studyEditor->updateActiveStudy();
276
277   // Get the selected objects in the study (SObject)
278   SALOME_StudyEditor::SObjectList* listOfSObject = _studyEditor->getSelectedObjects();
279   if ( listOfSObject->size() == 1 ) {
280     // In this case we ask the name of the variable for the python
281     // console
282
283     // >>>
284     // _GBO_ Note that it works only for a single field but the
285     // XmedDataObject will be improved to deal with mesh, timeseries
286     // and single field in a futur version. We suppose here that a
287     // single field has been selected.
288     // <<<
289
290     SALOMEDS::SObject_var soField = listOfSObject->at(0);
291     std::string name(_studyEditor->getName(soField));
292     if (soField->_is_nil() || name == "MEDCalc")
293       return;
294     SALOMEDS::GenericAttribute_var anAttr;
295     SALOMEDS::AttributeParameter_var aParam;
296     if ( soField->FindAttribute(anAttr,"AttributeParameter") ) {
297       aParam = SALOMEDS::AttributeParameter::_narrow(anAttr);
298       if (! aParam->IsSet(IS_IN_WORKSPACE, PT_BOOLEAN))
299         return;
300     }
301     bool isInWorkspace = aParam->GetBool(IS_IN_WORKSPACE);
302     if ( isInWorkspace ) {
303       QMessageBox::warning(_salomeModule->getApp()->desktop(),
304          tr("Operation not allowed"),
305          tr("This field is already defined in the workspace"));
306       return;
307     }
308
309     if (! aParam->IsSet(FIELD_ID, PT_INTEGER))
310       return;
311     int fieldId = aParam->GetInt(FIELD_ID);
312
313     // If fieldId equals -1, then it means that it is not a field
314     // managed by the MED module, and we stop this function process.
315     if ( fieldId < 0 ) {
316       QMessageBox::warning(_salomeModule->getApp()->desktop(),
317          tr("Operation not allowed"),
318          tr("This element is not a field object"));
319       return;
320     }
321
322     MEDCALC::FieldHandler* fieldHandler =
323       MEDFactoryClient::getDataManager()->getFieldHandler(fieldId);
324
325     if (! fieldHandler) {
326       QMessageBox::warning(_salomeModule->getApp()->desktop(),
327          tr("Operation not allowed"),
328          tr("No field is defined"));
329       return;
330     }
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);  // --> WorkspaceController::processDatasourceEvent()
349     // Tag the item to prevent double import
350     //    _studyEditor->setParameterBool(soField,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     MEDFactoryClient::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       if (soField->_is_nil())
362         continue;
363       SALOMEDS::GenericAttribute_var anAttr;
364       SALOMEDS::AttributeParameter_var aParam;
365       if ( soField->FindAttribute(anAttr,"AttributeParameter") ) {
366         aParam = SALOMEDS::AttributeParameter::_narrow(anAttr);
367         if (! aParam->IsSet(IS_IN_WORKSPACE, PT_BOOLEAN))
368           return;
369       }
370       bool isInWorkspace = aParam->GetBool(IS_IN_WORKSPACE);
371       if ( !isInWorkspace ) {
372         if (! aParam->IsSet(FIELD_ID, PT_INTEGER))
373           continue;
374         int fieldId = aParam->GetInt(FIELD_ID);
375         MEDCALC::FieldHandler* fieldHandler =
376           MEDFactoryClient::getDataManager()->getFieldHandler(fieldId);
377         DatasourceEvent* event = new DatasourceEvent();
378         event->eventtype = DatasourceEvent::EVENT_IMPORT_OBJECT;
379         XmedDataObject* dataObject = new XmedDataObject();
380         dataObject->setFieldHandler(*fieldHandler);
381         event->objectdata  = dataObject;
382         emit datasourceSignal(event); // --> WorkspaceController::processDatasourceEvent()
383         // Note that this signal is processed by the WorkspaceController
384
385         // Tag the item to prevent double import
386         //        _studyEditor->setParameterBool(soField,IS_IN_WORKSPACE,true);
387         // Tag the field as persistent on the server. It means that a
388         // saving of the workspace will save at least this field (maybe it
389         // should be an option?)
390         MEDFactoryClient::getDataManager()->markAsPersistent(fieldId, true);
391       }
392       else {
393         STDLOG("The field "<<_studyEditor->getName(soField)<<
394                " is already defined in the workspace");
395       }
396     }
397   }
398 }
399
400 void
401 DatasourceController::processWorkspaceEvent(const MEDCALC::MedEvent* event)
402 {
403   if ( event->type == MEDCALC::EVENT_ADD_DATASOURCE ) {
404     MEDCALC::DatasourceHandler* datasourceHandler = MEDFactoryClient::getDataManager()->getDatasourceHandler(event->filename);
405     this->updateTreeViewWithNewDatasource(datasourceHandler);
406   }
407 }