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