Salome HOME
Merge from V6_main 01/04/2013
[modules/paravis.git] / src / PVGUI / PVGUI_ParaViewSettingsPane.cxx
1 // PARAVIS : ParaView wrapper SALOME module
2 //
3 // Copyright (C) 2010-2013  CEA/DEN, EDF R&D
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 //
19 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 //
21 // File   : PVGUI_ParaViewSettingsPane.cxx
22 // Author : Vitaly Smetannikov
23 //
24
25 #include "PVGUI_ParaViewSettingsPane.h"
26 #include "ui_pqOptionsDialog.h"
27
28 #include <pqOptionsContainer.h>
29 #include <pqOptionsPage.h>
30 #include <pqUndoStack.h>
31 #include "pqApplicationCore.h"
32 #include "pqApplicationOptions.h"
33 #include "pqGlobalRenderViewOptions.h"
34 #include "pqPluginManager.h"
35 #include "pqViewOptionsInterface.h"
36 #include "pqInterfaceTracker.h"
37
38 #include <QAbstractItemModel>
39 #include <QHeaderView>
40 #include <QList>
41 #include <QMap>
42 #include <QString>
43
44
45 class OptionsDialogModelItem
46 {
47 public:
48   OptionsDialogModelItem();
49   OptionsDialogModelItem(const QString &name);
50   ~OptionsDialogModelItem();
51
52   OptionsDialogModelItem *Parent;
53   QString Name;
54   QList<OptionsDialogModelItem *> Children;
55 };
56
57
58 class OptionsDialogModel : public QAbstractItemModel
59 {
60 public:
61   OptionsDialogModel(QObject *parent=0);
62   virtual ~OptionsDialogModel();
63
64   virtual int rowCount(const QModelIndex &parent=QModelIndex()) const;
65   virtual int columnCount(const QModelIndex &parent=QModelIndex()) const;
66   virtual QModelIndex index(int row, int column,
67       const QModelIndex &parent=QModelIndex()) const;
68   virtual QModelIndex parent(const QModelIndex &child) const;
69
70   virtual QVariant data(const QModelIndex &index,
71       int role=Qt::DisplayRole) const;
72
73   QModelIndex getIndex(const QString &path) const;
74   QString getPath(const QModelIndex &index) const;
75   void addPath(const QString &path);
76   bool removeIndex(const QModelIndex &index);
77
78 private:
79   QModelIndex getIndex(OptionsDialogModelItem *item) const;
80
81 private:
82   OptionsDialogModelItem *Root;
83 };
84
85
86 class OptionsDialogForm : public Ui::pqOptionsFrame
87 {
88 public:
89   OptionsDialogForm();
90   ~OptionsDialogForm();
91
92   QMap<QString, pqOptionsPage *> Pages;
93   OptionsDialogModel *Model;
94   int ApplyUseCount;
95   //bool ApplyNeeded;
96 };
97
98
99 //----------------------------------------------------------------------------
100 OptionsDialogModelItem::OptionsDialogModelItem()
101   : Name(), Children()
102 {
103   this->Parent = 0;
104 }
105
106 OptionsDialogModelItem::OptionsDialogModelItem(const QString &name)
107   : Name(name), Children()
108 {
109   this->Parent = 0;
110 }
111
112 OptionsDialogModelItem::~OptionsDialogModelItem()
113 {
114   QList<OptionsDialogModelItem *>::Iterator iter = this->Children.begin();
115   for( ; iter != this->Children.end(); ++iter)
116     {
117     delete *iter;
118     }
119 }
120
121
122 //----------------------------------------------------------------------------
123 OptionsDialogModel::OptionsDialogModel(QObject *parentObject)
124   : QAbstractItemModel(parentObject)
125 {
126   this->Root = new OptionsDialogModelItem();
127 }
128
129 OptionsDialogModel::~OptionsDialogModel()
130 {
131   delete this->Root;
132 }
133
134 int OptionsDialogModel::rowCount(const QModelIndex &parentIndex) const
135 {
136   OptionsDialogModelItem *item = this->Root;
137   if(parentIndex.isValid())
138     {
139     item = reinterpret_cast<OptionsDialogModelItem *>(
140         parentIndex.internalPointer());
141     }
142
143   return item->Children.size();
144 }
145
146 int OptionsDialogModel::columnCount(const QModelIndex &) const
147 {
148   return 1;
149 }
150
151 QModelIndex OptionsDialogModel::index(int row, int column,
152     const QModelIndex &parentIndex) const
153 {
154   OptionsDialogModelItem *item = this->Root;
155   if(parentIndex.isValid())
156     {
157     item = reinterpret_cast<OptionsDialogModelItem *>(
158         parentIndex.internalPointer());
159     }
160
161   if(column == 0 && row >= 0 && row < item->Children.size())
162     {
163     return this->createIndex(row, column, item->Children[row]);
164     }
165
166   return QModelIndex();
167 }
168
169 QModelIndex OptionsDialogModel::parent(const QModelIndex &child) const
170 {
171   if(child.isValid())
172     {
173     OptionsDialogModelItem *item =
174         reinterpret_cast<OptionsDialogModelItem *>(child.internalPointer());
175     return this->getIndex(item->Parent);
176     }
177
178   return QModelIndex();
179 }
180
181 QVariant OptionsDialogModel::data(const QModelIndex &idx, int role) const
182 {
183   if(idx.isValid())
184     {
185     OptionsDialogModelItem *item =
186         reinterpret_cast<OptionsDialogModelItem *>(idx.internalPointer());
187     if(role == Qt::DisplayRole || role == Qt::ToolTipRole)
188       {
189       return QVariant(item->Name);
190       }
191     }
192
193   return QVariant();
194 }
195
196 QModelIndex OptionsDialogModel::getIndex(const QString &path) const
197 {
198   OptionsDialogModelItem *item = this->Root;
199   QStringList names = path.split(".");
200   QStringList::Iterator iter = names.begin();
201   for( ; item && iter != names.end(); ++iter)
202     {
203     OptionsDialogModelItem *child = 0;
204     QList<OptionsDialogModelItem *>::Iterator jter = item->Children.begin();
205     for( ; jter != item->Children.end(); ++jter)
206       {
207       if((*jter)->Name == *iter)
208         {
209         child = *jter;
210         break;
211         }
212       }
213
214     item = child;
215     }
216
217   if(item && item != this->Root)
218     {
219     return this->getIndex(item);
220     }
221
222   return QModelIndex();
223 }
224
225 QString OptionsDialogModel::getPath(const QModelIndex &idx) const
226 {
227   if(idx.isValid())
228     {
229     QString path;
230     OptionsDialogModelItem *item =
231         reinterpret_cast<OptionsDialogModelItem *>(idx.internalPointer());
232     if(item)
233       {
234       path = item->Name;
235       item = item->Parent;
236       }
237
238     while(item && item != this->Root)
239       {
240       path.prepend(".").prepend(item->Name);
241       item = item->Parent;
242       }
243
244     return path;
245     }
246
247   return QString();
248 }
249
250 void OptionsDialogModel::addPath(const QString &path)
251 {
252   OptionsDialogModelItem *item = this->Root;
253   QStringList names = path.split(".");
254   QStringList::Iterator iter = names.begin();
255   for( ; iter != names.end(); ++iter)
256     {
257     OptionsDialogModelItem *child = 0;
258     QList<OptionsDialogModelItem *>::Iterator jter = item->Children.begin();
259     for( ; jter != item->Children.end(); ++jter)
260       {
261       if((*jter)->Name == *iter)
262         {
263         child = *jter;
264         break;
265         }
266       }
267
268     if(!child)
269       {
270       child = new OptionsDialogModelItem(*iter);
271       child->Parent = item;
272       QModelIndex parentIndex = this->getIndex(item);
273       int row = item->Children.size();
274       this->beginInsertRows(parentIndex, row, row);
275       item->Children.append(child);
276       this->endInsertRows();
277       }
278
279     item = child;
280     }
281 }
282
283 bool OptionsDialogModel::removeIndex(const QModelIndex &idx)
284 {
285   if(idx.isValid())
286     {
287     OptionsDialogModelItem *item =
288         reinterpret_cast<OptionsDialogModelItem *>(idx.internalPointer());
289     if(item->Children.size() == 0)
290       {
291       QModelIndex parentIndex = this->getIndex(item->Parent);
292       this->beginRemoveRows(parentIndex, idx.row(), idx.row());
293       item->Parent->Children.removeAt(idx.row());
294       this->endRemoveRows();
295       delete item;
296       return true;
297       }
298     }
299
300   return false;
301 }
302
303 QModelIndex OptionsDialogModel::getIndex(
304     OptionsDialogModelItem *item) const
305 {
306   if(item && item->Parent)
307     {
308     return this->createIndex(item->Parent->Children.indexOf(item), 0, item);
309     }
310
311   return QModelIndex();
312 }
313
314
315 //----------------------------------------------------------------------------
316 OptionsDialogForm::OptionsDialogForm()
317   : Ui::pqOptionsFrame(), Pages()
318 {
319   this->Model = new OptionsDialogModel();
320   this->ApplyUseCount = 0;
321   //this->ApplyNeeded = false;
322 }
323
324 OptionsDialogForm::~OptionsDialogForm()
325 {
326   delete this->Model;
327 }
328
329
330 //----------------------------------------------------------------------------
331 PVGUI_ParaViewSettingsPane::PVGUI_ParaViewSettingsPane(QWidget *widgetParent)
332   : QtxUserDefinedContent(widgetParent)
333 {
334   this->Form = new OptionsDialogForm();
335   this->Form->setupUi(this);
336   this->Form->PageNames->setModel(this->Form->Model);
337
338   // Hide the tree widget header view.
339   this->Form->PageNames->header()->hide();
340
341   // Hide the apply and reset buttons until they are needed.
342   //this->Form->ApplyButton->setEnabled(false);
343   //this->Form->ResetButton->setEnabled(false);
344   //this->Form->ApplyButton->hide();
345   //this->Form->ResetButton->hide();
346
347   this->connect(this->Form->PageNames->selectionModel(),
348       SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
349       this, SLOT(changeCurrentPage()));
350   //this->connect(this->Form->ApplyButton, SIGNAL(clicked()),
351   //    this, SLOT(applyChanges()));
352   //this->connect(this->Form->ResetButton, SIGNAL(clicked()),
353   //    this, SLOT(resetChanges()));
354   //this->connect(this->Form->CloseButton, SIGNAL(clicked()),
355   //    this, SLOT(accept()));
356
357   // Code From pqApplicationOptionsDialog
358   //this->setApplyNeeded(true);
359
360   pqApplicationOptions* appOptions = new pqApplicationOptions;
361   this->addOptions(appOptions);
362   
363   pqGlobalRenderViewOptions* renOptions = new pqGlobalRenderViewOptions;
364   this->addOptions(renOptions);
365   
366   QStringList pages = appOptions->getPageList();
367   if(pages.size())
368     {
369     this->setCurrentPage(pages[0]);
370     }
371
372   /// Add panes as plugins are loaded.
373   QObject::connect(pqApplicationCore::instance()->getPluginManager(),
374     SIGNAL(guiInterfaceLoaded(QObject*)),
375     this, SLOT(pluginLoaded(QObject*)));
376
377   // Load panes from already loaded plugins.
378   foreach (QObject* plugin_interface, pqApplicationCore::instance()->interfaceTracker()->interfaces())
379            //pqApplicationCore::instance()->getPluginManager()->interfaces())
380     {
381     this->pluginLoaded(plugin_interface);
382     }
383 }
384
385 PVGUI_ParaViewSettingsPane::~PVGUI_ParaViewSettingsPane()
386 {
387   delete this->Form;
388 }
389 /*
390 bool PVGUI_ParaViewSettingsPane::isApplyNeeded() const
391 {
392   return this->Form->ApplyNeeded;
393 }
394 */
395 /*
396 void PVGUI_ParaViewSettingsPane::setApplyNeeded(bool applyNeeded)
397 {
398   if(applyNeeded != this->Form->ApplyNeeded)
399     {
400     if(!applyNeeded)
401       {
402       this->Form->ApplyNeeded = false;
403       //this->Form->ApplyButton->setEnabled(false);
404       //this->Form->ResetButton->setEnabled(false);
405       }
406     else if(this->Form->ApplyUseCount > 0)
407       {
408       this->Form->ApplyNeeded = true;
409       //this->Form->ApplyButton->setEnabled(true);
410       //this->Form->ResetButton->setEnabled(true);
411       }
412     }
413 }
414 */
415 void PVGUI_ParaViewSettingsPane::addOptions(const QString &path, pqOptionsPage *options)
416 {
417   if(!options)
418     {
419     return;
420     }
421
422   // See if the page is a container.
423   pqOptionsContainer *container = qobject_cast<pqOptionsContainer *>(options);
424   if(!container && path.isEmpty())
425     {
426     return;
427     }
428
429   // See if the page/container uses the apply button.
430   if(options->isApplyUsed())
431     {
432     this->Form->ApplyUseCount++;
433     /*if(this->Form->ApplyUseCount == 1)
434       {
435         //this->Form->ApplyButton->show();
436         //this->Form->ResetButton->show();
437         //QObject::connect(this, SIGNAL(accepted()), this, SLOT(applyChanges()));
438         }*/
439
440     //this->connect(options, SIGNAL(changesAvailable()),
441     //this, SLOT(enableButtons()));
442     }
443
444   // Add the widget to the stack.
445   this->Form->Stack->addWidget(options);
446
447   // Add the page(s) to the map and the model.
448   if(container)
449     {
450     // If the path is not empty, use it as the page prefix.
451     QString prefix;
452     if(!path.isEmpty())
453       {
454       prefix = path;
455       prefix.append(".");
456       }
457
458     container->setPagePrefix(prefix);
459
460     // Get the list of pages from the container.
461     QStringList pathList = container->getPageList();
462     QStringList::Iterator iter = pathList.begin();
463     for( ; iter != pathList.end(); ++iter)
464       {
465       this->Form->Pages.insert(prefix + *iter, options);
466       this->Form->Model->addPath(prefix + *iter);
467       }
468     }
469   else
470     {
471     this->Form->Pages.insert(path, options);
472     this->Form->Model->addPath(path);
473     }
474 }
475
476 void PVGUI_ParaViewSettingsPane::addOptions(pqOptionsContainer *options)
477 {
478   this->addOptions(QString(), options);
479 }
480
481 void PVGUI_ParaViewSettingsPane::removeOptions(pqOptionsPage *options)
482 {
483   if(!options)
484     {
485     return;
486     }
487
488   // Remove the widget from the stack.
489   this->Form->Stack->removeWidget(options);
490
491   // See if the options use the apply button.
492   if(options->isApplyUsed())
493     {
494     this->Form->ApplyUseCount--;
495     /*if(this->Form->ApplyUseCount == 0)
496       {
497         //this->Form->ApplyNeeded = false;
498       //this->Form->ApplyButton->setEnabled(false);
499       //this->Form->ResetButton->setEnabled(false);
500       //this->Form->ApplyButton->hide();
501       //this->Form->ResetButton->hide();
502       //QObject::disconnect(this, SIGNAL(accepted()), this, SLOT(applyChanges()));
503       }*/
504
505     this->disconnect(options, 0, this, 0);
506     }
507
508   // Search the map for the paths to remove.
509   QMap<QString, pqOptionsPage *>::Iterator iter = this->Form->Pages.begin();
510   while(iter != this->Form->Pages.end())
511     {
512     if(*iter == options)
513       {
514       QString path = iter.key();
515       iter = this->Form->Pages.erase(iter);
516
517       // Remove the item from the tree model as well.
518       QModelIndex index = this->Form->Model->getIndex(path);
519       QPersistentModelIndex parentIndex = index.parent();
520       if(this->Form->Model->removeIndex(index))
521         {
522         // Remove any empty parent items.
523         while(parentIndex.isValid() &&
524             this->Form->Model->rowCount(parentIndex) == 0)
525           {
526           index = parentIndex;
527           parentIndex = index.parent();
528
529           // Make sure the index path isn't in the map.
530           path = this->Form->Model->getPath(index);
531           if(this->Form->Pages.find(path) == this->Form->Pages.end())
532             {
533             if(!this->Form->Model->removeIndex(index))
534               {
535               break;
536               }
537             }
538           }
539         }
540       }
541     else
542       {
543       ++iter;
544       }
545     }
546 }
547
548 void PVGUI_ParaViewSettingsPane::setCurrentPage(const QString &path)
549 {
550   QModelIndex current = this->Form->Model->getIndex(path);
551   this->Form->PageNames->setCurrentIndex(current);
552 }
553
554 void PVGUI_ParaViewSettingsPane::applyChanges()
555 {
556   //if(this->Form->ApplyNeeded)
557   //  {
558     BEGIN_UNDO_SET("Changed View Settings");
559     emit this->aboutToApplyChanges();
560     QMap<QString, pqOptionsPage *>::Iterator iter = this->Form->Pages.begin();
561     for( ; iter != this->Form->Pages.end(); ++iter)
562       {
563       (*iter)->applyChanges();
564       }
565
566     //this->setApplyNeeded(false);
567     emit this->appliedChanges();
568     END_UNDO_SET();
569     //}
570 }
571
572 void PVGUI_ParaViewSettingsPane::resetChanges()
573 {
574   //if(this->Form->ApplyNeeded)
575   //{
576     QMap<QString, pqOptionsPage *>::Iterator iter = this->Form->Pages.begin();
577     for( ; iter != this->Form->Pages.end(); ++iter)
578       {
579       (*iter)->resetChanges();
580       }
581
582     //this->setApplyNeeded(false);
583     //}
584 }
585
586 void PVGUI_ParaViewSettingsPane::changeCurrentPage()
587 {
588   // Get the current index from the view.
589   QModelIndex current = this->Form->PageNames->currentIndex();
590
591   // Look up the path for the current index.
592   QString path = this->Form->Model->getPath(current);
593   QMap<QString, pqOptionsPage *>::Iterator iter = this->Form->Pages.find(path);
594   if(iter == this->Form->Pages.end())
595     {
596     // If no page is found, show the blank page.
597     this->Form->Stack->setCurrentWidget(this->Form->BlankPage);
598     }
599   else
600     {
601     this->Form->Stack->setCurrentWidget(*iter);
602     pqOptionsContainer *container = qobject_cast<pqOptionsContainer *>(*iter);
603     if(container)
604       {
605       // Get the path prefix from the container.
606       QString prefix = container->getPagePrefix();
607       if(!prefix.isEmpty())
608         {
609         // Remove the prefix from the path.
610         path.remove(0, prefix.length());
611         }
612
613       // Set the page on the container object.
614       container->setPage(path);
615       }
616     }
617 }
618
619 //-----------------------------------------------------------------------------
620 void PVGUI_ParaViewSettingsPane::pluginLoaded(QObject* iface)
621 {
622   pqViewOptionsInterface* viewOptions =
623     qobject_cast<pqViewOptionsInterface*>(iface);
624   if (viewOptions)
625     {
626     foreach(QString viewtype, viewOptions->viewTypes())
627       {
628       // Try to create global view options
629       pqOptionsContainer* globalOptions =
630         viewOptions->createGlobalViewOptions(viewtype, this);
631       if (globalOptions)
632         {
633         this->addOptions(globalOptions);
634         }
635       }
636     }
637 }
638
639 void PVGUI_ParaViewSettingsPane::store(QtxResourceMgr* , QtxPreferenceMgr* )
640 {
641   applyChanges();
642 }
643
644 void PVGUI_ParaViewSettingsPane::retrieve(QtxResourceMgr* , QtxPreferenceMgr* )
645 {
646 }
647