Salome HOME
Merge branch 'abn/port_pv42'
[modules/paravis.git] / src / Plugins / MEDReader / ParaViewPlugin / pqMEDReaderPanel.cxx
1 // Copyright (C) 2010-2014  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 // Author : Anthony Geay
20
21 #include "pqMEDReaderPanel.h"
22 #include "ui_MEDReaderPanel.h"
23 #include "VectBoolWidget.h"
24
25 #include "vtkProcessModule.h"
26 #include "vtkMultiBlockDataSet.h"
27 #include "vtkInformation.h"
28 #include "vtkIntArray.h"
29 #include "vtkSMDoubleVectorProperty.h"
30 #include "vtkSMIntVectorProperty.h"
31 #include "vtkSMStringVectorProperty.h"
32 #include "vtkSMProxy.h"
33 #include "vtkEventQtSlotConnect.h"
34 #include "vtkPVSILInformation.h"
35 #include "vtkGraph.h"
36 #include "vtkMutableDirectedGraph.h"
37 #include "vtkAdjacentVertexIterator.h"
38 #include "vtkSMPropertyHelper.h"
39 #include "vtkStringArray.h"
40 #include "vtkDataSetAttributes.h"
41 #include "vtkMEDReader.h"
42
43 #include "pqTreeWidgetItemObject.h"
44 #include "pqSMAdaptor.h"
45 #include "pqProxy.h"
46 #include "pqPropertyManager.h"
47 #include "pqSILModel.h"
48 #include "pqProxySILModel.h"
49 #include "pqTreeViewSelectionHelper.h"
50 #include "pqTreeWidgetSelectionHelper.h"
51
52 #include <QHeaderView>
53
54 #include <sstream>
55
56 static const char ZE_SEP[]="@@][@@";
57
58 class PixSingle
59 {
60 public:
61   static const PixSingle &GetInstance();
62   QPixmap getPixFromStr(const std::string& st) const;
63   QPixmap getWholeMeshPix() const;
64   PixSingle();
65 private:
66   static const int NB_OF_DISCR=4;
67   static PixSingle *UNIQUE_PIX_SINGLE;
68   QPixmap _pixmaps[NB_OF_DISCR];
69   std::map<std::string,int> _ze_map;
70   QPixmap _whole_mesh;
71 };
72
73 PixSingle *PixSingle::UNIQUE_PIX_SINGLE=0;
74
75 const PixSingle &PixSingle::GetInstance()
76 {
77   if(!UNIQUE_PIX_SINGLE)
78     UNIQUE_PIX_SINGLE=new PixSingle;
79   return *UNIQUE_PIX_SINGLE;
80 }
81
82 PixSingle::PixSingle()
83 {
84   _pixmaps[0]=QPixmap(":/ParaViewResources/Icons/pqCellData16.png");
85   _pixmaps[1]=QPixmap(":/ParaViewResources/Icons/pqPointData16.png");
86   _pixmaps[2]=QPixmap(":/ParaViewResources/Icons/pqQuadratureData16.png");
87   _pixmaps[3]=QPixmap(":/ParaViewResources/Icons/pqElnoData16.png");
88   _ze_map[std::string("P0")]=0;
89   _ze_map[std::string("P1")]=1;
90   _ze_map[std::string("GAUSS")]=2;
91   _ze_map[std::string("GSSNE")]=3;
92   _whole_mesh=QPixmap(":/ParaViewResources/Icons/pqCellDataForWholeMesh16.png");
93 }
94
95 QPixmap PixSingle::getPixFromStr(const std::string& st) const
96 {
97   std::map<std::string,int>::const_iterator it(_ze_map.find(st));
98   if(it!=_ze_map.end())
99     return _pixmaps[(*it).second];
100   else
101     return QPixmap();
102 }
103
104 QPixmap PixSingle::getWholeMeshPix() const
105 {
106   return _whole_mesh;
107 }
108
109 class pqMEDReaderPanel::pqUI: public QObject, public Ui::MEDReaderPanel
110 {
111 public:
112   pqUI(pqMEDReaderPanel *p):QObject(p)
113   {
114     this->VTKConnect = vtkSmartPointer<vtkEventQtSlotConnect>::New();
115   }
116
117   ~pqUI() { }
118   
119   vtkSmartPointer<vtkEventQtSlotConnect> VTKConnect;
120   QMap<QTreeWidgetItem*, QString> TreeItemToPropMap;
121 };
122
123 pqMEDReaderPanel::pqMEDReaderPanel(pqProxy *object_proxy, QWidget *p):Superclass(object_proxy,p),_reload_req(false),_optional_widget(0)
124 {
125   initAll();
126 }
127
128 void pqMEDReaderPanel::initAll()
129 {
130   _all_lev4.clear();
131   this->UI=new pqUI(this);
132   this->UI->setupUi(this);
133   this->UI->Fields->setHeaderHidden(true);
134   this->updateSIL();
135   ////////////////////
136   vtkSMProxy *reader(this->referenceProxy()->getProxy());
137   vtkPVSILInformation *info(vtkPVSILInformation::New());
138   reader->GatherInformation(info);
139   vtkGraph *g(info->GetSIL());
140   if(!g)//something wrong server side...
141     return ;
142   //vtkMutableDirectedGraph *g2(vtkMutableDirectedGraph::SafeDownCast(g));// agy: this line does not work in client/server mode ! but it works in standard mode ! Don't know why. ParaView bug ?
143   vtkMutableDirectedGraph *g2(static_cast<vtkMutableDirectedGraph *>(g));
144   int idNames(0);
145   vtkAbstractArray *verticesNames(g2->GetVertexData()->GetAbstractArray("Names",idNames));
146   vtkStringArray *verticesNames2(vtkStringArray::SafeDownCast(verticesNames));
147   vtkIdType id0;
148   bool found(false);
149   for(int i=0;i<verticesNames2->GetNumberOfValues();i++)
150     {
151       vtkStdString &st(verticesNames2->GetValue(i));
152       if(st=="FieldsStatusTree")
153         {
154           id0=i;
155           found=true;
156         }
157     }
158   if(!found)
159     std::cerr << "There is an internal error ! The tree on server side has not the expected look !" << std::endl;
160   vtkAdjacentVertexIterator *it0(vtkAdjacentVertexIterator::New());
161   g2->GetAdjacentVertices(id0,it0);
162   int kk(0),ll(0);
163   while(it0->HasNext())
164     {
165       vtkIdType idToolTipForTS(it0->Next());
166       QString toolTipName0(QString::fromStdString((const char *)verticesNames2->GetValue(idToolTipForTS)));
167       QString nbTS;
168       QList<QString> dts,its,tts;
169       {
170         vtkAdjacentVertexIterator *itForTS(vtkAdjacentVertexIterator::New());
171         g2->GetAdjacentVertices(idToolTipForTS,itForTS);
172         vtkIdType idForNbTS(itForTS->Next());
173         nbTS=QString::fromStdString((const char *)verticesNames2->GetValue(idForNbTS));
174         itForTS->Delete();
175         int nbTSInt(nbTS.toInt());
176         for(int ii=0;ii<nbTSInt;ii++)
177           {
178             dts.push_back(QString::fromStdString((const char *)verticesNames2->GetValue(idForNbTS+3*ii+1)));
179             its.push_back(QString::fromStdString((const char *)verticesNames2->GetValue(idForNbTS+3*ii+2)));
180             tts.push_back(QString::fromStdString((const char *)verticesNames2->GetValue(idForNbTS+3*ii+3)));
181           }
182       }
183       vtkIdType id1(it0->Next());
184       //
185       vtkSMProperty *SMProperty(this->proxy()->GetProperty("FieldsStatus"));
186       SMProperty->ResetToDefault();//this line is very important !
187       //
188       QString name0(QString::fromStdString((const char *)verticesNames2->GetValue(id1))); QList<QString> strs0; strs0.append(name0);
189       pqTreeWidgetItemObject *item0(new pqTreeWidgetItemObject(this->UI->Fields,strs0));
190       item0->setData(0,Qt::UserRole,name0);
191       item0->setData(0,Qt::ToolTipRole,toolTipName0);
192       //
193       QList<QVariant> modulesAct;
194       for(int i=0;i<nbTS.toInt();i++)
195         modulesAct.push_back(QVariant(true));
196       item0->setProperty("NbOfTS",nbTS);
197       item0->setProperty("DTS",QVariant(dts));
198       item0->setProperty("ITS",QVariant(its));
199       item0->setProperty("TTS",QVariant(tts));
200       item0->setProperty("ChosenTS",QVariant(modulesAct));
201       //
202       vtkAdjacentVertexIterator *it1(vtkAdjacentVertexIterator::New());//mesh
203       g2->GetAdjacentVertices(id1,it1);
204       while(it1->HasNext())
205         {
206           vtkIdType id2(it1->Next());
207           QString name1(QString::fromStdString((const char *)verticesNames2->GetValue(id2))); QList<QString> strs1; strs1.append(name1);
208           QString toolTipName1(name1);
209           pqTreeWidgetItemObject *item1(new pqTreeWidgetItemObject(item0,strs1));
210           item1->setData(0,Qt::UserRole,name1);
211           item1->setData(0,Qt::ToolTipRole,toolTipName1);
212           vtkAdjacentVertexIterator *it2(vtkAdjacentVertexIterator::New());//common support
213           g2->GetAdjacentVertices(id2,it2);
214           while(it2->HasNext())
215             {
216               vtkIdType id3(it2->Next());
217               QString name2(QString::fromStdString((const char *)verticesNames2->GetValue(id3))); QList<QString> strs2; strs2.append(name2);
218               pqTreeWidgetItemObject *item2(new pqTreeWidgetItemObject(item1,strs2));
219               item2->setData(0,Qt::UserRole,name2);
220               item2->setData(0,Qt::CheckStateRole,0);
221               vtkAdjacentVertexIterator *it3(vtkAdjacentVertexIterator::New());//fields !
222               g2->GetAdjacentVertices(id3,it3);
223               vtkIdType id3Arrs(it3->Next());
224               vtkAdjacentVertexIterator *it3Arrs(vtkAdjacentVertexIterator::New());//arrs in fields !
225               g2->GetAdjacentVertices(id3Arrs,it3Arrs);
226               while(it3Arrs->HasNext())
227                 {
228                   vtkIdType id4(it3Arrs->Next());
229                   std::string name3CppFull((const char *)verticesNames2->GetValue(id4));
230                   std::size_t pos(name3CppFull.find(ZE_SEP));
231                   std::string name3Only(name3CppFull.substr(0,pos)); std::string spatialDiscr(name3CppFull.substr(pos+sizeof(ZE_SEP)-1));
232                   QString name3(QString::fromStdString(name3Only)); QList<QString> strs3; strs3.append(name3);
233                   QString toolTipName3(name3+QString(" (")+spatialDiscr.c_str()+QString(")"));
234                   //
235                   vtkAdjacentVertexIterator *it4(vtkAdjacentVertexIterator::New());// is it a special field ? A field mesh ?
236                   g2->GetAdjacentVertices(id4,it4);
237                   bool isSpecial(it4->HasNext());
238                   it4->Delete();
239                   //
240                   pqTreeWidgetItemObject *item3(new pqTreeWidgetItemObject(item2,strs3));
241                   _all_lev4.push_back(item3);
242                   item3->setData(0,Qt::UserRole,name3);
243                   item3->setData(0,Qt::CheckStateRole,0);
244                   if(isSpecial)
245                     {
246                       QFont font; font.setItalic(true); font.setUnderline(true);
247                       item3->setData(0,Qt::FontRole,QVariant(font));
248                       item3->setData(0,Qt::ToolTipRole,QString("Whole \"%1\" mesh").arg(name3));
249                       item3->setData(0,Qt::DecorationRole,PixSingle::GetInstance().getWholeMeshPix());
250                     }
251                   else
252                     {
253                       item3->setData(0,Qt::ToolTipRole,toolTipName3);
254                       item3->setData(0,Qt::DecorationRole,PixSingle::GetInstance().getPixFromStr(spatialDiscr));
255                     }
256                   _leaves.insert(std::pair<pqTreeWidgetItemObject *,int>(item3,ll));
257                   std::ostringstream pdm; pdm << name0.toStdString() << "/" << name1.toStdString() << "/" << name2.toStdString() << "/" << name3CppFull;
258                   (static_cast<vtkSMStringVectorProperty *>(SMProperty))->SetElement(2*ll,pdm.str().c_str());
259                   char tmp2[2]; tmp2[0]=(kk==0?'1':'0'); tmp2[1]='\0';
260                   std::string tmp(tmp2);
261                   (static_cast<vtkSMStringVectorProperty *>(SMProperty))->SetElement(2*ll+1,tmp.c_str());
262                   //SMProperty->ResetToDefault();
263                   item2->setChecked(kk==0);
264                   item3->setChecked(kk==0);
265                   this->propertyManager()->registerLink(item3,"checked",SIGNAL(checkedStateChanged(bool)),this->proxy(),SMProperty,ll);
266                   connect(item2,SIGNAL(checkedStateChanged(bool)),item3,SLOT(setChecked(bool)));
267                   connect(item3,SIGNAL(checkedStateChanged(bool)),this,SLOT(aLev4HasBeenFired()));
268                   ll++;
269                 }
270               vtkIdType id3Gts(it3->Next());
271               vtkAdjacentVertexIterator *it3Gts(vtkAdjacentVertexIterator::New());//geo types in fields !
272               g2->GetAdjacentVertices(id3Gts,it3Gts);
273               QString toolTipName2(name2);
274               while(it3Gts->HasNext())
275                 {
276                   vtkIdType idGt(it3Gts->Next());
277                   std::string gtName((const char *)verticesNames2->GetValue(idGt));
278                   toolTipName2=QString("%1\n- %2").arg(toolTipName2).arg(QString(gtName.c_str()));
279                 }
280               item2->setData(0,Qt::ToolTipRole,toolTipName2);
281               it3Gts->Delete();
282               it3->Delete();
283               it3Arrs->Delete();
284               kk++;
285             }
286           it2->Delete();
287         }
288       it1->Delete();
289     }
290   it0->Delete();
291   this->UI->Fields->header()->setStretchLastSection(true);
292   this->UI->Fields->expandAll();
293   info->Delete();
294   this->UI->stdMode->setChecked(true);
295   this->UI->VTKConnect->Connect(this->proxy(),vtkCommand::UpdateInformationEvent, this, SLOT(updateSIL()));
296   ///
297   this->UI->Reload->setProperty("NbOfReloadDynProp",QVariant(1));
298   vtkSMProperty *SMProperty(this->proxy()->GetProperty("ReloadReq"));
299   connect(this->UI->Reload,SIGNAL(pressed()),this,SLOT(reloadFired()));
300   this->propertyManager()->registerLink(this->UI->Reload,"NbOfReloadDynProp",SIGNAL(pressed()),this->proxy(),SMProperty);
301   ///
302   vtkSMProperty *SMProperty0(this->proxy()->GetProperty("GenerateVectors"));
303   this->propertyManager()->registerLink(this->UI->GenerateVects,"checked",SIGNAL(stateChanged(int)),this->proxy(),SMProperty0);
304   ///
305   vtkSMProperty *SMProperty2(this->proxy()->GetProperty("TimeOrModal"));
306   SMProperty2->ResetToDefault();//this line is very important !
307   this->propertyManager()->registerLink(this->UI->modeMode,"checked",SIGNAL(toggled(bool)),this->proxy(),SMProperty2);
308   ///
309   delete _optional_widget;
310   _optional_widget=new VectBoolWidget(this->UI->timeStepsInspector,getMaxNumberOfTS());
311   _optional_widget->hide();
312   this->UI->timeStepsInspector->setMinimumSize(QSize(0,0));
313   connect(this->UI->modeMode,SIGNAL(toggled(bool)),this,SLOT(vectOfBoolWidgetRequested(bool)));
314   vtkSMProperty *SMProperty3(this->proxy()->GetProperty("TimesFlagsStatus"));
315   SMProperty3->ResetToDefault();
316   const QVector<VectBoolItem *>& items(_optional_widget->getItems());
317   int itt(0);
318   foreach(VectBoolItem *item,items)
319     {
320       this->propertyManager()->registerLink(item,"activated",SIGNAL(changed()),this->proxy(),SMProperty3,itt++);
321     }
322 }
323
324 pqMEDReaderPanel::~pqMEDReaderPanel()
325 {
326   delete _optional_widget;
327 }
328
329 void pqMEDReaderPanel::linkServerManagerProperties()
330 {
331   this->Superclass::linkServerManagerProperties();
332 }
333
334 void pqMEDReaderPanel::updateSIL()
335 {
336   if(_reload_req)
337     {
338       _reload_req=false;
339       this->UI->geometryGroupBox->hide();
340       delete this->UI;
341       foreach(QObject *child,children())
342         {
343           QLayout *layout(qobject_cast<QLayout *>(child));
344           if(layout)
345             delete layout;
346         }
347       initAll();
348     }
349 }
350
351 void pqMEDReaderPanel::aLev4HasBeenFired()
352 {
353   pqTreeWidgetItemObject *zeItem(qobject_cast<pqTreeWidgetItemObject *>(sender()));
354   if(!zeItem)
355     return;
356   pqTreeWidgetItemObject *father(dynamic_cast<pqTreeWidgetItemObject *>(zeItem->QTreeWidgetItem::parent()));
357   QTreeWidgetItem *godFather(father->QTreeWidgetItem::parent()->parent());
358   if(!father)
359     return ;
360   if(zeItem->isChecked())
361     {
362       bool isActivatedTSChanged(false);
363       // This part garantees that all leaves having not the same father than zeItem are desactivated
364       foreach(pqTreeWidgetItemObject* elt,this->_all_lev4)
365         {
366           QTreeWidgetItem *testFath(elt->QTreeWidgetItem::parent());
367           if(testFath!=father)
368             if(elt->isChecked())
369               {
370                 elt->setChecked(false);
371                 if(godFather!=testFath->parent()->parent())
372                   isActivatedTSChanged=true;
373               }
374         }
375       //If all leaves are checked the father is check too
376       bool allItemsAreChked(true);
377       for(int i=0;i<father->childCount() && allItemsAreChked;i++)
378         {
379           pqTreeWidgetItemObject *elt(dynamic_cast<pqTreeWidgetItemObject *>(father->child(i)));
380           if(elt && !elt->isChecked())
381             allItemsAreChked=false;
382         }
383       if(allItemsAreChked && !father->isChecked())
384         father->setChecked(true);
385       // the user by clicking to a new entry has changed of TimeStepSeries -> notify it to thee time step selector widget
386       if(isActivatedTSChanged)
387         {
388           QStringList its,dts,tts;
389           getCurrentTS(its,dts,tts);
390           _optional_widget->setItems(its,dts,tts);
391         }
392     }
393   else
394     {
395       // if all are unchecked - check it again
396       bool allItemsAreUnChked(true);
397       foreach(pqTreeWidgetItemObject* elt,this->_all_lev4)
398         {
399           if(elt && elt->isChecked())
400             allItemsAreUnChked=false;
401         }
402       if(allItemsAreUnChked)
403         zeItem->setChecked(true);// OK zeItem was required to be unchecked but as it is the last one. Recheck it !
404       else
405         {// if all items are uncheked inside a same parent - uncheck the parent
406           allItemsAreUnChked=true;
407           for(int i=0;i<father->childCount() && allItemsAreUnChked;i++)
408             {
409               pqTreeWidgetItemObject *elt(dynamic_cast<pqTreeWidgetItemObject *>(father->child(i)));
410               if(elt && elt->isChecked())
411             allItemsAreUnChked=false;
412             }
413           if(allItemsAreUnChked && father->isChecked())
414             father->setChecked(false);
415         } 
416     }
417 }
418
419 void pqMEDReaderPanel::reloadFired()
420 {
421   static int iii(1);
422   QVariant v(iii++);
423   this->UI->Reload->setProperty("NbOfReloadDynProp",v);
424   _reload_req=true;
425   for(std::set<std::pair<pqTreeWidgetItemObject *,int> >::const_iterator it=_leaves.begin();it!=_leaves.end();it++)
426     ((*it).first)->disconnect(SIGNAL(checkedStateChanged(bool)));
427   //
428   vtkSMProperty *SMProperty(this->proxy()->GetProperty("FieldsStatus"));
429   for(std::set<std::pair<pqTreeWidgetItemObject *,int> >::const_iterator it=_leaves.begin();it!=_leaves.end();it++)
430     this->propertyManager()->unregisterLink((*it).first,"checked",SIGNAL(checkedStateChanged(bool)),this->proxy(),SMProperty,(*it).second);
431   this->propertyManager()->propertyChanged();
432   vtkSMProperty *SMProperty3(this->proxy()->GetProperty("TimeOrModal"));
433   this->propertyManager()->unregisterLink(this->UI->modeMode,"checked",SIGNAL(toggled(bool)),this->proxy(),SMProperty3);
434 }
435
436 void pqMEDReaderPanel::vectOfBoolWidgetRequested(bool isMode)
437 {
438   if(isMode)
439     {
440       this->UI->timeStepsInspector->setMinimumSize(QSize(200,250));
441       _optional_widget->show();
442       QStringList its,dts,tts;
443       getCurrentTS(its,dts,tts);
444       _optional_widget->setItems(its,dts,tts);
445     }
446   else
447     {
448       _optional_widget->hide();
449       this->UI->timeStepsInspector->setMinimumSize(QSize(0,0));
450     }
451 }
452
453 void pqMEDReaderPanel::getCurrentTS(QStringList& its, QStringList& dts, QStringList& tts) const
454 {
455   
456   for(std::vector<pqTreeWidgetItemObject *>::const_iterator it=_all_lev4.begin();it!=_all_lev4.end();it++)
457     {
458       if((*it)->property("checked").toInt())
459         {
460           QTreeWidgetItem *obj((*it)->QTreeWidgetItem::parent()->QTreeWidgetItem::parent()->QTreeWidgetItem::parent());
461           pqTreeWidgetItemObject *objC(dynamic_cast<pqTreeWidgetItemObject *>(obj));
462           its=objC->property("ITS").toStringList();
463           dts=objC->property("DTS").toStringList();
464           tts=objC->property("TTS").toStringList();
465           return;
466         }
467     }
468   std::cerr << "pqMEDReaderPanel::getCurrentTS : internal error ! Something is going wrong !" << std::endl;
469 }
470
471 int pqMEDReaderPanel::getMaxNumberOfTS() const
472 {
473   int ret(0);
474   for(std::vector<pqTreeWidgetItemObject *>::const_iterator it=_all_lev4.begin();it!=_all_lev4.end();it++)
475     {
476       QTreeWidgetItem *obj((*it)->QTreeWidgetItem::parent()->QTreeWidgetItem::parent()->QTreeWidgetItem::parent());
477       pqTreeWidgetItemObject *objC(dynamic_cast<pqTreeWidgetItemObject *>(obj));
478       ret=std::max(ret,objC->property("NbOfTS").toInt());
479     }
480   return ret;
481 }