]> SALOME platform Git repositories - modules/shaper.git/blob - src/PartSet/PartSet_BSplineWidget.cpp
Salome HOME
Set scroll area for B-Spline widgets
[modules/shaper.git] / src / PartSet / PartSet_BSplineWidget.cpp
1 // Copyright (C) 2019-2020  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 <PartSet_BSplineWidget.h>
21
22 #include <SketchPlugin_BSpline.h>
23
24 #include <ModuleBase_Tools.h>
25
26 #include <ModelAPI_AttributeDoubleArray.h>
27
28 #include <GeomDataAPI_Point2DArray.h>
29
30 #include <GeomAPI_Pnt2d.h>
31
32 #include <QFormLayout>
33 #include <QGroupBox>
34 #include <QLabel>
35 #include <QVBoxLayout>
36 #include <QScrollArea>
37
38
39 PartSet_BSplineWidget::PartSet_BSplineWidget(
40     QWidget* theParent,
41     const Config_WidgetAPI* theData)
42   : ModuleBase_ModelWidget(theParent, theData)
43 {
44   QVBoxLayout* aMainLayout = new QVBoxLayout(this);
45   aMainLayout->setContentsMargins(0, 0, 0, 0);
46
47   // GroupBox to keep widgets for B-spline poles and weights
48   myPolesGroupBox = new QGroupBox(tr("Poles and weights"), this);
49   aMainLayout->addWidget(myPolesGroupBox);
50
51   QVBoxLayout* aLayout = new QVBoxLayout(myPolesGroupBox);
52   ModuleBase_Tools::adjustMargins(aLayout);
53
54   myScrollArea = new QScrollArea(myPolesGroupBox);
55   myScrollArea->setWidgetResizable(true);
56   myScrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
57   myScrollArea->setFrameStyle(QFrame::NoFrame);
58   aLayout->addWidget(myScrollArea);
59
60   QWidget* aContainer = new QWidget(myScrollArea);
61   QVBoxLayout* aBoxLay = new QVBoxLayout(aContainer);
62   aBoxLay->setContentsMargins(0, 0, 0, 0);
63
64   // layout of GroupBox
65   myPolesWgt = new QWidget(aContainer);
66   QGridLayout* aGroupLayout = new QGridLayout(myPolesWgt);
67   aGroupLayout->setSpacing(4);
68   aGroupLayout->setColumnStretch(1, 1);
69   ModuleBase_Tools::adjustMargins(aGroupLayout);
70
71   restoreValueCustom();
72   aBoxLay->addWidget(myPolesWgt);
73   aBoxLay->addStretch(1);
74   myScrollArea->setWidget(aContainer);
75 }
76
77 void PartSet_BSplineWidget::setFeature(const FeaturePtr& theFeature,
78                                             const bool theToStoreValue,
79                                             const bool isUpdateFlushed)
80 {
81   ModuleBase_ModelWidget::setFeature(theFeature, theToStoreValue, isUpdateFlushed);
82   restoreValueCustom();
83 }
84
85 void PartSet_BSplineWidget::deactivate()
86 {
87   ModuleBase_ModelWidget::deactivate();
88   storeValueCustom();
89 }
90
91
92 QList<QWidget*> PartSet_BSplineWidget::getControls() const
93 {
94   QList<QWidget*> aControls;
95   aControls.append(myScrollArea);
96   return aControls;
97 }
98
99 void PartSet_BSplineWidget::storePolesAndWeights() const
100 {
101   std::shared_ptr<ModelAPI_Data> aData = myFeature->data();
102   AttributeDoubleArrayPtr aWeightsArray = aData->realArray(SketchPlugin_BSpline::WEIGHTS_ID());
103
104   std::list<BSplinePoleWidgets>::const_iterator anIt = myPoles.begin();
105   for (int anIndex = 0; anIt != myPoles.end(); ++anIndex, ++anIt) {
106     aWeightsArray->setValue(anIndex, anIt->myWeight->value());
107   }
108 }
109
110 bool PartSet_BSplineWidget::storeValueCustom()
111 {
112   std::shared_ptr<ModelAPI_Data> aData = myFeature->data();
113   if (!aData || !aData->isValid()) // can be on abort of sketcher element
114     return false;
115
116   AttributeDoubleArrayPtr aWeights = aData->realArray(SketchPlugin_BSpline::WEIGHTS_ID());
117
118   bool isBlocked = blockSignals(true);
119   storePolesAndWeights();
120   ModuleBase_Tools::flushUpdated(myFeature);
121   blockSignals(isBlocked);
122
123   updateObject(myFeature);
124   return true;
125 }
126
127 bool PartSet_BSplineWidget::restoreValueCustom()
128 {
129   if (!myFeature)
130     return false;
131
132   DataPtr aData = myFeature->data();
133
134   AttributePoint2DArrayPtr aPoles = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(
135       aData->attribute(SketchPlugin_BSpline::POLES_ID()));
136   AttributeDoubleArrayPtr aWeights = aData->realArray(SketchPlugin_BSpline::WEIGHTS_ID());
137
138   while (myPoles.size() < aPoles->size())
139     addPoleWidget();
140
141   std::list<BSplinePoleWidgets>::iterator anIt = myPoles.begin();
142   for (int anIndex = 0; anIt != myPoles.end(); ++anIt, ++anIndex) {
143     GeomPnt2dPtr aPoint = aPoles->pnt(anIndex);
144     anIt->myX->setValue(aPoint->x());
145     anIt->myY->setValue(aPoint->y());
146     bool isBlocked = anIt->myWeight->blockSignals(true);
147     anIt->myWeight->setValue(aWeights->value(anIndex));
148     anIt->myWeight->blockSignals(isBlocked);
149   }
150
151   return true;
152 }
153
154 void PartSet_BSplineWidget::addPoleWidget()
155 {
156   QGridLayout* aGroupLay = dynamic_cast<QGridLayout*>(myPolesWgt->layout());
157   ModuleBase_Tools::adjustMargins(aGroupLay);
158
159   int aNbPoles = (int)myPoles.size();
160
161   QString aPoleStr = tr("Pole %1");
162   aPoleStr = aPoleStr.arg(aNbPoles + 1);
163
164   QGroupBox* aPoleGroupBox = new QGroupBox(aPoleStr, myPolesWgt);
165   QFormLayout* aPoleLay = new QFormLayout(aPoleGroupBox);
166   ModuleBase_Tools::adjustMargins(aPoleLay);
167   aPoleLay->setSpacing(2);
168
169   myPoles.push_back(BSplinePoleWidgets());
170   BSplinePoleWidgets& aPoleWidgets = myPoles.back();
171
172   aPoleWidgets.myX = new ModuleBase_LabelValue(aPoleGroupBox, tr("X"));
173   aPoleLay->addRow(aPoleWidgets.myX);
174   aPoleWidgets.myY = new ModuleBase_LabelValue(aPoleGroupBox, tr("Y"));
175   aPoleLay->addRow(aPoleWidgets.myY);
176   aPoleWidgets.myWeight = new ModuleBase_ParamSpinBox(aPoleGroupBox);
177   aPoleWidgets.myWeight->setMinimum(0.0);
178   aPoleLay->addRow(tr("Weight") + " : ", aPoleWidgets.myWeight);
179
180   aGroupLay->addWidget(aPoleGroupBox, aNbPoles, 1);
181
182   // we should listen textChanged signal as valueChanged do not send when text is modified
183   connect(aPoleWidgets.myWeight, SIGNAL(textChanged(const QString&)),
184     this, SIGNAL(valuesChanged()));
185 }