Salome HOME
Remove QT4 compatibility.
[modules/paravis.git] / src / Plugins / ArrayRenamer / pqArraysEditorPropertyWidget.cxx
1 // Copyright (C) 2014-2019  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 : Roman NIKOLAEV
20
21 // Local includes
22 #include "pqArraysEditorPropertyWidget.h"
23 #include "pqEditComponents.h"
24
25 //ParaView includes
26 #include <vtkPVArrayInformation.h>
27 #include <vtkPVDataInformation.h>
28 #include <vtkPVDataSetAttributesInformation.h>
29 #include <vtkSMPropertyGroup.h>
30 #include <vtkSMSourceProxy.h>
31 #include <vtkSMUncheckedPropertyHelper.h>
32
33 // Qt Includes
34 #include <QAbstractTableModel>
35 #include <QApplication>
36 #include <QCheckBox>
37 #include <QDialog>
38 #include <QGroupBox>
39 #include <QHBoxLayout>
40 #include <QHeaderView>
41 #include <QPushButton>
42 #include <QPushButton>
43 #include <QSpacerItem>
44 #include <QTableView>
45 #include <QVBoxLayout>
46
47 // STD includes
48 #include <limits>
49
50
51 /// Table model for the components table
52 class pqComponentsModel : public QAbstractTableModel {
53   typedef QAbstractTableModel Superclass;
54 public:
55   typedef QPair<QString, QString> SingleComponentInfoType;
56   typedef QVector<SingleComponentInfoType> ComponentsInfoType;
57 private:
58   ComponentsInfoType myComponentsInfoVector;
59   bool               myRenameSimilar;
60
61 public:
62   enum ColumnRoles {
63   COMPONENT_NAME = 0,
64   NEW_COMPONENT_NAME = 1,
65   };
66
67   //------------------------------------------------------------------
68   pqComponentsModel( QObject* parentObject=0 ):
69     Superclass(parentObject),
70     myRenameSimilar(false) {}
71   
72   //------------------------------------------------------------------
73   virtual ~pqComponentsModel() {}
74
75   void setRenameSimilar( bool IsRenameSimilar ) {
76     myRenameSimilar = IsRenameSimilar;
77     if ( myRenameSimilar ) {
78       QHash<QString,QString> anUnique;
79       foreach( SingleComponentInfoType item, myComponentsInfoVector ) { 
80         if( !anUnique.contains( item.first ) ) {
81           anUnique.insert( item.first,item.second );
82         }
83       }
84       bool modified = false;
85       int min = std::numeric_limits<int>::max(); 
86       int max = std::numeric_limits<int>::min();
87       for( int i = 0; i < myComponentsInfoVector.size(); i++ ) { 
88         if( anUnique.contains( myComponentsInfoVector[i].first) && 
89             anUnique.value( myComponentsInfoVector[i].first ) != myComponentsInfoVector[i].second ) {
90           myComponentsInfoVector[i].second = anUnique.value( myComponentsInfoVector[i].first );
91           min = qMin( min, i );
92           max = qMax( max, i );
93           modified = true;
94         }
95       }
96       if( modified ) {
97         emit dataChanged( index( 1, min ) , index( 1, max ) );
98       }
99     }
100   }
101
102   //------------------------------------------------------------------
103   virtual Qt::ItemFlags flags( const QModelIndex &idx ) const {
104     Qt::ItemFlags value = Superclass::flags( idx );
105     if ( idx.isValid() ) {
106       switch ( idx.column() ) {
107         case NEW_COMPONENT_NAME: return value | Qt::ItemIsEditable;
108       default:
109         break;
110       }
111     }
112     return value;
113   }
114
115   //------------------------------------------------------------------
116   virtual int rowCount( const QModelIndex& idx=QModelIndex() ) const {
117     return idx.isValid() ? 0 : myComponentsInfoVector.size();
118   }
119
120   //------------------------------------------------------------------
121   virtual int columnCount( const QModelIndex& idx=QModelIndex() ) const {
122     Q_UNUSED( idx );
123     return 2;
124   }
125
126   //------------------------------------------------------------------
127   virtual QVariant data(const QModelIndex& idx, int role=Qt::DisplayRole) const {
128     if ( idx.column() == COMPONENT_NAME ) {
129       switch ( role ) {
130         case Qt::DisplayRole:
131         case Qt::ToolTipRole:
132         case Qt::StatusTipRole:
133           return myComponentsInfoVector[idx.row()].first;
134         default:
135           break;
136         }
137       }
138     else if (idx.column() == NEW_COMPONENT_NAME) {
139       switch (role) {
140         case Qt::DisplayRole:
141         case Qt::EditRole:
142         case Qt::ToolTipRole:
143         case Qt::StatusTipRole:
144           return myComponentsInfoVector[idx.row()].second;
145         case Qt::ForegroundRole: {
146           if ( myComponentsInfoVector[idx.row()].second == myComponentsInfoVector[idx.row()].first )
147             return QApplication::palette().color(QPalette::Disabled, QPalette::Text);
148         }
149         case Qt::FontRole: {
150           if ( myComponentsInfoVector[idx.row()].second == myComponentsInfoVector[idx.row()].first ) {
151             QFont f = QApplication::font();
152             f.setItalic(true);
153             return f;
154           }
155         }
156         default:
157           break;
158       }
159     }
160     return QVariant();
161   }
162
163   //------------------------------------------------------------------
164   virtual bool setData(const QModelIndex &idx, const QVariant &value, int role=Qt::EditRole) {
165     if (idx.column() == NEW_COMPONENT_NAME && role == Qt::EditRole ) {
166       QString new_name = value.toString();
167       Q_ASSERT(idx.row() < myComponentsInfoVector.size());
168       myComponentsInfoVector[idx.row()].second = new_name;
169       int min = idx.row();
170       int max = idx.row();
171       if( myRenameSimilar ) {
172         QString ref_name = myComponentsInfoVector[idx.row()].first;
173         for( int i = 0; i < myComponentsInfoVector.size(); i++ ) {
174           if(myComponentsInfoVector[i].first == ref_name) {
175               min = qMin( min, i );
176               max = qMax( max, i );
177               myComponentsInfoVector[i].second = new_name;
178           }
179         }         
180       }
181       emit dataChanged( index( 1, min ) , index( 1, max ) );
182       return true;
183     }
184     return Superclass::setData(idx,value,role);
185   }
186
187   //------------------------------------------------------------------
188   QVariant headerData( int section, Qt::Orientation orientation, int role ) const {
189     if ( orientation == Qt::Horizontal ) {
190       if ( role == Qt::DisplayRole || role == Qt::ToolTipRole ) {
191         switch (section) {
192           case COMPONENT_NAME:
193             return role == Qt::DisplayRole? "Origin Name": "Origin Names of components";
194           case NEW_COMPONENT_NAME:
195             return role == Qt::DisplayRole? "New Name": "New Names of components";
196           default:
197             break;
198         }
199       }
200     }
201     return this->Superclass::headerData(section, orientation, role);
202   }
203
204   //------------------------------------------------------------------
205   void setComponentsInfo( const ComponentsInfoType& data ) {
206     emit this->beginResetModel();
207     myComponentsInfoVector = data;
208     emit this->endResetModel();
209   }
210
211   //------------------------------------------------------------------
212   const ComponentsInfoType& componentsInfo() const {
213     return myComponentsInfoVector;
214   }
215 private:
216   Q_DISABLE_COPY(pqComponentsModel);
217 };
218
219 /// Table model for the array's table
220 class pqArraysModel : public QAbstractTableModel
221 {
222   typedef QAbstractTableModel Superclass;
223 public:
224   struct ArrayInfo {
225     bool copyArray;  // How to porocess arrays: remane origin array or keep origin and make copy with the new name
226     QString newName;
227     pqComponentsModel::ComponentsInfoType myComponentsInfo;
228   
229   public:
230
231     //------------------------------------------------------------------
232     const int nbComps() const {
233       return myComponentsInfo.size();
234     }
235
236     //------------------------------------------------------------------
237     const bool isCompomentsModified() const {
238       foreach(pqComponentsModel::SingleComponentInfoType item , myComponentsInfo) {
239         if(item.first != item.second)
240           return true;
241       }
242       return false;
243     }
244   };
245
246 public:  
247   typedef QPair<QString, ArrayInfo> ArraysInfoItemType;
248   typedef QVector<ArraysInfoItemType> ArraysInfoType;  
249
250 private:
251   ArraysInfoType myArraysInfo;
252
253 public:
254
255   //------------------------------------------------------------------
256   enum ColumnRoles {
257     PROCESSING = 0,
258     NAME = 1,
259     NEW_NAME = 2,
260     COMPONENTS = 3,
261   };
262
263   //------------------------------------------------------------------
264   pqArraysModel( QObject* parentObject=0 ) :
265     Superclass( parentObject ) { }
266
267   //------------------------------------------------------------------
268   virtual ~pqArraysModel() { }
269
270   //------------------------------------------------------------------
271   virtual Qt::ItemFlags flags( const QModelIndex &idx ) const {
272     Qt::ItemFlags value = Superclass::flags( idx );
273     if (idx.isValid()) {
274       switch ( idx.column() ) {
275         case PROCESSING:
276           return value | Qt::ItemIsUserCheckable;
277         case NEW_NAME:
278           return value | Qt::ItemIsEditable;
279         default:
280          break;
281       }
282     }
283     return value;
284   }
285
286   //------------------------------------------------------------------
287   virtual int rowCount( const QModelIndex& idx=QModelIndex() ) const {
288     return idx.isValid() ? 0 : myArraysInfo.size();
289   }
290
291   //------------------------------------------------------------------
292   virtual int columnCount( const QModelIndex& idx=QModelIndex() ) const {
293     Q_UNUSED(idx);
294     return 4;
295   }
296
297   //------------------------------------------------------------------
298   virtual QVariant data(const QModelIndex& idx, int role=Qt::DisplayRole) const {
299     Q_ASSERT( idx.row() < myArraysInfo.size() );
300     if ( idx.column() == PROCESSING ) {
301       switch (role) {
302         case Qt::CheckStateRole:
303           return myArraysInfo[idx.row()].second.copyArray ? Qt::Checked : Qt::Unchecked;
304         default:
305           break;
306       }
307     } else if ( idx.column() == NAME ) {
308       switch ( role ) {
309         case Qt::DisplayRole:
310         case Qt::ToolTipRole:
311         case Qt::StatusTipRole:
312           return myArraysInfo[idx.row()].first;
313         default:
314           break;
315       }
316     } else if ( idx.column() == NEW_NAME ) {
317       switch (role) {
318         case Qt::DisplayRole:
319         case Qt::EditRole:
320         case Qt::ToolTipRole:
321         case Qt::StatusTipRole:
322          return myArraysInfo[idx.row()].second.newName;
323         case Qt::ForegroundRole: {
324           if ( myArraysInfo[idx.row()].second.newName == myArraysInfo[idx.row()].first )
325             return QApplication::palette().color(QPalette::Disabled, QPalette::Text);
326         }
327         case Qt::FontRole: {
328           if ( myArraysInfo[idx.row()].second.newName == myArraysInfo[idx.row()].first ) {
329             QFont f = QApplication::font();
330             f.setItalic(true);
331             return f;
332           }
333         }
334         default:
335           break;
336       }
337     }
338     return QVariant();
339   }
340
341   //------------------------------------------------------------------
342   virtual bool setData(const QModelIndex &idx, const QVariant &value, int role=Qt::EditRole) {
343
344     if (idx.column() == PROCESSING && role == Qt::CheckStateRole) {
345       bool checkState = (value.toInt() == Qt::Checked);
346       Q_ASSERT(idx.row() < myArraysInfo.size());
347       myArraysInfo[idx.row()].second.copyArray = (bool)checkState;
348       emit dataChanged(idx, idx);
349       return true;
350     }
351
352     if (idx.column() == NEW_NAME && role == Qt::EditRole) {
353       QString new_name = value.toString();
354       if ( !new_name.isEmpty() ) {
355         Q_ASSERT(idx.row() < myArraysInfo.size());
356         myArraysInfo[idx.row()].second.newName = new_name;
357         emit dataChanged(idx, idx);
358         return true;
359       }
360     }
361     return Superclass::setData(idx,value,role);
362   }
363
364   //------------------------------------------------------------------
365   QVariant headerData(int section, Qt::Orientation orientation, int role) const {
366     if ( orientation == Qt::Horizontal ) {
367       if ( role == Qt::DisplayRole || role == Qt::ToolTipRole ) {
368         switch ( section ) {
369           case PROCESSING:
370             return role == Qt::DisplayRole? "": "Toggle to copy arrays";
371           case NAME:
372             return role == Qt::DisplayRole? "Origin Name": "Origin Names of arrays";
373           case NEW_NAME:
374             return role == Qt::DisplayRole? "New Name": "New Names of arrays";
375           case COMPONENTS:
376           return role == Qt::DisplayRole? "Components" : "Click item to edit components";
377           default:
378             break;
379         }
380       } else if ( role == Qt::DecorationRole ) {
381         switch ( section ) {
382           case PROCESSING: return QIcon( ":/ArrayRenamerIcons/resources/copy_ico_16x16.png" );
383           default:
384             break;
385         }
386       }
387     }
388     return Superclass::headerData( section, orientation, role );
389   }
390
391   //------------------------------------------------------------------
392   QString arrayName( const QModelIndex& idx ) const {
393     if ( idx.isValid() && idx.row() < myArraysInfo.size() ) {
394       return myArraysInfo[idx.row()].first;
395     }
396     return QString();
397   }
398
399   //------------------------------------------------------------------
400   void setArraysInfo( const QVector<QPair<QString, ArrayInfo> >& data ) {
401     emit beginResetModel();
402     myArraysInfo = data;
403     emit endResetModel();
404   }
405
406   //------------------------------------------------------------------
407   const ArraysInfoType& arraysInfo() const {
408     return myArraysInfo;
409   }
410
411   //------------------------------------------------------------------
412   ArraysInfoType& editArraysInfo() {
413     return myArraysInfo;
414   }
415
416 private:
417   Q_DISABLE_COPY(pqArraysModel);
418 };
419
420 //-----------------------------------------------------------------------------
421 pqEditComponents::pqEditComponents( pqComponentsModel* model, QWidget* parent ) {
422
423   myComponentsModel = model;
424   setWindowTitle( "Edit Components" );
425
426   //Layout
427   QVBoxLayout *mainLayout = new QVBoxLayout( this );
428   QGroupBox* aComps = new QGroupBox( "Components", this );
429   QGroupBox* aParams = new QGroupBox( "Parameters", this );
430   QGroupBox* aBtns = new QGroupBox( this );
431   mainLayout->addWidget( aComps );
432   mainLayout->addWidget( aParams );
433   mainLayout->addWidget( aBtns );
434   
435   /// Table
436   QVBoxLayout *aCompsLayout = new QVBoxLayout( aComps );
437   QTableView* componentsTable = new QTableView( this );
438   componentsTable->setModel( model );
439   aCompsLayout->addWidget( componentsTable );
440   componentsTable->horizontalHeader()->setSectionResizeMode( pqComponentsModel::COMPONENT_NAME,  QHeaderView::Stretch );
441   componentsTable->horizontalHeader()->setSectionResizeMode( pqComponentsModel::NEW_COMPONENT_NAME, QHeaderView::Stretch );
442
443   /// Parameters
444   QVBoxLayout *aParamsLayout = new QVBoxLayout( aParams );
445   myRenameAllComps = new QCheckBox( "Rename all similar Components", aParams );
446   aParamsLayout->addWidget( myRenameAllComps );
447   
448   /// Buttons
449   QPushButton* anOk = new QPushButton( "OK", this );
450   QPushButton* aCancel = new QPushButton( "Cancel", this );
451   QSpacerItem* space =  new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
452   QHBoxLayout* aBtnsLayout = new QHBoxLayout( aBtns );      
453   aBtnsLayout->addWidget( anOk );
454   aBtnsLayout->addItem( space );
455   aBtnsLayout->addWidget( aCancel );
456   
457   //Connections
458   connect( anOk, SIGNAL( clicked() ), this, SLOT( accept() ) );
459   connect( myRenameAllComps, SIGNAL( toggled(bool) ), this, SLOT( onRenameAll(bool) ) );
460   connect( aCancel, SIGNAL( clicked() ), this, SLOT( reject() ) );
461 }
462
463 //-----------------------------------------------------------------------------
464 pqEditComponents::~pqEditComponents() { }
465
466 //-----------------------------------------------------------------------------
467 bool pqEditComponents::renameAllComps() {
468   return myRenameAllComps->checkState() == Qt::Checked;
469 }
470
471 //-----------------------------------------------------------------------------
472 void pqEditComponents::onRenameAll( bool val ) {
473   myComponentsModel->setRenameSimilar( val );
474 }
475
476 //-----------------------------------------------------------------------------
477 pqArraysEditorPropertyWidget::pqArraysEditorPropertyWidget( vtkSMProxy* smproxy, vtkSMPropertyGroup* smgroup, QWidget* parentObject ) : 
478   Superclass(smproxy, parentObject) {
479
480   myPropertyGroup = smgroup;  
481   myConnection = vtkEventQtSlotConnect::New();
482   
483   // Table
484   myArraysTable = new QTableView(this);
485   myArraysModel = new pqArraysModel(this);
486   myArraysTable->setModel(myArraysModel);
487
488   // Layout
489   QVBoxLayout* lay = new QVBoxLayout(this);
490   lay->addWidget(myArraysTable);
491   myArraysTable->horizontalHeader()->setSectionResizeMode( pqArraysModel::PROCESSING, QHeaderView::ResizeToContents );
492   myArraysTable->horizontalHeader()->setSectionResizeMode( pqArraysModel::NAME,  QHeaderView::Stretch);
493   myArraysTable->horizontalHeader()->setSectionResizeMode( pqArraysModel::NEW_NAME, QHeaderView::Stretch );
494   myArraysTable->horizontalHeader()->setSectionResizeMode( pqArraysModel::COMPONENTS, QHeaderView::ResizeToContents );
495   myArraysTable->resizeColumnsToContents();
496
497   // Connections
498   /// Clien < - > Server
499   addPropertyLink( this, "arrayInfo", SIGNAL( arraysInfoChanged() ), smgroup->GetProperty( "ArrayInfo" ) );
500   addPropertyLink( this, "componentsInfo", SIGNAL( componentsInfoChanged() ), smgroup->GetProperty( "ComponentInfo" ) );
501   myConnection->Connect( smproxy, vtkCommand::UpdateDataEvent, this, SLOT( onInputDataChanged() ) ); 
502     
503   /// Qt
504   QObject::connect( myArraysModel,
505     SIGNAL( dataChanged( const QModelIndex &, const QModelIndex& ) ),
506     this, SLOT( onDataChanged( const QModelIndex&, const QModelIndex& ) ) );
507
508   // Obtains list of the data arrays
509   updateArraysList();
510 }
511
512 pqArraysEditorPropertyWidget::~pqArraysEditorPropertyWidget() {
513   delete myArraysModel;
514   myConnection->Delete();
515 }
516
517 //-----------------------------------------------------------------------------
518 void pqArraysEditorPropertyWidget::setArraysInfo( const QList<QVariant> & values ){
519   pqArraysModel::ArraysInfoType vdata;
520   vdata.resize( values.size()/3 );
521   for ( int cc=0; ( cc + 1 ) < values.size(); cc+=3 ) {
522     vdata[cc/3].first = values[cc].toString();
523     vdata[cc/3].second.newName = values[cc+1].toString();
524     vdata[cc/3].second.copyArray = values[cc+2].toBool();
525   }
526   myArraysModel->setArraysInfo( vdata );
527 }
528
529 //-----------------------------------------------------------------------------
530 QList<QVariant> pqArraysEditorPropertyWidget::arraysInfo() const {
531   const pqArraysModel::ArraysInfoType &vdata = myArraysModel->arraysInfo();
532   QList<QVariant> reply;
533   for ( int cc=0; cc < vdata.size(); cc++ ) {
534     if(vdata[cc].first != vdata[cc].second.newName ) {
535       reply.push_back( vdata[cc].first );
536       reply.push_back( vdata[cc].second.newName );
537       reply.push_back( vdata[cc].second.copyArray ? 1 : 0 );
538     }
539   }
540   return reply;
541 }
542
543 //-----------------------------------------------------------------------------
544 void pqArraysEditorPropertyWidget::setComponentsInfo( const QList<QVariant> & values ) {
545
546   pqArraysModel::ArraysInfoType &vdata = myArraysModel->editArraysInfo();
547   for(int i = 0; i < vdata.size(); i++) {
548     vdata.resize( values.size()/3 );
549     QString anArrayName = "", aNewCompName = "";
550     int aCompId = 0;
551     for ( int cc=0; ( cc + 1 ) < values.size(); cc+=3 ) {
552       anArrayName = values[cc].toString();
553       aCompId = values[cc+1].toInt();
554       aNewCompName = values[cc+2].toString();
555     }
556     if( vdata[i].first == anArrayName && aCompId < vdata[i].second.myComponentsInfo.size() ) {
557       vdata[i].second.myComponentsInfo[i].second = aNewCompName;
558     }
559   }
560 }
561
562 //-----------------------------------------------------------------------------
563 QList<QVariant> pqArraysEditorPropertyWidget::componentsInfo() const {
564
565   pqArraysModel::ArraysInfoType &vdata = myArraysModel->editArraysInfo();
566   QList<QVariant> reply;
567   for ( int cc=0; cc < vdata.size(); cc++ ) {
568     for ( int ll = 0; ll < vdata[cc].second.myComponentsInfo.size(); ll++ ) {
569       if ( vdata[cc].second.myComponentsInfo[ll].second != vdata[cc].second.myComponentsInfo[ll].first) {
570         QString aArrayName = 
571           (vdata[cc].first != vdata[cc].second.newName && !vdata[cc].second.newName.isEmpty()) ? vdata[cc].second.newName : vdata[cc].first;
572         reply.push_back( aArrayName );
573         reply.push_back( ll );
574         reply.push_back( vdata[cc].second.myComponentsInfo[ll].second );
575       }
576     }
577   }
578
579   return reply;
580 }
581
582 //-----------------------------------------------------------------------------
583 void pqArraysEditorPropertyWidget::onDataChanged( const QModelIndex& topleft, const QModelIndex& btmright ) {
584   if ( topleft.column() == pqArraysModel::PROCESSING || topleft.column() == pqArraysModel::NEW_NAME ) {
585     if ( topleft.column() == pqArraysModel::PROCESSING ) {
586       const pqArraysModel::ArraysInfoType &vdata = myArraysModel->arraysInfo();
587       Q_ASSERT(topleft.row() < vdata.size());
588       if( vdata[topleft.row()].second.isCompomentsModified() ) {
589         myPropertyGroup->GetProperty( "ComponentInfo" )->Modified();
590       }
591     }
592     emit arraysInfoChanged();
593   }
594 }
595
596 //-----------------------------------------------------------------------------
597 void pqArraysEditorPropertyWidget::updateArraysList() {
598   vtkPVDataSetAttributesInformation *cdi = NULL, *pdi = NULL;
599
600   vtkSMSourceProxy* input = vtkSMSourceProxy::SafeDownCast( vtkSMUncheckedPropertyHelper( proxy(), "Input" ).GetAsProxy( 0 ) );
601
602   // Null insput
603   if ( !input )
604     return;
605
606   const QVector<QPair<QString, pqArraysModel::ArrayInfo> > &oldModelData = myArraysModel->arraysInfo();
607   
608   QStringList oldNames;
609   QPair<QString, pqArraysModel::ArrayInfo> oldArrayInfo;
610   foreach ( oldArrayInfo, oldModelData ) {
611     oldNames.append(oldArrayInfo.first);
612   }
613
614   myDataTime = input->GetDataInformation( 0 )->GetMTime();
615
616   pdi = input->GetDataInformation( 0 )->GetPointDataInformation();
617   cdi = input->GetDataInformation( 0 )->GetCellDataInformation();
618   QVector<QPair<QString, pqArraysModel::ArrayInfo> > myModelArraysInfo;
619
620   if ( pdi ) {
621     for ( int i=0; i<pdi->GetNumberOfArrays(); i++ ) {
622       vtkPVArrayInformation* pvArrayInformation = pdi->GetArrayInformation( i );
623       QString anArrayName = QString( pvArrayInformation->GetName() );
624       int numComponents = pvArrayInformation->GetNumberOfComponents();
625       int index = oldNames.indexOf(anArrayName);
626       if ( index < 0 ) {
627
628         myModelArraysInfo.push_back( qMakePair( anArrayName , pqArraysModel::ArrayInfo() ) );
629         myModelArraysInfo.last().second.newName = anArrayName;  
630         for ( int j=0; j<numComponents; j++ ) {
631           QString compName =  pvArrayInformation->GetComponentName( j );
632           myModelArraysInfo.last().second.myComponentsInfo.insert(j, qMakePair( compName, compName ) );
633         }
634       } else {
635
636         myModelArraysInfo.push_back( qMakePair(anArrayName, oldModelData[index].second ) );
637         if ( oldModelData[index].second.nbComps() != numComponents ) {
638           for ( int j=0; j<numComponents; j++ ) {
639             QString compName =  pvArrayInformation->GetComponentName( j );
640             myModelArraysInfo.last().second.myComponentsInfo.insert( j, qMakePair( compName, compName ) );
641           }         
642         }
643       }
644     }
645   }
646   if ( cdi ) {
647     for ( int i=0; i<cdi->GetNumberOfArrays(); i++ ) {
648       
649       vtkPVArrayInformation* pvArrayInformation = cdi->GetArrayInformation( i );
650       QString anArrayName = QString( pvArrayInformation->GetName() );
651       int numComponents = pvArrayInformation->GetNumberOfComponents();
652       int index = oldNames.indexOf(anArrayName);
653       if ( index < 0 ) {
654         myModelArraysInfo.push_back( qMakePair( anArrayName , pqArraysModel::ArrayInfo() ) );
655         myModelArraysInfo.last().second.newName = anArrayName;
656         for ( int j=0; j<numComponents; j++ ){
657           QString compName =  pvArrayInformation->GetComponentName( j );
658           myModelArraysInfo.last().second.myComponentsInfo.insert( j,  qMakePair( compName, compName ) );
659         }       
660       } else {
661         
662         myModelArraysInfo.push_back( qMakePair(anArrayName, oldModelData[index].second ) );
663         if ( oldModelData[index].second.nbComps() != numComponents ) {
664           for ( int j=0; j<numComponents; j++ ) {
665             QString compName =  pvArrayInformation->GetComponentName( j );
666             myModelArraysInfo.last().second.myComponentsInfo.insert( j, qMakePair( compName, compName ) );
667           }         
668         }
669       }
670     }
671   }
672   
673   myArraysModel->setArraysInfo(myModelArraysInfo);
674   
675   for ( int i = 0; i < myModelArraysInfo.size(); i++ ) {
676     if ( myModelArraysInfo[i].second.nbComps() > 1 ) {
677       QPushButton* aBtn = new QPushButton(myArraysTable);
678       aBtn->setProperty("arrayName",myModelArraysInfo[i].first);
679       aBtn->setIcon( QIcon( ":/ArrayRenamerIcons/resources/edit_ico_16x16.png" ) );
680       myArraysTable->setIndexWidget( myArraysModel->index( i, 3 ), aBtn );
681       connect(aBtn, SIGNAL( clicked() ) , this, SLOT( onComponentsEdit() ) );
682     }
683   }
684 }
685   
686 //-----------------------------------------------------------------------------
687 void pqArraysEditorPropertyWidget::onInputDataChanged() {
688
689   vtkSMSourceProxy* input = vtkSMSourceProxy::SafeDownCast( vtkSMUncheckedPropertyHelper( proxy(), "Input" ).GetAsProxy( 0 ) );
690   if ( myDataTime < input->GetDataInformation( 0 )->GetMTime() ) {
691     updateArraysList();
692   }
693 }
694
695 //-----------------------------------------------------------------------------
696 void pqArraysEditorPropertyWidget::onComponentsEdit() {
697   QObject* snd = sender();
698   QVariant v = snd->property("arrayName");
699   int index = -1;
700
701   if( v.isValid() )  {
702     QString anArrayName = v.toString();
703     pqComponentsModel::ComponentsInfoType* aComponents = NULL;
704     pqArraysModel::ArraysInfoType &aModelData = myArraysModel->editArraysInfo();
705     for ( int i = 0 ; i < aModelData.size() ; i++ ) {
706       pqArraysModel::ArraysInfoItemType& item = aModelData[i];
707       if( item.first == anArrayName ) {
708         aComponents = &item.second.myComponentsInfo;
709         index = i;
710         break;
711       }
712     }
713
714     if( aComponents  )  {
715       pqComponentsModel* aCompsModel = new pqComponentsModel();
716       aCompsModel->setComponentsInfo(*aComponents);
717       pqEditComponents* dlg = new pqEditComponents(aCompsModel, this);
718       if ( dlg->exec() == QDialog::Accepted ) {
719         const pqComponentsModel::ComponentsInfoType& aRenamedComponents = aCompsModel->componentsInfo();
720         if( dlg->renameAllComps() )  {
721           /// Rename all components in all arrays
722           for ( int i = 0 ; i < aModelData.size() ; i++ ) {
723             pqArraysModel::ArraysInfoItemType& item = aModelData[i];
724             for (int j = 0; j < item.second.myComponentsInfo.size(); j++ ) {
725               pqComponentsModel::ComponentsInfoType &aComps = item.second.myComponentsInfo;
726               for (int k = 0; k < aRenamedComponents.size(); k++ ) {
727                 if( aComps[j].first == aRenamedComponents[k].first ) {
728                   aComps[j].second = aRenamedComponents[k].second;
729                 }    
730               }           
731             }
732           }
733         } else {
734           if( index >= 0 ) {
735             aModelData[index].second.myComponentsInfo = aRenamedComponents;
736           }
737         }
738         emit componentsInfoChanged();
739       }
740       delete dlg;
741       delete aCompsModel; 
742     }     
743   }
744 }