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