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