1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // Author : Guillaume Boulant (EDF)
22 #include "DatasourceController.hxx"
23 #include "DatasourceConstants.hxx"
25 #include "MEDOPFactoryClient.hxx"
26 #include "QtHelper.hxx"
28 #include CORBA_CLIENT_HEADER(SALOMEDS)
29 #include <SUIT_FileDlg.h>
30 #include <SUIT_Desktop.h>
32 #include <QStringList>
34 #include <QMessageBox>
36 #include "DlgAlias.hxx"
39 // ==============================================================
40 // Datasource controller
41 // ==============================================================
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);
49 connect(_dlgChangeUnderlyingMesh,SIGNAL(inputValidated()),
50 this, SLOT(OnChangeUnderlyingMeshInputValidated()));
54 DatasourceController::~DatasourceController() {
55 STDLOG("Deleting the DatasourceController");
59 void DatasourceController::createActions() {
61 // Main actions (toolbar and menubar)
63 QString label = tr("LAB_ADD_DATA_SOURCE");
64 QString tooltip = tr("TIP_ADD_DATA_SOURCE");
65 QString icon = tr("ICO_DATASOURCE_ADD");
67 actionId = _salomeModule->createStandardAction(label,this, SLOT(OnAddDatasource()),icon,tooltip);
68 _salomeModule->addActionInToolbar(actionId);
70 // This action has to be placed in the general file menu with the label "Import MED file"
71 int menuId = _salomeModule->createMenu( tr( "MEN_FILE" ), -1, 1 );
72 _salomeModule->addActionInMenubar(actionId, menuId);
74 label = tr("LAB_ADD_IMAGE_SOURCE");
75 tooltip = tr("TIP_ADD_IMAGE_SOURCE");
76 icon = tr("ICO_IMAGE_ADD");
77 actionId = _salomeModule->createStandardAction(label,this, SLOT(OnAddImagesource()),icon,tooltip);
78 _salomeModule->addActionInToolbar(actionId);
81 // Actions for popup menu only
83 // Expand field timeseries
84 label = tr("LAB_EXPAND_FIELD");
85 icon = tr("ICO_DATASOURCE_EXPAND_FIELD");
86 actionId = _salomeModule->createStandardAction(label,this,SLOT(OnExpandField()),icon);
87 _salomeModule->addActionInPopupMenu(actionId);
89 // Create a control view
90 label = tr("LAB_VISUALIZE");
91 icon = tr("ICO_DATASOURCE_VIEW");
92 actionId = _salomeModule->createStandardAction(label,this,SLOT(OnVisualize()),icon);
93 _salomeModule->addActionInPopupMenu(actionId);
96 label = tr("LAB_USE_IN_WORKSPACE");
97 icon = tr("ICO_DATASOURCE_USE");
98 actionId = _salomeModule->createStandardAction(label,this,SLOT(OnUseInWorkspace()),icon);
99 _salomeModule->addActionInPopupMenu(actionId);
101 // Change underlying mesh (note that this action creates a new field in
102 // the workspace that corresponds to a copy of the selected field
103 // modified by the change of the underlying mesh.
104 label = tr("LAB_CHANGE_MESH");
105 icon = tr("ICO_DATASOURCE_CHANGE_MESH");
106 actionId = _salomeModule->createStandardAction(label,this,SLOT(OnChangeUnderlyingMesh()),icon);
107 _salomeModule->addActionInPopupMenu(actionId);
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 * informations to the GUI, and the GUI creates a tree view of these
116 * data in the study object browser.
118 MEDOP::DatasourceHandler * DatasourceController::addDatasource(const char * filename) {
120 MEDOP::DatasourceHandler * datasourceHandler =
121 MEDOPFactoryClient::getDataManager()->addDatasource(filename);
123 // We need a studyEditor updated on the active study
124 _studyEditor->updateActiveStudy();
126 // Create a datasource SObject as a father of the module root
127 SALOMEDS::SComponent_var root = _studyEditor->findRoot(QCHARSTAR(_salomeModule->moduleName()));
128 SALOMEDS::SObject_var soDatasource = _studyEditor->newObject(root);
129 _studyEditor->setName(soDatasource,datasourceHandler->name);
130 _studyEditor->setIcon(soDatasource,tr("ICO_DATASOURCE").toStdString().c_str());
131 _studyEditor->setParameterInt(soDatasource,OBJECT_ID,datasourceHandler->id);
134 // We can add the meshes as children of the datasource
135 MEDOP::MeshHandlerList * meshHandlerList =
136 MEDOPFactoryClient::getDataManager()->getMeshList(datasourceHandler->id);
138 for(CORBA::ULong iMesh=0; iMesh<meshHandlerList->length(); iMesh++) {
139 MEDOP::MeshHandler meshHandler = (*meshHandlerList)[iMesh];
140 SALOMEDS::SObject_var soMesh = _studyEditor->newObject(soDatasource);
141 _studyEditor->setName(soMesh,meshHandler.name);
142 _studyEditor->setIcon(soMesh,tr("ICO_DATASOURCE_MESH").toStdString().c_str());
143 _studyEditor->setParameterInt(soMesh,OBJECT_ID,meshHandler.id);
144 _studyEditor->setParameterBool(soMesh,OBJECT_IS_IN_WORKSPACE,false);
147 // We add the field timeseries defined on this mesh, as children
148 // of the mesh SObject
149 MEDOP::FieldseriesHandlerList * fieldseriesHandlerList =
150 MEDOPFactoryClient::getDataManager()->getFieldseriesListOnMesh(meshHandler.id);
152 for(CORBA::ULong iFieldseries=0; iFieldseries<fieldseriesHandlerList->length(); iFieldseries++) {
153 MEDOP::FieldseriesHandler fieldseriesHandler = (*fieldseriesHandlerList)[iFieldseries];
154 SALOMEDS::SObject_var soFieldseries = _studyEditor->newObject(soMesh);
156 std::string label(fieldseriesHandler.name);
157 label +=" ("+std::string(XmedDataObject::mapTypeOfFieldLabel[fieldseriesHandler.type])+")";
158 _studyEditor->setName(soFieldseries,label.c_str());
160 _studyEditor->setIcon(soFieldseries,tr("ICO_DATASOURCE_FIELD").toStdString().c_str());
161 _studyEditor->setParameterInt(soFieldseries,OBJECT_ID,fieldseriesHandler.id);
162 _studyEditor->setParameterBool(soFieldseries,OBJECT_IS_IN_WORKSPACE,false);
166 return datasourceHandler;
170 void DatasourceController::OnAddDatasource()
172 // Dialog to get the filename where the input data are read from
174 filter.append(tr("FILE_FILTER_MED"));
176 QString anInitialPath = "";
177 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
178 anInitialPath = QDir::currentPath();
181 QString filename = SUIT_FileDlg::getFileName(_salomeModule->getApp()->desktop(),
184 tr("IMPORT_MED_FIELDS"),
188 QStringList filenames = SUIT_FileDlg::getOpenFileNames( _salomeModule->getApp()->desktop(),
191 tr("IMPORT_MED_FIELDS") );
193 if ( filenames.count() <= 0 ) return;
194 for ( QStringList::ConstIterator itFile = filenames.begin();
195 itFile != filenames.end(); ++itFile ) {
196 QString filename = *itFile;
197 this->addDatasource(QCHARSTAR(filename));
198 _salomeModule->updateObjBrowser(true);
202 #include "DlgImageToMed.hxx"
205 void DatasourceController::OnAddImagesource()
208 DlgImageToMed dialog;
209 dialog.setAutoLoaded(true);
210 int choice = dialog.exec();
211 if ( choice == QDialog::Rejected ) {
212 // The user decides to cancel the operation
216 QString imageFilename = dialog.getImageFilepath();
217 QString medFilename = dialog.getMedFilepath();
218 bool autoLoad = dialog.isAutoLoaded();
220 std::string ROOT_DIR(getenv("MED_ROOT_DIR"));
221 std::string command(ROOT_DIR+"/bin/salome/med/image2med.py");
222 command += " -i "+QS2S(imageFilename);
223 command += " -m "+QS2S(medFilename);
224 int error = system(command.c_str());
226 QMessageBox::critical(_salomeModule->getApp()->desktop(),
227 tr("Operation failed"),
228 tr("The creation of med data from the image file failed"));
233 this->addDatasource(QCHARSTAR(medFilename));
234 _salomeModule->updateObjBrowser(true);
239 void DatasourceController::OnExpandField()
241 // We need a studyEditor updated on the active study
242 _studyEditor->updateActiveStudy();
244 // Get the selected objects in the study (SObject)
245 SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects();
246 for (int i=0; i<listOfSObject->size(); i++) {
247 SALOMEDS::SObject_var soFieldseries = listOfSObject->at(i);
249 // First retrieve the fieldseries id associated to this study object
250 long fieldseriesId = _studyEditor->getParameterInt(soFieldseries,OBJECT_ID);
251 STDLOG("Expand the field timeseries "<<fieldseriesId);
253 // If fieldseriesId equals -1, then it means that it is not a
254 // fieldseries managed by the MED module, and we stop this
256 if ( fieldseriesId < 0 )
258 // _GBO_ A better correction should be to no display the
259 // contextual menu if the selected object is not conform
261 // Then retrieve the list of fields in this timeseries
262 MEDOP::FieldHandlerList * fieldHandlerList =
263 MEDOPFactoryClient::getDataManager()->getFieldListInFieldseries(fieldseriesId);
265 // Finally, create an entry for each of the field
266 for(CORBA::ULong iField=0; iField<fieldHandlerList->length(); iField++) {
267 MEDOP::FieldHandler fieldHandler = (*fieldHandlerList)[iField];
268 SALOMEDS::SObject_var soField = _studyEditor->newObject(soFieldseries);
269 std::string label("it="); label += ToString(fieldHandler.iteration);
270 _studyEditor->setName(soField,label.c_str());
271 _studyEditor->setParameterInt(soField, OBJECT_ID, fieldHandler.id);
272 _studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,false);
275 _salomeModule->updateObjBrowser(true);
278 void DatasourceController::OnVisualize() {
279 STDLOG("OnVisualize: To Be Implemented");
281 // We need a _studyEditor updated on the active study
282 _studyEditor->updateActiveStudy();
284 // Get the selected objects in the study (SObject)
285 SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects();
287 // For each object, emit a signal to the workspace to request a
288 // visualisation using the tui command (so that the user can see how
289 // to make a view of an object from the tui console).
290 for (int i=0; i<listOfSObject->size(); i++) {
291 SALOMEDS::SObject_var soField = listOfSObject->at(i);
292 int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID);
293 // If fieldId equals -1, then it means that it is not a field
294 // managed by the MED module, and we stop this function process.
298 MEDOP::FieldHandler * fieldHandler = MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
300 DatasourceEvent * event = new DatasourceEvent();
301 event->eventtype = DatasourceEvent::EVENT_VIEW_OBJECT;
302 XmedDataObject * dataObject = new XmedDataObject();
303 dataObject->setFieldHandler(*fieldHandler);
304 event->objectdata = dataObject;
305 emit datasourceSignal(event);
310 void DatasourceController::OnUseInWorkspace() {
311 // We need a studyEditor updated on the active study
312 _studyEditor->updateActiveStudy();
314 // Get the selected objects in the study (SObject)
315 SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects();
316 if ( listOfSObject->size() == 1 ) {
317 // In this case we ask the name of the variable for the python
321 // _GBO_ Note that it works only for a single field but the
322 // XmedDataObject will be improved to deal with mesh, timeseries
323 // and single field in a futur version. We suppose here that a
324 // single field has been selected.
327 SALOMEDS::SObject_var soField = listOfSObject->at(0);
329 bool isInWorkspace = _studyEditor->getParameterBool(soField,OBJECT_IS_IN_WORKSPACE);
330 if ( isInWorkspace ) {
331 QMessageBox::warning(_salomeModule->getApp()->desktop(),
332 tr("Operation not allowed"),
333 tr("This field is already defined in the workspace"));
337 int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID);
339 // If fieldId equals -1, then it means that it is not a field
340 // managed by the MED module, and we stop this function process.
342 QMessageBox::warning(_salomeModule->getApp()->desktop(),
343 tr("Operation not allowed"),
344 tr("This element is not a field object"));
348 MEDOP::FieldHandler * fieldHandler =
349 MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
351 QString alias(fieldHandler->fieldname);
353 dialog.setAlias(alias);
354 int choice = dialog.exec();
355 if ( choice == QDialog::Rejected ) {
356 // The user decides to cancel the operation
359 alias = dialog.getAlias();
361 DatasourceEvent * event = new DatasourceEvent();
362 event->eventtype = DatasourceEvent::EVENT_USE_OBJECT;
363 XmedDataObject * dataObject = new XmedDataObject();
364 dataObject->setFieldHandler(*fieldHandler);
365 event->objectdata = dataObject;
366 event->objectalias = alias;
367 emit datasourceSignal(event);
368 // Tag the item to prevent double import
369 _studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,true);
370 // Tag the field as persistent on the server. It means that a
371 // saving of the workspace will save at least this field (maybe it
372 // should be an option?)
373 MEDOPFactoryClient::getDataManager()->markAsPersistent(fieldId, true);
376 // In this case, we don't ask the user to specify an alias for
377 // each item, we just import the whole set of items.
378 for (int i=0; i<listOfSObject->size(); i++) {
379 SALOMEDS::SObject_var soField = listOfSObject->at(i);
381 bool isInWorkspace = _studyEditor->getParameterBool(soField,OBJECT_IS_IN_WORKSPACE);
382 if ( !isInWorkspace ) {
383 int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID);
384 MEDOP::FieldHandler * fieldHandler =
385 MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
386 DatasourceEvent * event = new DatasourceEvent();
387 event->eventtype = DatasourceEvent::EVENT_IMPORT_OBJECT;
388 XmedDataObject * dataObject = new XmedDataObject();
389 dataObject->setFieldHandler(*fieldHandler);
390 event->objectdata = dataObject;
391 emit datasourceSignal(event);
392 // Note that this signal is processed by the WorkspaceController
394 // Tag the item to prevent double import
395 _studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,true);
396 // Tag the field as persistent on the server. It means that a
397 // saving of the workspace will save at least this field (maybe it
398 // should be an option?)
399 MEDOPFactoryClient::getDataManager()->markAsPersistent(fieldId, true);
402 STDLOG("The field "<<_studyEditor->getName(soField)<<
403 " is already defined in the workspace");
410 void DatasourceController::OnChangeUnderlyingMesh() {
411 // We need a studyEditor updated on the active study
412 _studyEditor->updateActiveStudy();
414 // Get the selected objects in the study (SObject). In cas of a
415 // multiple selection, we consider only the first item. At least one
416 // item must be selected.
417 SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects();
418 if ( listOfSObject->size() > 0 ) {
419 SALOMEDS::SObject_var soField = listOfSObject->at(0);
420 int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID);
421 // _GBO_ : the dialog should not be modal, so that we can choose a
422 // mesh in the browser. Then we have to emit a signal from the
423 // dialog.accept, connected to a slot of the DatasourceControler
424 _dlgChangeUnderlyingMesh->setFieldId(fieldId);
425 Qt::WindowFlags flags = _dlgChangeUnderlyingMesh->windowFlags();
426 _dlgChangeUnderlyingMesh->setWindowFlags(flags | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint);
427 _dlgChangeUnderlyingMesh->open();
431 void DatasourceController::OnChangeUnderlyingMeshInputValidated() {
432 int meshId = _dlgChangeUnderlyingMesh->getMeshId();
433 STDLOG("meshId = " << ToString(meshId));
434 int fieldId = _dlgChangeUnderlyingMesh->getFieldId();
435 MEDOP::FieldHandler * fieldHandler =
436 MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
438 // We don't modify the original field but create first a duplicate
439 MEDOP::FieldHandler * duplicate = MEDOPFactoryClient::getCalculator()->dup(*fieldHandler);
440 MEDOPFactoryClient::getDataManager()->changeUnderlyingMesh(duplicate->id, meshId);
442 // Request once more the duplicate to update the meta-data on this
444 duplicate = MEDOPFactoryClient::getDataManager()->getFieldHandler(duplicate->id);
447 // WARN: the following is a temporary code for test purpose
448 // Automatically add in ws
449 DatasourceEvent * event = new DatasourceEvent();
450 event->eventtype = DatasourceEvent::EVENT_IMPORT_OBJECT;
451 XmedDataObject * dataObject = new XmedDataObject();
452 dataObject->setFieldHandler(*duplicate);
453 event->objectdata = dataObject;
454 emit datasourceSignal(event);
455 // Note that this signal is processed by the WorkspaceController
457 // Tag the item to prevent double import
458 //_studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,true);