1 // Copyright (C) 2007-2021 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, or (at your option) any later version.
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 <MEDCalcConstants.hxx>
25 #include <SalomeApp_Application.h>
26 #include <SalomeApp_Study.h>
27 #include <SalomeApp_DataObject.h>
29 #include <SALOME_ListIO.hxx>
30 #include <LightApp_SelectionMgr.h>
32 #include <SALOME_LifeCycleCORBA.hxx>
33 #include <SALOMEDS_SObject.hxx>
34 #include <SALOMEDS_Study.hxx>
36 #include "MEDFactoryClient.hxx"
37 #include "MEDModule.hxx"
38 #include "QtHelper.hxx"
40 #include CORBA_CLIENT_HEADER(SALOMEDS)
41 #include CORBA_CLIENT_HEADER(SALOMEDS_Attributes)
42 #include <SUIT_FileDlg.h>
43 #include <SUIT_Desktop.h>
45 #include <QStringList>
47 #include <QMessageBox>
48 #include <QFileDialog>
50 #include "DlgAlias.hxx"
53 // ==============================================================
54 // Datasource controller
55 // ==============================================================
57 DatasourceController::DatasourceController(MEDModule* salomeModule)
59 STDLOG("Creating a DatasourceController");
60 _salomeModule = salomeModule;
61 _studyEditor = _salomeModule->getStudyEditor();
64 DatasourceController::~DatasourceController() {
65 STDLOG("Deleting the DatasourceController");
68 void DatasourceController::createActions() {
69 int toolbarId = _salomeModule->createTool("Datasource", "DatasourceToolbar");
72 // Main actions (toolbar and menubar)
74 QString label = tr("LAB_ADD_DATA_SOURCE");
75 QString tooltip = tr("TIP_ADD_DATA_SOURCE");
76 QString icon = tr("ICO_DATASOURCE_ADD");
78 actionId = _salomeModule->createStandardAction(label, this, SLOT(OnAddDatasource()),
79 icon, tooltip, FIELDSOp::OpAddDataSource);
80 _salomeModule->createTool(actionId, toolbarId);
82 // This action has to be placed in the general file menu with the label "Import MED file"
83 int menuId = _salomeModule->createMenu( tr( "MEN_FILE" ), -1, 1 );
84 _salomeModule->action(actionId)->setIconVisibleInMenu(true);
85 _salomeModule->createMenu(actionId, menuId, 10);
87 label = tr("LAB_ADD_IMAGE_SOURCE");
88 tooltip = tr("TIP_ADD_IMAGE_SOURCE");
89 icon = tr("ICO_IMAGE_ADD");
90 actionId = _salomeModule->createStandardAction(label,this, SLOT(OnAddImagesource()),icon,tooltip);
91 _salomeModule->createTool(actionId, toolbarId);
92 _salomeModule->action(actionId)->setIconVisibleInMenu(true);
93 _salomeModule->createMenu(actionId, menuId, 20);
96 // Actions for popup menu only
98 // Expand field timeseries
99 label = tr("LAB_EXPAND_FIELD");
100 icon = tr("ICO_DATASOURCE_EXPAND_FIELD");
101 actionId = _salomeModule->createStandardAction(label,this,SLOT(OnExpandField()),icon);
102 _salomeModule->addActionInPopupMenu(actionId);
105 label = tr("LAB_USE_IN_WORKSPACE");
106 icon = tr("ICO_DATASOURCE_USE");
107 actionId = _salomeModule->createStandardAction(label,this,SLOT(OnUseInWorkspace()),icon);
108 _salomeModule->addActionInPopupMenu(actionId);
113 * This function adds the specified MED file as a datasource in the
114 * dataspace. Technically speaking, the engine loads the
115 * meta-information concerning med data from the file, gives this
116 * information to the GUI, and the GUI creates a tree view of these
117 * data in the study object browser.
119 // This function emits a signal that will be caught by workspace to delegate command (datasource creation) to python console.
121 DatasourceController::addDatasource(const char* filename)
123 DatasourceEvent* event = new DatasourceEvent();
124 event->eventtype = DatasourceEvent::EVENT_ADD_DATASOURCE;
125 event->objectalias = filename;
126 emit datasourceSignal(event); // --> WorkspaceController::processDatasourceEvent()
127 //#ifdef MED_WITH_QTTESTING
128 // _dirtyAddDataSource = true;
129 // while(_dirtyAddDataSource)
130 // QApplication::processEvents();
134 // After above data source creation, python console emits a signal, forwarded by workspace, to update the GUI
136 DatasourceController::updateTreeViewWithNewDatasource(const MEDCALC::DatasourceHandler* datasourceHandler)
138 if (!datasourceHandler) {
142 _salomeModule->engine()->addDatasourceToStudy(*datasourceHandler);
144 // update Object browser
145 _salomeModule->getApp()->updateObjectBrowser(true);
147 //#ifdef MED_WITH_QTTESTING
148 // _dirtyAddDataSource = false;
152 void DatasourceController::OnAddDatasource()
154 // Dialog to get the filename where the input data are read from
156 filter.append(tr("FILE_FILTER_MED"));
158 QString anInitialPath = "";
159 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
160 anInitialPath = QDir::currentPath();
162 // QStringList filenames = SUIT_FileDlg::getOpenFileNames( _salomeModule->getApp()->desktop(),
165 // tr("IMPORT_MED_FIELDS") );
166 // [ABN] the below to be compatible with QtTesting:
167 QStringList filenames = QFileDialog::getOpenFileNames( _salomeModule->getApp()->desktop(),
168 tr("IMPORT_MED_FIELDS"),
170 tr("FILE_FILTER_MED") );
172 if ( filenames.count() <= 0 ) return;
173 for ( QStringList::ConstIterator itFile = filenames.begin();
174 itFile != filenames.end(); ++itFile ) {
175 QString filename = *itFile;
176 this->addDatasource(QCHARSTAR(filename));
177 _salomeModule->updateObjBrowser(true);
181 #include "DlgImageToMed.hxx"
182 void DatasourceController::OnAddImagesource()
185 DlgImageToMed dialog;
186 dialog.setAutoLoaded(true);
187 int choice = dialog.exec();
188 if ( choice == QDialog::Rejected ) {
189 // The user decides to cancel the operation
193 QString imageFilename = dialog.getImageFilepath();
195 QString medFilename = dialog.getMedFilepath();
196 bool autoLoad = dialog.isAutoLoaded();
198 std::string ROOT_DIR(getenv("FIELDS_ROOT_DIR"));
199 std::string command(ROOT_DIR+"/bin/salome/fields/image2med.py");
200 command += " -i "+QS2S(imageFilename);
201 command += " -m "+QS2S(medFilename);
202 int error = system(command.c_str());
204 QMessageBox::critical(_salomeModule->getApp()->desktop(),
205 tr("Operation failed"),
206 tr("The creation of med data from the image file failed"));
211 this->addDatasource(QCHARSTAR(medFilename));
212 _salomeModule->updateObjBrowser(true);
216 DatasourceEvent* event = new DatasourceEvent();
217 event->eventtype = DatasourceEvent::EVENT_ADD_IMAGE_AS_DATASOURCE;
218 event->objectalias = imageFilename;
219 emit datasourceSignal(event); // --> WorkspaceController::processDatasourceEvent()
222 void DatasourceController::OnExpandField()
224 SALOMEDS::Study_var aStudy = KERNEL::getStudyServant();
225 // check if reference to study is valid
226 if (CORBA::is_nil(aStudy))
229 // check if reference to use case builder is valid
230 SALOMEDS::UseCaseBuilder_var useCaseBuilder = aStudy->GetUseCaseBuilder();
231 if (CORBA::is_nil(useCaseBuilder))
235 // Get the selected objects in the study (SObject)
236 SALOME_StudyEditor::SObjectList* listOfSObject = _studyEditor->getSelectedObjects();
237 for (int i=0; i<(int)listOfSObject->size(); i++) {
238 SALOMEDS::SObject_var soFieldseries = listOfSObject->at(i);
239 std::string name(_studyEditor->getName(soFieldseries));
240 if (soFieldseries->_is_nil() || name == "MEDCalc")
243 // First retrieve the fieldseries id associated to this study object
244 SALOMEDS::GenericAttribute_var anAttr;
245 SALOMEDS::AttributeParameter_var aParam;
246 if ( soFieldseries->FindAttribute(anAttr,"AttributeParameter") ) {
247 aParam = SALOMEDS::AttributeParameter::_narrow(anAttr);
248 if (! aParam->IsSet(FIELD_SERIES_ID, PT_INTEGER))
251 long fieldseriesId = aParam->GetInt(FIELD_SERIES_ID);
252 STDLOG("Expand the field timeseries "<<fieldseriesId);
254 // If fieldseriesId equals -1, then it means that it is not a
255 // fieldseries managed by the MED module, and we stop this
257 if ( fieldseriesId < 0 )
259 // _GBO_ A better correction should be to no display the
260 // contextual menu if the selected object is not conform
262 // Then retrieve the list of fields in this timeseries
263 MEDCALC::FieldHandlerList* fieldHandlerList =
264 MEDFactoryClient::getDataManager()->getFieldListInFieldseries(fieldseriesId);
266 // Finally, create an entry for each of the field
267 for(CORBA::ULong iField=0; iField<fieldHandlerList->length(); iField++) {
268 MEDCALC::FieldHandler fieldHandler = (*fieldHandlerList)[iField];
269 SALOMEDS::SObject_var soField = _studyEditor->newObject(soFieldseries);
270 std::string label("it="); label += ToString(fieldHandler.iteration);
271 _studyEditor->setName(soField,label.c_str());
272 _studyEditor->setParameterInt(soField, FIELD_ID, fieldHandler.id);
273 _studyEditor->setParameterBool(soField,IS_IN_WORKSPACE,false);
274 useCaseBuilder->AppendTo(soField->GetFather(), soField);
277 _salomeModule->updateObjBrowser(true);
280 void DatasourceController::OnUseInWorkspace() {
281 // Get the selected objects in the study (SObject)
282 SALOME_StudyEditor::SObjectList* listOfSObject = _studyEditor->getSelectedObjects();
283 if ( listOfSObject->size() == 1 ) {
284 // In this case we ask the name of the variable for the python
288 // _GBO_ Note that it works only for a single field but the
289 // XmedDataObject will be improved to deal with mesh, timeseries
290 // and single field in a futur version. We suppose here that a
291 // single field has been selected.
294 SALOMEDS::SObject_var soField = listOfSObject->at(0);
295 std::string name(_studyEditor->getName(soField));
296 if (soField->_is_nil() || name == "MEDCalc")
298 SALOMEDS::GenericAttribute_var anAttr;
299 SALOMEDS::AttributeParameter_var aParam;
300 if ( soField->FindAttribute(anAttr,"AttributeParameter") ) {
301 aParam = SALOMEDS::AttributeParameter::_narrow(anAttr);
302 if (! aParam->IsSet(IS_IN_WORKSPACE, PT_BOOLEAN))
305 bool isInWorkspace = aParam->GetBool(IS_IN_WORKSPACE);
306 if ( isInWorkspace ) {
307 QMessageBox::warning(_salomeModule->getApp()->desktop(),
308 tr("Operation not allowed"),
309 tr("This field is already defined in the workspace"));
313 if (! aParam->IsSet(FIELD_ID, PT_INTEGER))
315 int fieldId = aParam->GetInt(FIELD_ID);
317 // If fieldId equals -1, then it means that it is not a field
318 // managed by the MED module, and we stop this function process.
320 QMessageBox::warning(_salomeModule->getApp()->desktop(),
321 tr("Operation not allowed"),
322 tr("This element is not a field object"));
326 MEDCALC::FieldHandler* fieldHandler =
327 MEDFactoryClient::getDataManager()->getFieldHandler(fieldId);
329 if (! fieldHandler) {
330 QMessageBox::warning(_salomeModule->getApp()->desktop(),
331 tr("Operation not allowed"),
332 tr("No field is defined"));
336 QString alias(fieldHandler->fieldname);
338 dialog.setAlias(alias);
339 int choice = dialog.exec();
340 if ( choice == QDialog::Rejected ) {
341 // The user decides to cancel the operation
344 alias = dialog.getAlias();
346 DatasourceEvent* event = new DatasourceEvent();
347 event->eventtype = DatasourceEvent::EVENT_USE_OBJECT;
348 XmedDataObject* dataObject = new XmedDataObject();
349 dataObject->setFieldHandler(*fieldHandler);
350 event->objectdata = dataObject;
351 event->objectalias = alias;
352 emit datasourceSignal(event); // --> WorkspaceController::processDatasourceEvent()
353 // Tag the item to prevent double import
354 // _studyEditor->setParameterBool(soField,IS_IN_WORKSPACE,true);
355 // Tag the field as persistent on the server. It means that a
356 // saving of the workspace will save at least this field (maybe it
357 // should be an option?)
358 MEDFactoryClient::getDataManager()->markAsPersistent(fieldId, true);
361 // In this case, we don't ask the user to specify an alias for
362 // each item, we just import the whole set of items.
363 for (int i=0; i<(int)listOfSObject->size(); i++) {
364 SALOMEDS::SObject_var soField = listOfSObject->at(i);
365 if (soField->_is_nil())
367 SALOMEDS::GenericAttribute_var anAttr;
368 SALOMEDS::AttributeParameter_var aParam;
369 if ( soField->FindAttribute(anAttr,"AttributeParameter") ) {
370 aParam = SALOMEDS::AttributeParameter::_narrow(anAttr);
371 if (! aParam->IsSet(IS_IN_WORKSPACE, PT_BOOLEAN))
374 bool isInWorkspace = aParam->GetBool(IS_IN_WORKSPACE);
375 if ( !isInWorkspace ) {
376 if (! aParam->IsSet(FIELD_ID, PT_INTEGER))
378 int fieldId = aParam->GetInt(FIELD_ID);
379 MEDCALC::FieldHandler* fieldHandler =
380 MEDFactoryClient::getDataManager()->getFieldHandler(fieldId);
381 DatasourceEvent* event = new DatasourceEvent();
382 event->eventtype = DatasourceEvent::EVENT_IMPORT_OBJECT;
383 XmedDataObject* dataObject = new XmedDataObject();
384 dataObject->setFieldHandler(*fieldHandler);
385 event->objectdata = dataObject;
386 emit datasourceSignal(event); // --> WorkspaceController::processDatasourceEvent()
387 // Note that this signal is processed by the WorkspaceController
389 // Tag the item to prevent double import
390 // _studyEditor->setParameterBool(soField,IS_IN_WORKSPACE,true);
391 // Tag the field as persistent on the server. It means that a
392 // saving of the workspace will save at least this field (maybe it
393 // should be an option?)
394 MEDFactoryClient::getDataManager()->markAsPersistent(fieldId, true);
397 STDLOG("The field "<<_studyEditor->getName(soField)<<
398 " is already defined in the workspace");
405 DatasourceController::processWorkspaceEvent(const MEDCALC::MedEvent* event)
407 if ( event->type == MEDCALC::EVENT_ADD_DATASOURCE ) {
408 MEDCALC::DatasourceHandler* datasourceHandler = MEDFactoryClient::getDataManager()->getDatasourceHandler(event->filename);
409 this->updateTreeViewWithNewDatasource(datasourceHandler);