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