Salome HOME
Copyright update 2022
[modules/paravis.git] / src / PVGUI / PVGUI_ParaViewSettingsPane.cxx
1 // PARAVIS : ParaView wrapper SALOME module
2 //
3 // Copyright (C) 2010-2022  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, or (at your option) any later version.
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_pqCustomSettingsWidget.h"
27
28 #include <LightApp_Application.h>
29
30 #include <QtxDialog.h>
31
32 #include <QString>
33
34
35 #include "pqActiveObjects.h"
36 #include "pqApplicationCore.h"
37 #include "pqProxyWidget.h"
38 #include "pqSearchBox.h"
39 #include "pqServer.h"
40 #include "pqSettings.h"
41 #include "pqUndoStack.h"
42 #include "vtkNew.h"
43 #include "vtkPVXMLElement.h"
44 #include "vtkSmartPointer.h"
45 #include "vtkSMProperty.h"
46 #include "vtkSMPropertyHelper.h"
47 #include "vtkSMPropertyIterator.h"
48 #include "vtkSMProxy.h"
49 #include "vtkSMProxyIterator.h"
50 #include "vtkSMSessionProxyManager.h"
51 #include "vtkSMSettings.h"
52
53 #include <QKeyEvent>
54 #include <QMap>
55 #include <QPushButton>
56 #include <QScrollArea>
57 #include <QSpacerItem>
58 #include <QVBoxLayout>
59 #include <QShowEvent>
60 #include <QHideEvent>
61
62 class PVGUI_ParaViewSettingsPane::pqInternals
63 {
64 public:
65   Ui::CustomSettingsWidget Ui;
66
67   // Map from tab indices to stack widget indices. This is needed because there
68   // are more widgets in the stacked widgets than just what we add.
69   QMap<int, int> TabToStackedWidgets;
70 };
71
72 bool PVGUI_ParaViewSettingsPane::ShowRestartRequired = false;
73
74 //----------------------------------------------------------------------------
75 PVGUI_ParaViewSettingsPane::PVGUI_ParaViewSettingsPane(QWidget *widgetParent, LightApp_Application * app)
76   : QtxUserDefinedContent(widgetParent),
77     Internals (new PVGUI_ParaViewSettingsPane::pqInternals())
78 {
79   Ui::CustomSettingsWidget &ui = this->Internals->Ui;
80   ui.setupUi(this);
81   ui.tabBar->setDocumentMode(false);
82   ui.tabBar->setDrawBase(false);
83   ui.tabBar->setExpanding(false);
84   ui.tabBar->setUsesScrollButtons(true);
85
86   // Hide restart message
87   ui.restartRequiredLabel->setVisible(PVGUI_ParaViewSettingsPane::ShowRestartRequired);
88
89   QList<vtkSMProxy*> proxies_to_show;
90
91   pqServer* server = pqActiveObjects::instance().activeServer();
92   vtkNew<vtkSMProxyIterator> iter;
93   iter->SetSession(server->session());
94   iter->SetModeToOneGroup();
95   for (iter->Begin("settings"); !iter->IsAtEnd(); iter->Next())
96     {
97     vtkSMProxy* proxy = iter->GetProxy();
98     if (proxy)
99       {
100       proxies_to_show.push_back(proxy);
101       }
102     }
103
104   // Add color palette.
105   if (vtkSMProxy* proxy = server->proxyManager()->GetProxy("global_properties", "ColorPalette"))
106     {
107     proxies_to_show.push_back(proxy);
108     }
109
110   foreach (vtkSMProxy* proxy, proxies_to_show)
111     {
112     QString proxyName = proxy->GetXMLName();
113
114     QScrollArea *scrollArea = new QScrollArea(this);
115     scrollArea->setObjectName(QString("ScrollArea%1").arg(proxyName));
116     scrollArea->setWidgetResizable(true);
117     scrollArea->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
118     scrollArea->setFrameShape(QFrame::NoFrame);
119
120     QWidget* container = new QWidget(scrollArea);
121     container->setObjectName("Container");
122     container->setContentsMargins(6, 0, 6, 0);
123
124     QVBoxLayout* vbox = new QVBoxLayout(container);
125     vbox->setMargin(0);
126     vbox->setSpacing(0);
127
128     pqProxyWidget* widget = new pqProxyWidget(proxy, container);
129     widget->setObjectName("ProxyWidget");
130     widget->setApplyChangesImmediately(false);
131     widget->setView(NULL);
132
133     widget->connect(this, SIGNAL(accepted()), SLOT(apply()));
134     widget->connect(this, SIGNAL(rejected()), SLOT(reset()));
135     this->connect(widget, SIGNAL(restartRequired()), SLOT(showRestartRequiredMessage()));
136     vbox->addWidget(widget);
137
138     QSpacerItem* spacer = new QSpacerItem(0, 0,QSizePolicy::Fixed,
139       QSizePolicy::MinimumExpanding);
140     vbox->addItem(spacer);
141
142     scrollArea->setWidget(container);
143     // show panel widgets
144     widget->updatePanel();
145
146     int tabIndex = ui.tabBar->addTab(proxy->GetXMLLabel());
147     int stackIndex = ui.stackedWidget->addWidget(scrollArea);
148     this->Internals->TabToStackedWidgets[tabIndex] = stackIndex;
149
150     this->connect(widget, SIGNAL(changeAvailable()), SLOT(onChangeAvailable()));
151     widget->connect(this, SIGNAL(filterWidgets(bool, QString)), SLOT(filterWidgets(bool, QString)));
152     }
153
154   // Disable some buttons to start
155 //  ui.buttonBox->button(QDialogButtonBox::Reset)->setEnabled(false);
156 //  ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
157
158 //  this->connect(ui.buttonBox->button(QDialogButtonBox::RestoreDefaults), SIGNAL(clicked()),
159 //                SLOT(onRestoreDefaults()));
160 //  this->connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), SLOT(clicked(QAbstractButton*)));
161
162   // [ABN] connect to reset to default emitted by Light_App:
163   this->connect(app, SIGNAL(preferenceResetToDefaults()), this, SLOT(onRestoreDefaults()));
164
165   this->connect(this, SIGNAL(accepted()), SLOT(onAccepted()));
166   this->connect(this, SIGNAL(rejected()), SLOT(onRejected()));
167   this->connect(ui.tabBar, SIGNAL(currentChanged(int)), this, SLOT(onTabIndexChanged(int)));
168
169   this->connect(ui.SearchBox, SIGNAL(advancedSearchActivated(bool)), SLOT(filterPanelWidgets()));
170   this->connect(ui.SearchBox, SIGNAL(textChanged(QString)), SLOT(filterPanelWidgets()));
171
172   // After all the tabs are set up, select the first
173   this->onTabIndexChanged(0);
174
175   this->filterPanelWidgets();
176 }
177
178 //-----------------------------------------------------------------------------
179 PVGUI_ParaViewSettingsPane::~PVGUI_ParaViewSettingsPane()
180 {
181   delete this->Internals;
182   this->Internals = NULL;
183 }
184
185 void PVGUI_ParaViewSettingsPane::store(QtxResourceMgr* , QtxPreferenceMgr* )
186 {
187   emit this->accepted();
188 }
189
190 void PVGUI_ParaViewSettingsPane::retrieve(QtxResourceMgr* , QtxPreferenceMgr* )
191 {
192 //  onRestoreDefaults();
193 }
194
195 void PVGUI_ParaViewSettingsPane::showEvent(QShowEvent * ev)
196 {
197 //  // Connect SALOME's default button to ParaView's default restore.
198 //  LightApp_PreferencesDlg * prefDg;
199 //  QWidget *w = this->parentWidget();
200 //  // UGLY!!!
201 //  while (w)
202 //    {
203 //      LightApp_PreferencesDlg * prefDg = dynamic_cast<LightApp_PreferencesDlg *>( w );
204 //      if (prefDg)
205 //        break;
206 //      w = w->parentWidget();
207 //    }
208 //  if (prefDg)
209 //    prefDg->connect(btn, SIGNAL(clicked()), this, SLOT(onRestoreDefaults()));
210   ev->accept();
211 }
212
213 void PVGUI_ParaViewSettingsPane::hideEvent(QHideEvent * ev)
214 {
215   // Connect SALOME's default button to ParaView's default restore.
216   ev->accept();
217 }
218
219 //-----------------------------------------------------------------------------
220 void PVGUI_ParaViewSettingsPane::clicked(QAbstractButton * /*button*/)
221 {
222 //  Ui::CustomSettingsWidget &ui = this->Internals->Ui;
223 //  QDialogButtonBox::ButtonRole role = ui.buttonBox->buttonRole(button);
224 //  switch (role)
225 //    {
226 //  case QDialogButtonBox::AcceptRole:
227 //  case QDialogButtonBox::ApplyRole:
228 //    emit this->accepted();
229 //    break;
230 //
231 //  case QDialogButtonBox::ResetRole:
232 //  case QDialogButtonBox::RejectRole:
233 //    emit this->rejected();
234 //    break;
235 //  default:
236 //    break;
237 //    }
238 }
239
240 //-----------------------------------------------------------------------------
241 void PVGUI_ParaViewSettingsPane::onAccepted()
242 {
243   // If there are any properties that needed to save their values in QSettings,
244   // do that. Otherwise, save to the vtkSMSettings singleton.
245   vtkSMSettings * settings = vtkSMSettings::GetInstance();
246   pqServer* server = pqActiveObjects::instance().activeServer();
247   vtkNew<vtkSMProxyIterator> iter;
248   iter->SetSession(server->session());
249   iter->SetModeToOneGroup();
250   for (iter->Begin("settings"); !iter->IsAtEnd(); iter->Next())
251     {
252     vtkSMProxy* proxy = iter->GetProxy();
253     settings->SetProxySettings(proxy);
254     vtkSmartPointer<vtkSMPropertyIterator> iter2;
255     iter2.TakeReference(proxy->NewPropertyIterator());
256     for (iter2->Begin(); !iter2->IsAtEnd(); iter2->Next())
257       {
258       vtkSMProperty* smproperty = iter2->GetProperty();
259       if (smproperty && smproperty->GetHints() &&
260         smproperty->GetHints()->FindNestedElementByName("SaveInQSettings"))
261         {
262         QString key = QString("%1.%2").arg(iter->GetKey()).arg(iter2->GetKey());
263         this->saveInQSettings(key.toLatin1().data(), smproperty);
264         }
265       }
266     }
267
268   // Save color palette settings
269   vtkSMProxy* paletteProxy = server->proxyManager()->GetProxy("global_properties", "ColorPalette");
270   if (paletteProxy)
271     {
272     settings->SetProxySettings(paletteProxy);
273     }
274
275   // Disable buttons
276 //  Ui::CustomSettingsWidget &ui = this->Internals->Ui;
277 //  ui.buttonBox->button(QDialogButtonBox::Reset)->setEnabled(false);
278 //  ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
279
280   // In theory, the above changes are undo-redo able, the only things that's not
281   // undo-able is the "serialized" values. Hence we just clear the undo stack.
282   CLEAR_UNDO_STACK();
283 }
284
285 //-----------------------------------------------------------------------------
286 void PVGUI_ParaViewSettingsPane::onRejected()
287 {
288   // Disable buttons
289 //  Ui::CustomSettingsWidget &ui = this->Internals->Ui;
290 //  ui.buttonBox->button(QDialogButtonBox::Reset)->setEnabled(false);
291 //  ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
292 }
293
294 //-----------------------------------------------------------------------------
295 void PVGUI_ParaViewSettingsPane::onRestoreDefaults()
296 {
297   pqServer* server = pqActiveObjects::instance().activeServer();
298   vtkSMSession * session = server->session();
299
300   vtkNew<vtkSMProxyIterator> iter;
301   iter->SetSession(session);
302   iter->SetModeToOneGroup();
303   for (iter->Begin("settings"); !iter->IsAtEnd(); iter->Next())
304     {
305     vtkSMProxy* proxy = iter->GetProxy();
306     if (proxy)
307       {
308       proxy->ResetPropertiesToXMLDefaults();
309       }
310     }
311
312   vtkSMProxy* paletteProxy = server->proxyManager()->GetProxy("global_properties", "ColorPalette");
313   if (paletteProxy)
314     {
315     paletteProxy->ResetPropertiesToXMLDefaults();
316     }
317 }
318
319 //-----------------------------------------------------------------------------
320 void PVGUI_ParaViewSettingsPane::onTabIndexChanged(int index)
321 {
322   int stackWidgetIndex = this->Internals->TabToStackedWidgets[index];
323   Ui::CustomSettingsWidget &ui = this->Internals->Ui;
324   ui.stackedWidget->setCurrentIndex(stackWidgetIndex);
325 }
326
327 //-----------------------------------------------------------------------------
328 void PVGUI_ParaViewSettingsPane::filterPanelWidgets()
329 {
330   Ui::CustomSettingsWidget &ui = this->Internals->Ui;
331   emit this->filterWidgets(
332     ui.SearchBox->isAdvancedSearchActive(), ui.SearchBox->text());
333 }
334
335 //-----------------------------------------------------------------------------
336 void PVGUI_ParaViewSettingsPane::onChangeAvailable()
337 {
338 //  Ui::CustomSettingsWidget &ui = this->Internals->Ui;
339 //  ui.buttonBox->button(QDialogButtonBox::Reset)->setEnabled(true);
340 //  ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(true);
341 }
342
343 //-----------------------------------------------------------------------------
344 void PVGUI_ParaViewSettingsPane::showRestartRequiredMessage()
345 {
346   Ui::CustomSettingsWidget &ui = this->Internals->Ui;
347   ui.restartRequiredLabel->setVisible(true);
348   PVGUI_ParaViewSettingsPane::ShowRestartRequired = true;
349 }
350
351 //-----------------------------------------------------------------------------
352 void PVGUI_ParaViewSettingsPane::saveInQSettings(
353   const char* key, vtkSMProperty* smproperty)
354 {
355   pqSettings* settings = pqApplicationCore::instance()->settings();
356
357   // FIXME: handle all property types. This will only work for single value
358   // properties.
359   if (smproperty->IsA("vtkSMIntVectorProperty") ||
360     smproperty->IsA("vtkSMIdTypeVectorProperty"))
361     {
362     settings->setValue(key, vtkSMPropertyHelper(smproperty).GetAsInt());
363     }
364   else if (smproperty->IsA("vtkSMDoubleVectorProperty"))
365     {
366     settings->setValue(key, vtkSMPropertyHelper(smproperty).GetAsDouble());
367     }
368   else if (smproperty->IsA("vtkSMStringVectorProperty"))
369     {
370     settings->setValue(key, vtkSMPropertyHelper(smproperty).GetAsString());
371     }
372 }
373