Salome HOME
[salome test] Update list of tests
[modules/paravis.git] / src / Plugins / ArrayRenamer / pqArraysEditorPropertyWidget.cxx
1 // Copyright (C) 2014-2016  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 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
441   componentsTable->horizontalHeader()->setResizeMode( pqComponentsModel::COMPONENT_NAME,  QHeaderView::Stretch );
442   componentsTable->horizontalHeader()->setResizeMode( pqComponentsModel::NEW_COMPONENT_NAME, QHeaderView::Stretch );
443 #else
444   componentsTable->horizontalHeader()->setSectionResizeMode( pqComponentsModel::COMPONENT_NAME,  QHeaderView::Stretch );
445   componentsTable->horizontalHeader()->setSectionResizeMode( pqComponentsModel::NEW_COMPONENT_NAME, QHeaderView::Stretch );
446 #endif
447   /// Parameters
448   QVBoxLayout *aParamsLayout = new QVBoxLayout( aParams );
449   myRenameAllComps = new QCheckBox( "Rename all similar Components", aParams );
450   aParamsLayout->addWidget( myRenameAllComps );
451   
452   /// Buttons
453   QPushButton* anOk = new QPushButton( "OK", this );
454   QPushButton* aCancel = new QPushButton( "Cancel", this );
455   QSpacerItem* space =  new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
456   QHBoxLayout* aBtnsLayout = new QHBoxLayout( aBtns );      
457   aBtnsLayout->addWidget( anOk );
458   aBtnsLayout->addItem( space );
459   aBtnsLayout->addWidget( aCancel );
460   
461   //Connections
462   connect( anOk, SIGNAL( clicked() ), this, SLOT( accept() ) );
463   connect( myRenameAllComps, SIGNAL( toggled(bool) ), this, SLOT( onRenameAll(bool) ) );
464   connect( aCancel, SIGNAL( clicked() ), this, SLOT( reject() ) );
465 }
466
467 //-----------------------------------------------------------------------------
468 pqEditComponents::~pqEditComponents() { }
469
470 //-----------------------------------------------------------------------------
471 bool pqEditComponents::renameAllComps() {
472   return myRenameAllComps->checkState() == Qt::Checked;
473 }
474
475 //-----------------------------------------------------------------------------
476 void pqEditComponents::onRenameAll( bool val ) {
477   myComponentsModel->setRenameSimilar( val );
478 }
479
480 //-----------------------------------------------------------------------------
481 pqArraysEditorPropertyWidget::pqArraysEditorPropertyWidget( vtkSMProxy* smproxy, vtkSMPropertyGroup* smgroup, QWidget* parentObject ) : 
482   Superclass(smproxy, parentObject) {
483
484   myPropertyGroup = smgroup;  
485   myConnection = vtkEventQtSlotConnect::New();
486   
487   // Table
488   myArraysTable = new QTableView(this);
489   myArraysModel = new pqArraysModel(this);
490   myArraysTable->setModel(myArraysModel);
491
492   // Layout
493   QVBoxLayout* lay = new QVBoxLayout(this);
494   lay->addWidget(myArraysTable);
495 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
496   myArraysTable->horizontalHeader()->setResizeMode( pqArraysModel::PROCESSING, QHeaderView::ResizeToContents );
497   myArraysTable->horizontalHeader()->setResizeMode( pqArraysModel::NAME,  QHeaderView::Stretch);
498   myArraysTable->horizontalHeader()->setResizeMode( pqArraysModel::NEW_NAME, QHeaderView::Stretch );
499   myArraysTable->horizontalHeader()->setResizeMode( pqArraysModel::COMPONENTS, QHeaderView::ResizeToContents );
500 #else
501   myArraysTable->horizontalHeader()->setSectionResizeMode( pqArraysModel::PROCESSING, QHeaderView::ResizeToContents );
502   myArraysTable->horizontalHeader()->setSectionResizeMode( pqArraysModel::NAME,  QHeaderView::Stretch);
503   myArraysTable->horizontalHeader()->setSectionResizeMode( pqArraysModel::NEW_NAME, QHeaderView::Stretch );
504   myArraysTable->horizontalHeader()->setSectionResizeMode( pqArraysModel::COMPONENTS, QHeaderView::ResizeToContents );
505 #endif
506   myArraysTable->resizeColumnsToContents();
507
508   // Connections
509   /// Clien < - > Server
510   addPropertyLink( this, "arrayInfo", SIGNAL( arraysInfoChanged() ), smgroup->GetProperty( "ArrayInfo" ) );
511   addPropertyLink( this, "componentsInfo", SIGNAL( componentsInfoChanged() ), smgroup->GetProperty( "ComponentInfo" ) );
512   myConnection->Connect( smproxy, vtkCommand::UpdateDataEvent, this, SLOT( onInputDataChanged() ) ); 
513     
514   /// Qt
515   QObject::connect( myArraysModel,
516     SIGNAL( dataChanged( const QModelIndex &, const QModelIndex& ) ),
517     this, SLOT( onDataChanged( const QModelIndex&, const QModelIndex& ) ) );
518
519   // Obtains list of the data arrays
520   updateArraysList();
521 }
522
523 pqArraysEditorPropertyWidget::~pqArraysEditorPropertyWidget() {
524   delete myArraysModel;
525   myConnection->Delete();
526 }
527
528 //-----------------------------------------------------------------------------
529 void pqArraysEditorPropertyWidget::setArraysInfo( const QList<QVariant> & values ){
530   pqArraysModel::ArraysInfoType vdata;
531   vdata.resize( values.size()/3 );
532   for ( int cc=0; ( cc + 1 ) < values.size(); cc+=3 ) {
533     vdata[cc/3].first = values[cc].toString();
534     vdata[cc/3].second.newName = values[cc+1].toString();
535     vdata[cc/3].second.copyArray = values[cc+2].toBool();
536   }
537   myArraysModel->setArraysInfo( vdata );
538 }
539
540 //-----------------------------------------------------------------------------
541 QList<QVariant> pqArraysEditorPropertyWidget::arraysInfo() const {
542   const pqArraysModel::ArraysInfoType &vdata = myArraysModel->arraysInfo();
543   QList<QVariant> reply;
544   for ( int cc=0; cc < vdata.size(); cc++ ) {
545     if(vdata[cc].first != vdata[cc].second.newName ) {
546       reply.push_back( vdata[cc].first );
547       reply.push_back( vdata[cc].second.newName );
548       reply.push_back( vdata[cc].second.copyArray ? 1 : 0 );
549     }
550   }
551   return reply;
552 }
553
554 //-----------------------------------------------------------------------------
555 void pqArraysEditorPropertyWidget::setComponentsInfo( const QList<QVariant> & values ) {
556
557   pqArraysModel::ArraysInfoType &vdata = myArraysModel->editArraysInfo();
558   for(int i = 0; i < vdata.size(); i++) {
559     vdata.resize( values.size()/3 );
560     QString anArrayName = "", aNewCompName = "";
561     int aCompId = 0;
562     for ( int cc=0; ( cc + 1 ) < values.size(); cc+=3 ) {
563       anArrayName = values[cc].toString();
564       aCompId = values[cc+1].toInt();
565       aNewCompName = values[cc+2].toString();
566     }
567     if( vdata[i].first == anArrayName && aCompId < vdata[i].second.myComponentsInfo.size() ) {
568       vdata[i].second.myComponentsInfo[i].second = aNewCompName;
569     }
570   }
571 }
572
573 //-----------------------------------------------------------------------------
574 QList<QVariant> pqArraysEditorPropertyWidget::componentsInfo() const {
575
576   pqArraysModel::ArraysInfoType &vdata = myArraysModel->editArraysInfo();
577   QList<QVariant> reply;
578   for ( int cc=0; cc < vdata.size(); cc++ ) {
579     for ( int ll = 0; ll < vdata[cc].second.myComponentsInfo.size(); ll++ ) {
580       if ( vdata[cc].second.myComponentsInfo[ll].second != vdata[cc].second.myComponentsInfo[ll].first) {
581         QString aArrayName = 
582           (vdata[cc].first != vdata[cc].second.newName && !vdata[cc].second.newName.isEmpty()) ? vdata[cc].second.newName : vdata[cc].first;
583         reply.push_back( aArrayName );
584         reply.push_back( ll );
585         reply.push_back( vdata[cc].second.myComponentsInfo[ll].second );
586       }
587     }
588   }
589
590   return reply;
591 }
592
593 //-----------------------------------------------------------------------------
594 void pqArraysEditorPropertyWidget::onDataChanged( const QModelIndex& topleft, const QModelIndex& btmright ) {
595   if ( topleft.column() == pqArraysModel::PROCESSING || topleft.column() == pqArraysModel::NEW_NAME ) {
596     if ( topleft.column() == pqArraysModel::PROCESSING ) {
597       const pqArraysModel::ArraysInfoType &vdata = myArraysModel->arraysInfo();
598       Q_ASSERT(topleft.row() < vdata.size());
599       if( vdata[topleft.row()].second.isCompomentsModified() ) {
600         myPropertyGroup->GetProperty( "ComponentInfo" )->Modified();
601       }
602     }
603     emit arraysInfoChanged();
604   }
605 }
606
607 //-----------------------------------------------------------------------------
608 void pqArraysEditorPropertyWidget::updateArraysList() {
609   vtkPVDataSetAttributesInformation *cdi = NULL, *pdi = NULL;
610
611   vtkSMSourceProxy* input = vtkSMSourceProxy::SafeDownCast( vtkSMUncheckedPropertyHelper( proxy(), "Input" ).GetAsProxy( 0 ) );
612
613   // Null insput
614   if ( !input )
615     return;
616
617   const QVector<QPair<QString, pqArraysModel::ArrayInfo> > &oldModelData = myArraysModel->arraysInfo();
618   
619   QStringList oldNames;
620   QPair<QString, pqArraysModel::ArrayInfo> oldArrayInfo;
621   foreach ( oldArrayInfo, oldModelData ) {
622     oldNames.append(oldArrayInfo.first);
623   }
624
625   myDataTime = input->GetDataInformation( 0 )->GetMTime();
626
627   pdi = input->GetDataInformation( 0 )->GetPointDataInformation();
628   cdi = input->GetDataInformation( 0 )->GetCellDataInformation();
629   QVector<QPair<QString, pqArraysModel::ArrayInfo> > myModelArraysInfo;
630
631   if ( pdi ) {
632     for ( int i=0; i<pdi->GetNumberOfArrays(); i++ ) {
633       vtkPVArrayInformation* pvArrayInformation = pdi->GetArrayInformation( i );
634       QString anArrayName = QString( pvArrayInformation->GetName() );
635       int numComponents = pvArrayInformation->GetNumberOfComponents();
636       int index = oldNames.indexOf(anArrayName);
637       if ( index < 0 ) {
638
639         myModelArraysInfo.push_back( qMakePair( anArrayName , pqArraysModel::ArrayInfo() ) );
640         myModelArraysInfo.last().second.newName = anArrayName;  
641         for ( int j=0; j<numComponents; j++ ) {
642           QString compName =  pvArrayInformation->GetComponentName( j );
643           myModelArraysInfo.last().second.myComponentsInfo.insert(j, qMakePair( compName, compName ) );
644         }
645       } else {
646
647         myModelArraysInfo.push_back( qMakePair(anArrayName, oldModelData[index].second ) );
648         if ( oldModelData[index].second.nbComps() != numComponents ) {
649           for ( int j=0; j<numComponents; j++ ) {
650             QString compName =  pvArrayInformation->GetComponentName( j );
651             myModelArraysInfo.last().second.myComponentsInfo.insert( j, qMakePair( compName, compName ) );
652           }         
653         }
654       }
655     }
656   }
657   if ( cdi ) {
658     for ( int i=0; i<cdi->GetNumberOfArrays(); i++ ) {
659       
660       vtkPVArrayInformation* pvArrayInformation = cdi->GetArrayInformation( i );
661       QString anArrayName = QString( pvArrayInformation->GetName() );
662       int numComponents = pvArrayInformation->GetNumberOfComponents();
663       int index = oldNames.indexOf(anArrayName);
664       if ( index < 0 ) {
665         myModelArraysInfo.push_back( qMakePair( anArrayName , pqArraysModel::ArrayInfo() ) );
666         myModelArraysInfo.last().second.newName = anArrayName;
667         for ( int j=0; j<numComponents; j++ ){
668           QString compName =  pvArrayInformation->GetComponentName( j );
669           myModelArraysInfo.last().second.myComponentsInfo.insert( j,  qMakePair( compName, compName ) );
670         }       
671       } else {
672         
673         myModelArraysInfo.push_back( qMakePair(anArrayName, oldModelData[index].second ) );
674         if ( oldModelData[index].second.nbComps() != numComponents ) {
675           for ( int j=0; j<numComponents; j++ ) {
676             QString compName =  pvArrayInformation->GetComponentName( j );
677             myModelArraysInfo.last().second.myComponentsInfo.insert( j, qMakePair( compName, compName ) );
678           }         
679         }
680       }
681     }
682   }
683   
684   myArraysModel->setArraysInfo(myModelArraysInfo);
685   
686   for ( int i = 0; i < myModelArraysInfo.size(); i++ ) {
687     if ( myModelArraysInfo[i].second.nbComps() > 1 ) {
688       QPushButton* aBtn = new QPushButton(myArraysTable);
689       aBtn->setProperty("arrayName",myModelArraysInfo[i].first);
690       aBtn->setIcon( QIcon( ":/ArrayRenamerIcons/resources/edit_ico_16x16.png" ) );
691       myArraysTable->setIndexWidget( myArraysModel->index( i, 3 ), aBtn );
692       connect(aBtn, SIGNAL( clicked() ) , this, SLOT( onComponentsEdit() ) );
693     }
694   }
695 }
696   
697 //-----------------------------------------------------------------------------
698 void pqArraysEditorPropertyWidget::onInputDataChanged() {
699
700   vtkSMSourceProxy* input = vtkSMSourceProxy::SafeDownCast( vtkSMUncheckedPropertyHelper( proxy(), "Input" ).GetAsProxy( 0 ) );
701   if ( myDataTime < input->GetDataInformation( 0 )->GetMTime() ) {
702     updateArraysList();
703   }
704 }
705
706 //-----------------------------------------------------------------------------
707 void pqArraysEditorPropertyWidget::onComponentsEdit() {
708   QObject* snd = sender();
709   QVariant v = snd->property("arrayName");
710   int index = -1;
711
712   if( v.isValid() )  {
713     QString anArrayName = v.toString();
714     pqComponentsModel::ComponentsInfoType* aComponents = NULL;
715     pqArraysModel::ArraysInfoType &aModelData = myArraysModel->editArraysInfo();
716     for ( int i = 0 ; i < aModelData.size() ; i++ ) {
717       pqArraysModel::ArraysInfoItemType& item = aModelData[i];
718       if( item.first == anArrayName ) {
719         aComponents = &item.second.myComponentsInfo;
720         index = i;
721         break;
722       }
723     }
724
725     if( aComponents  )  {
726       pqComponentsModel* aCompsModel = new pqComponentsModel();
727       aCompsModel->setComponentsInfo(*aComponents);
728       pqEditComponents* dlg = new pqEditComponents(aCompsModel, this);
729       if ( dlg->exec() == QDialog::Accepted ) {
730         const pqComponentsModel::ComponentsInfoType& aRenamedComponents = aCompsModel->componentsInfo();
731         if( dlg->renameAllComps() )  {
732           /// Rename all components in all arrays
733           for ( int i = 0 ; i < aModelData.size() ; i++ ) {
734             pqArraysModel::ArraysInfoItemType& item = aModelData[i];
735             for (int j = 0; j < item.second.myComponentsInfo.size(); j++ ) {
736               pqComponentsModel::ComponentsInfoType &aComps = item.second.myComponentsInfo;
737               for (int k = 0; k < aRenamedComponents.size(); k++ ) {
738                 if( aComps[j].first == aRenamedComponents[k].first ) {
739                   aComps[j].second = aRenamedComponents[k].second;
740                 }    
741               }           
742             }
743           }
744         } else {
745           if( index >= 0 ) {
746             aModelData[index].second.myComponentsInfo = aRenamedComponents;
747           }
748         }
749         emit componentsInfoChanged();
750       }
751       delete dlg;
752       delete aCompsModel; 
753     }     
754   }
755 }