]> SALOME platform Git repositories - modules/shaper.git/blob - src/ModuleBase/ModuleBase_WidgetOptionalBox.cpp
Salome HOME
Issue #3086: Avoid crash when FeatureInfo is null.
[modules/shaper.git] / src / ModuleBase / ModuleBase_WidgetOptionalBox.cpp
1 // Copyright (C) 2014-2019  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
20 #include <ModuleBase_WidgetOptionalBox.h>
21 #include <ModelAPI_AttributeString.h>
22 #include <ModelAPI_AttributeBoolean.h>
23
24 #include <Config_WidgetAPI.h>
25 #include <Config_Keywords.h>
26
27 #include <QWidget>
28 #include <QGroupBox>
29 #include <QCheckBox>
30 #include <QGridLayout>
31 #include <QVBoxLayout>
32
33 #include <QList>
34
35 ModuleBase_WidgetOptionalBox::ModuleBase_WidgetOptionalBox(QWidget* theParent,
36                                                                const Config_WidgetAPI* theData)
37 : ModuleBase_ModelWidget(theParent, theData),
38   ModuleBase_PageBase(),
39   myOptionType(CheckBox),
40   myCheckBoxFrame(0),
41   myCheckBox(0),
42   myCheckBoxLayout(0),
43   myCheckBoxWidget(0),
44   myGroupBox(0),
45   myGroupBoxLayout(0),
46   myCheckGroup(0),
47   myCheckGroupLayout(0),
48   myCheckContent(0),
49   myCheckGroupBtn(0),
50   myEnableOnCheck(true)
51 {
52   myToolTip = theData->widgetTooltip();
53   myGroupTitle = theData->getProperty(CONTAINER_PAGE_NAME);
54
55   myHaveFrame = theData->getBooleanAttribute("has_frame", true);
56   myEnableOnCheck = theData->getBooleanAttribute("enable_on_check", true);
57
58   bool isChecked = theData->getBooleanAttribute(ATTR_DEFAULT, false);
59   setDefaultValue(isChecked ? "true" : "false");
60
61   myMainLayout = new QVBoxLayout(this);
62   ModuleBase_Tools::adjustMargins(myMainLayout);
63 }
64
65 ModuleBase_WidgetOptionalBox::~ModuleBase_WidgetOptionalBox()
66 {
67 }
68
69 QWidget* ModuleBase_WidgetOptionalBox::pageWidget()
70 {
71   return myOptionType == GroupBox ? (myGroupBox? myGroupBox : myCheckGroup) :
72     (QWidget*)myCheckBoxFrame;
73 }
74
75 QList<QWidget*> ModuleBase_WidgetOptionalBox::getControls() const
76 {
77   QList<QWidget*> aControls;
78   if (myOptionType == GroupBox) {
79     if (myGroupBox)
80       aControls.append(myGroupBox);
81     else
82       aControls.append(myCheckGroup);
83   }
84   else
85     aControls.append(myCheckBoxFrame);
86
87   return aControls;
88 }
89
90 void ModuleBase_WidgetOptionalBox::onPageClicked()
91 {
92   storeValue();
93   updateControlsVisibility();
94
95   if (!isEditingMode())
96     emit focusOutWidget(this);
97 }
98
99 void ModuleBase_WidgetOptionalBox::addPageStretch()
100 {
101 }
102
103 void ModuleBase_WidgetOptionalBox::placeModelWidget(ModuleBase_ModelWidget* theWidget)
104 {
105   if(!isCheckBoxFilled() && myOptionType == CheckBox) {
106     createControl(CheckBox);
107     setOptionType(CheckBox);
108
109     myCheckBoxWidget = theWidget; /// check box frame becomes filled
110     myCheckBoxLayout->addWidget(theWidget, 1);
111   }
112   else {
113     createControl(GroupBox);
114     setOptionType(GroupBox);
115
116     ModuleBase_ModelWidget* aCheckBoxWidget = myCheckBoxWidget;
117     myCheckBoxWidget = 0;
118     if (aCheckBoxWidget) // move the model widget from check box frame to group box frame
119       placeModelWidget(aCheckBoxWidget);
120
121     const int kCol = 0;
122     const int kRow = myGroupBoxLayout->count();
123     // it seems, that the align on left is not necessary here, but leads to widgets, which are
124     // not extended on full width of the parent page. The case is grouped widgets in
125     // the sketch translation operation
126     myGroupBoxLayout->addWidget(theWidget, kRow, kCol, Qt::AlignTop);// | Qt::AlignLeft);
127     myGroupBoxLayout->setRowStretch(kRow, 0);
128   }
129 }
130
131 void ModuleBase_WidgetOptionalBox::placeWidget(QWidget* theWidget)
132 {
133   createControl(GroupBox);
134   setOptionType(GroupBox);
135   if (isCheckBoxFilled())
136     placeModelWidget(myCheckBoxWidget);
137
138
139   if (!theWidget) {
140 #ifdef _DEBUG
141     std::cout << "ModuleBase_PageGroupBox::placePageWidget: can not cast page" << std::endl;
142 #endif
143     return;
144   }
145   if (myGroupBoxLayout) {
146     const int kCol = 0;
147     const int kRow = myGroupBoxLayout->count();
148     myGroupBoxLayout->addWidget(theWidget, kRow, kCol);
149     myGroupBoxLayout->setRowStretch(kRow, 0);
150   }
151   else {
152     myCheckGroupLayout->addWidget(theWidget);
153   }
154 }
155
156 QLayout* ModuleBase_WidgetOptionalBox::pageLayout()
157 {
158   return myOptionType == GroupBox ? myGroupBoxLayout : (QLayout*)myCheckBoxLayout;
159 }
160
161 void ModuleBase_WidgetOptionalBox::createControl(const OptionType& theType)
162 {
163   if (theType == GroupBox && !myGroupBox) {
164     // group box: more than one model widget is inside
165     if (myHaveFrame) {
166       myGroupBox = new QGroupBox(this);
167       myGroupBox->setTitle(translate(myGroupTitle));
168       myGroupBox->setVisible(false);
169       myGroupBox->setCheckable(true);
170       myGroupBox->setChecked(getDefaultValue() == "true");
171       myGroupBox->setToolTip(translate(myToolTip));
172
173       myGroupBoxLayout = new QGridLayout(myGroupBox);
174       ModuleBase_Tools::zeroMargins(myGroupBoxLayout);
175       myGroupBox->setLayout(myGroupBoxLayout);
176
177       // default vertical size policy is preferred
178       myMainLayout->addWidget(myGroupBox);
179       connect(myGroupBox, SIGNAL(clicked(bool)), this, SLOT(onPageClicked()));
180     }
181     else {
182       myCheckGroup = new QWidget(this);
183       QVBoxLayout* aLayout = new QVBoxLayout(myCheckGroup);
184       ModuleBase_Tools::zeroMargins(aLayout);
185
186       myCheckGroupBtn = new QCheckBox(translate(myGroupTitle), myCheckGroup);
187       aLayout->addWidget(myCheckGroupBtn);
188
189       myCheckContent = new QWidget(myCheckGroup);
190       myCheckGroupLayout = new QVBoxLayout(myCheckContent);
191       ModuleBase_Tools::zeroMargins(myCheckGroupLayout);
192       aLayout->addWidget(myCheckContent);
193
194       myMainLayout->addWidget(myCheckGroup);
195       connect(myCheckGroupBtn, SIGNAL(toggled(bool)), this, SLOT(onPageClicked()));
196     }
197   }
198   else if (theType == CheckBox && !myCheckBoxFrame) {
199     myCheckBoxFrame = new QFrame(this);
200     myMainLayout->addWidget(myCheckBoxFrame);
201
202     myCheckBoxLayout = new QHBoxLayout(myCheckBoxFrame);
203     ModuleBase_Tools::adjustMargins(myCheckBoxLayout);
204     myCheckBox = new QCheckBox(myCheckBoxFrame);
205     myCheckBox->setChecked(getDefaultValue() == "true");
206     myCheckBoxLayout->addWidget(myCheckBox);
207
208     connect(myCheckBox, SIGNAL(clicked(bool)), this, SLOT(onPageClicked()));
209   }
210 }
211
212 bool ModuleBase_WidgetOptionalBox::storeValueCustom()
213 {
214   DataPtr aData = myFeature->data();
215   AttributeStringPtr aStringAttr = aData->string(attributeID());
216   if (aStringAttr.get())
217     aStringAttr->setValue(getCurrentValue() ? attributeID() : "");
218   else {
219     AttributeBooleanPtr aBoolAtr = aData->boolean(attributeID());
220     aBoolAtr->setValue(getCurrentValue());
221   }
222
223   updateObject(myFeature);
224
225   return true;
226 }
227
228 bool ModuleBase_WidgetOptionalBox::restoreValueCustom()
229 {
230   DataPtr aData = myFeature->data();
231   AttributeStringPtr aStringAttr = aData->string(attributeID());
232   if (aStringAttr.get())
233     setCurrentValue(!aStringAttr->value().empty());
234   else {
235     AttributeBooleanPtr aBoolAtr = aData->boolean(attributeID());
236     setCurrentValue(aBoolAtr->value());
237   }
238   return true;
239 }
240
241 void ModuleBase_WidgetOptionalBox::setOptionType(
242                          const ModuleBase_WidgetOptionalBox::OptionType& theType)
243 {
244   myOptionType = theType;
245
246   bool isGroupBox = myOptionType == GroupBox;
247   if (myCheckBoxFrame)
248     myCheckBoxFrame->setVisible(!isGroupBox);
249   if (myGroupBox)
250     myGroupBox->setVisible(isGroupBox);
251   else if (myCheckContent)
252     myCheckGroup->setVisible(isGroupBox);
253 }
254
255 bool ModuleBase_WidgetOptionalBox::isCheckBoxFilled() const
256 {
257   return myCheckBoxWidget != 0;
258 }
259
260 bool ModuleBase_WidgetOptionalBox::getCurrentValue() const
261 {
262   bool isGroupBox = myOptionType == GroupBox;
263   return isGroupBox ? (myGroupBox? myGroupBox->isChecked() : myCheckGroupBtn->isChecked()) :
264     myCheckBox->isChecked();
265 }
266
267 void ModuleBase_WidgetOptionalBox::setCurrentValue(const bool& theValue)
268 {
269   bool isGroupBox = myOptionType == GroupBox;
270   if (isGroupBox) {
271     if (myGroupBox) {
272       bool isBlocked = myGroupBox->blockSignals(true);
273       myGroupBox->setChecked(theValue);
274       myGroupBox->blockSignals(isBlocked);
275     }
276     else {
277       bool isBlocked = myCheckGroupBtn->blockSignals(true);
278       myCheckGroupBtn->setChecked(theValue);
279       myCheckGroupBtn->blockSignals(isBlocked);
280     }
281   }
282   else {
283     bool isBlocked = myCheckBox->blockSignals(true);
284     myCheckBox->setChecked(theValue);
285     myCheckBox->blockSignals(isBlocked);
286   }
287   updateControlsVisibility();
288 }
289
290 void ModuleBase_WidgetOptionalBox::updateControlsVisibility()
291 {
292   if (myOptionType == GroupBox) {
293     bool aChecked = toEnableWidgets();
294     ModuleBase_Tools::adjustMargins(myGroupBoxLayout);
295
296     QLayout* aLayout = myGroupBoxLayout ? myGroupBoxLayout : (QLayout*)myCheckGroupLayout;
297
298     int aNbSubControls = aLayout->count();
299     for (int i = 0; i < aNbSubControls; i++) {
300       QWidget* aWidget = aLayout->itemAt(i)->widget();
301       if (aWidget)
302         aWidget->setEnabled(aChecked);
303     }
304   }
305   else {
306     myCheckBoxWidget->setEnabled(toEnableWidgets());
307   }
308 }
309
310 bool ModuleBase_WidgetOptionalBox::toEnableWidgets() const
311 {
312   bool aChecked;
313   if (myOptionType == GroupBox)
314     aChecked = myGroupBox ? myGroupBox->isChecked() : myCheckGroupBtn->isChecked();
315   else
316     aChecked = myCheckBox->isChecked();
317
318   if (myEnableOnCheck)
319     return aChecked;
320   else
321     return !aChecked;
322 }