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 = QString("Add Data Source");
64 QString tooltip = QString("Add a file data source (file providing med data)");
65 QString icon = QString("datasource_add.png");
67 actionId = _salomeModule->createStandardAction(label,this, SLOT(OnAddDatasource()),icon,tooltip);
68 _salomeModule->addActionInToolbar(actionId);
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);
77 // Actions for popup menu only
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);
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);
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);
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);
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.
113 MEDOP::DatasourceHandler * DatasourceController::addDatasource(const char * filename) {
115 MEDOP::DatasourceHandler * datasourceHandler =
116 MEDOPFactoryClient::getDataManager()->addDatasource(filename);
118 // We need a studyEditor updated on the active study
119 _studyEditor->updateActiveStudy();
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);
129 // We can add the meshes as children of the datasource
130 MEDOP::MeshHandlerList * meshHandlerList =
131 MEDOPFactoryClient::getDataManager()->getMeshList(datasourceHandler->id);
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);
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);
147 for(CORBA::ULong iFieldseries=0; iFieldseries<fieldseriesHandlerList->length(); iFieldseries++) {
148 MEDOP::FieldseriesHandler fieldseriesHandler = (*fieldseriesHandlerList)[iFieldseries];
149 SALOMEDS::SObject_var soFieldseries = _studyEditor->newObject(soMesh);
151 std::string label(fieldseriesHandler.name);
152 label +=" ("+std::string(XmedDataObject::mapTypeOfFieldLabel[fieldseriesHandler.type])+")";
153 _studyEditor->setName(soFieldseries,label.c_str());
155 _studyEditor->setIcon(soFieldseries,"datasource_field.png");
156 _studyEditor->setParameterInt(soFieldseries,OBJECT_ID,fieldseriesHandler.id);
157 _studyEditor->setParameterBool(soFieldseries,OBJECT_IS_IN_WORKSPACE,false);
161 return datasourceHandler;
165 void DatasourceController::OnAddDatasource()
167 // Dialog to get the filename where the input data are read from
169 filter.append(QObject::tr("MED files (*.med)"));
171 QString filename = SUIT_FileDlg::getFileName(_salomeModule->getApp()->desktop(),
174 QObject::tr("Import MED fields"),
177 if ( filename.isEmpty() ) return;
179 this->addDatasource(QCHARSTAR(filename));
180 _salomeModule->updateObjBrowser(true);
183 #include "DlgImageToMed.hxx"
186 void DatasourceController::OnAddImagesource()
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
197 QString imageFilename = dialog.getImageFilepath();
198 QString medFilename = dialog.getMedFilepath();
199 bool autoLoad = dialog.isAutoLoaded();
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());
207 QMessageBox::critical(_salomeModule->getApp()->desktop(),
208 tr("Operation failed"),
209 tr("The creation of med data from the image file failed"));
214 this->addDatasource(QCHARSTAR(medFilename));
215 _salomeModule->updateObjBrowser(true);
220 void DatasourceController::OnExpandField()
222 // We need a studyEditor updated on the active study
223 _studyEditor->updateActiveStudy();
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);
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);
234 // If fieldseriesId equals -1, then it means that it is not a
235 // fieldseries managed by the MED module, and we stop this
237 if ( fieldseriesId < 0 )
239 // _GBO_ A better correction should be to no display the
240 // contextual menu if the selected object is not conform
242 // Then retrieve the list of fields in this timeseries
243 MEDOP::FieldHandlerList * fieldHandlerList =
244 MEDOPFactoryClient::getDataManager()->getFieldListInFieldseries(fieldseriesId);
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);
256 _salomeModule->updateObjBrowser(true);
259 void DatasourceController::OnVisualize() {
260 STDLOG("OnVisualize: To Be Implemented");
262 // We need a _studyEditor updated on the active study
263 _studyEditor->updateActiveStudy();
265 // Get the selected objects in the study (SObject)
266 SALOME_StudyEditor::SObjectList * listOfSObject = _studyEditor->getSelectedObjects();
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.
279 MEDOP::FieldHandler * fieldHandler = MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
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);
291 void DatasourceController::OnUseInWorkspace() {
292 // We need a studyEditor updated on the active study
293 _studyEditor->updateActiveStudy();
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
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.
308 SALOMEDS::SObject_var soField = listOfSObject->at(0);
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"));
318 int fieldId = _studyEditor->getParameterInt(soField,OBJECT_ID);
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.
323 QMessageBox::warning(_salomeModule->getApp()->desktop(),
324 tr("Operation not allowed"),
325 tr("This element is not a field object"));
329 MEDOP::FieldHandler * fieldHandler =
330 MEDOPFactoryClient::getDataManager()->getFieldHandler(fieldId);
332 QString alias(fieldHandler->fieldname);
334 dialog.setAlias(alias);
335 int choice = dialog.exec();
336 if ( choice == QDialog::Rejected ) {
337 // The user decides to cancel the operation
340 alias = dialog.getAlias();
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);
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);
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
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);
383 STDLOG("The field "<<_studyEditor->getName(soField)<<
384 " is already defined in the workspace");
391 void DatasourceController::OnChangeUnderlyingMesh() {
392 // We need a studyEditor updated on the active study
393 _studyEditor->updateActiveStudy();
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();
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);
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);
423 // Request once more the duplicate to update the meta-data on this
425 duplicate = MEDOPFactoryClient::getDataManager()->getFieldHandler(duplicate->id);
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
438 // Tag the item to prevent double import
439 //_studyEditor->setParameterBool(soField,OBJECT_IS_IN_WORKSPACE,true);