Salome HOME
c58af6149797a657ad03b16cde0c3232dd55d605
[modules/shaper.git] / src / ModuleBase / ModuleBase_WidgetFactory.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 /*
4  * ModuleBase_WidgetFactory.cpp
5  *
6  *  Created on: Apr 3, 2014
7  *      Author: sbh
8  */
9
10 #include <ModuleBase_WidgetFactory.h>
11 #include <ModuleBase_IconFactory.h>
12
13 #include <ModuleBase_Operation.h>
14 #include <ModuleBase_OperationDescription.h>
15 #include <ModuleBase_WidgetEditor.h>
16 #include <ModuleBase_WidgetSwitch.h>
17 #include <ModuleBase_WidgetShapeSelector.h>
18 #include <ModuleBase_WidgetFeatureSelector.h>
19 #include <ModuleBase_WidgetDoubleValue.h>
20 #include <ModuleBase_WidgetLabelValue.h>
21 #include <ModuleBase_WidgetIntValue.h>
22 #include <ModuleBase_WidgetBoolValue.h>
23 #include <ModuleBase_WidgetFileSelector.h>
24 #include <ModuleBase_WidgetChoice.h>
25 #include <ModuleBase_IWorkshop.h>
26 #include <ModuleBase_IModule.h>
27 #include <ModuleBase_Tools.h>
28 #include <ModuleBase_WidgetLineEdit.h>
29 #include <ModuleBase_WidgetMultiSelector.h>
30 #include <ModuleBase_WidgetConcealedObjects.h>
31 #include <ModuleBase_WidgetLabel.h>
32 #include <ModuleBase_WidgetToolbox.h>
33 #include <ModuleBase_PageBase.h>
34 #include <ModuleBase_PageGroupBox.h>
35 #include <ModuleBase_WidgetOptionalBox.h>
36 #include <ModuleBase_PageWidget.h>
37 #include <ModuleBase_WidgetExprEditor.h>
38 #include <ModuleBase_WidgetCreatorFactory.h>
39 #include <ModuleBase_WidgetAction.h>
40
41 #include <ModelAPI_Validator.h>
42 #include <ModelAPI_Session.h>
43
44 #include <Config_Keywords.h>
45 #include <Config_WidgetAPI.h>
46
47 #include <QWidget>
48 #include <QHBoxLayout>
49 #include <QGridLayout>
50 #include <QSpinBox>
51 #include <QMetaProperty>
52 #include <QLabel>
53 #include <QPixmap>
54 #include <QGroupBox>
55 #include <QToolBox>
56
57 #ifdef _DEBUG
58 #include <QDebug>
59 #endif
60
61 #include <cfloat>
62 #include <climits>
63
64 ModuleBase_WidgetFactory::ModuleBase_WidgetFactory(const std::string& theXmlRepresentation,
65                                                    ModuleBase_IWorkshop* theWorkshop)
66     : myWorkshop(theWorkshop)
67 {
68   myWidgetApi = new Config_WidgetAPI(theXmlRepresentation);
69 }
70
71 ModuleBase_WidgetFactory::~ModuleBase_WidgetFactory()
72 {
73   delete myWidgetApi;
74 }
75
76 void ModuleBase_WidgetFactory::createWidget(ModuleBase_PageBase* thePage, bool alignToTop)
77 {
78   std::string aWType = myWidgetApi->widgetType();
79   if (aWType == NODE_FEATURE) {
80     // if XML definition of the feature contains the next key, the widgets should not be created,
81     // but a specific panel should be made. However, to provide persistent of the panel values,
82     // we need to get into the panel the feature of the operation. As a result this panel should
83     // be created after the feature creating(create operation). The method setPanel() of this
84     // class is used for this. Here, we just return to avoid the widgets creation.
85     std::string aPanelName = myWidgetApi->getProperty(PROPERTY_PANEL_ID);
86     if (!aPanelName.empty())
87       return;
88   }
89
90   if (!myWidgetApi->toChildWidget())
91     return;
92
93   do {  //Iterate over each node
94     std::string aWdgType = myWidgetApi->widgetType();
95     // Create PageGroup TODO: extract
96     if (myWidgetApi->isGroupBoxWidget() ||
97         ModuleBase_WidgetCreatorFactory::get()->hasPageWidget(aWdgType)) {
98
99       //if current widget is groupbox (container) process it's children recursively
100       ModuleBase_PageBase* aPage = createPageByType(aWdgType, thePage->pageWidget());
101
102       createWidget(aPage);
103       thePage->addPageWidget(aPage);
104     } else {
105       // Create a ModelWidget
106       ModuleBase_ModelWidget* aWidget = createWidgetByType(aWdgType, thePage->pageWidget());
107       if (aWidget) {
108         if (!myWidgetApi->getBooleanAttribute(ATTR_INTERNAL, false)) {
109           thePage->addModelWidget(aWidget);
110         } else {
111           aWidget->setVisible(false);
112         }
113       }
114       // Create PagedContainer TODO: extract
115       if (myWidgetApi->isPagedWidget()) {
116         //If current widget is toolbox or switch-casebox then fetch all
117         //it's pages recursively and setup into the widget.
118         if (myWidgetApi->toChildWidget()) {
119           do {
120             QString aPageName = qs(myWidgetApi->getProperty(CONTAINER_PAGE_NAME));
121             QString aCaseId = qs(myWidgetApi->getProperty(_ID));
122             ModuleBase_PageBase* aPage = new ModuleBase_PageWidget(aWidget);
123             createWidget(aPage);
124             if (aWdgType == WDG_SWITCH || aWdgType == WDG_TOOLBOX) {
125               ModuleBase_PagedContainer* aContainer =
126                 qobject_cast<ModuleBase_PagedContainer*>(aWidget);
127
128               QString anIconPath = qs( myWidgetApi->getProperty( CONTAINER_PAGE_ICON ) );
129               QPixmap anIcon = ModuleBase_IconFactory::loadPixmap( anIconPath );
130               aContainer->addPage( aPage, aPageName, aCaseId, anIcon );
131             }
132           } while (myWidgetApi->toNextWidget());
133         }
134       }
135     }
136   } while (myWidgetApi->toNextWidget());
137
138   if (alignToTop)
139     thePage->alignToTop();
140 }
141
142 void ModuleBase_WidgetFactory::createPanel(ModuleBase_PageBase* thePage,
143                                            const FeaturePtr& theFeature)
144 {
145   std::string aPanelName = myWidgetApi->getProperty(PROPERTY_PANEL_ID);
146   if (!aPanelName.empty() && ModuleBase_WidgetCreatorFactory::get()->hasPanelWidget(aPanelName)) {
147     QWidget* aPanel = ModuleBase_WidgetCreatorFactory::get()->createPanelByType(aPanelName,
148                                                                thePage->pageWidget(), theFeature);
149     thePage->addWidget(aPanel);
150     thePage->alignToTop();
151   }
152 }
153
154 void ModuleBase_WidgetFactory::createWidget(ModuleBase_PageBase* thePage,
155                                             const std::string& theWidgetId)
156 {
157   bool aFound = false;
158   moveToWidgetId(theWidgetId, aFound);
159   if (aFound) {
160     std::string aWdgType = myWidgetApi->widgetType();
161
162     // Create a ModelWidget
163     ModuleBase_ModelWidget* aWidget = createWidgetByType(aWdgType, thePage->pageWidget());
164     if (aWidget) {
165       if (!myWidgetApi->getBooleanAttribute(ATTR_INTERNAL, false)) {
166         thePage->addModelWidget(aWidget);
167       }
168       else {
169         aWidget->setVisible(false);
170       }
171     }
172   }
173   thePage->alignToTop();
174 }
175
176 void ModuleBase_WidgetFactory::getAttributeTitle(const std::string& theAttributeId,
177                                                  std::string& theTitle)
178 {
179   bool aFound = false;
180   moveToWidgetId(theAttributeId, aFound);
181   if (aFound) {
182     theTitle = QString::fromStdString(myWidgetApi->widgetLabel()).toStdString().c_str();
183     if (theTitle.empty())
184       theTitle =
185       QString::fromStdString(myWidgetApi->getProperty(CONTAINER_PAGE_NAME)).toStdString().c_str();
186   }
187 }
188
189 void ModuleBase_WidgetFactory::getGreedAttribute(std::string& theAttributeId)
190 {
191   if (!theAttributeId.empty())
192     return;
193
194   if (!myWidgetApi->toChildWidget())
195     return;
196
197   do {  //Iterate over each node
198     std::string aWdgType = myWidgetApi->widgetType();
199     // Find title under PageGroup
200     if (myWidgetApi->isGroupBoxWidget() ||
201       ModuleBase_WidgetCreatorFactory::get()->hasPageWidget(aWdgType)) {
202       getGreedAttribute(theAttributeId);
203     }
204     else {
205       // Find title here
206       std::string anAttributeId = myWidgetApi->widgetId();
207       if (myWidgetApi->getBooleanAttribute(ATTR_GREED, false))
208         theAttributeId = anAttributeId;
209       if (theAttributeId.empty() && myWidgetApi->isPagedWidget()) {
210         //If current widget is toolbox or switch-casebox then fetch all
211         //it's pages recursively and setup into the widget.
212         if (myWidgetApi->toChildWidget()) {
213           do {
214             getGreedAttribute(theAttributeId);
215           } while (theAttributeId.empty() && myWidgetApi->toNextWidget());
216         }
217       }
218     }
219   } while (theAttributeId.empty() && myWidgetApi->toNextWidget());
220 }
221
222 void ModuleBase_WidgetFactory::moveToWidgetId(const std::string& theWidgetId, bool& theFound)
223 {
224   if (theFound)
225     return;
226
227   if (!myWidgetApi->toChildWidget())
228     return;
229
230   do {  //Iterate over each node
231     std::string aWdgType = myWidgetApi->widgetType();
232     // Find title under PageGroup
233     if (myWidgetApi->isGroupBoxWidget() ||
234       ModuleBase_WidgetCreatorFactory::get()->hasPageWidget(aWdgType)) {
235       moveToWidgetId(theWidgetId, theFound);
236     }
237     else {
238       // Find title here
239       std::string anAttributeId = myWidgetApi->widgetId();
240       theFound = anAttributeId == theWidgetId;
241       if (!theFound && myWidgetApi->isPagedWidget()) {
242         //If current widget is toolbox or switch-casebox then fetch all
243         //it's pages recursively and setup into the widget.
244         if (myWidgetApi->toChildWidget()) {
245           do {
246             moveToWidgetId(theWidgetId, theFound);
247           } while (!theFound && myWidgetApi->toNextWidget());
248         }
249       }
250     }
251   } while (!theFound && myWidgetApi->toNextWidget());
252 }
253
254 ModuleBase_PageBase* ModuleBase_WidgetFactory::createPageByType(const std::string& theType,
255                                                                 QWidget* theParent)
256 {
257   ModuleBase_PageBase* aResult = NULL;
258
259   if (theType == WDG_GROUP) {
260     QString aGroupName = qs(myWidgetApi->getProperty(CONTAINER_PAGE_NAME));
261     ModuleBase_PageGroupBox* aPage = new ModuleBase_PageGroupBox(theParent);
262     aPage->setTitle(aGroupName);
263     aResult = aPage;
264   }
265   else if (theType == WDG_OPTIONALBOX) {
266     ModuleBase_WidgetOptionalBox* aPage = new ModuleBase_WidgetOptionalBox(theParent,
267                                                                 myWidgetApi);
268     aResult = aPage;
269   }
270   if (!aResult)
271     aResult = ModuleBase_WidgetCreatorFactory::get()->createPageByType(theType, theParent,
272                                                                        myWidgetApi);
273
274   ModuleBase_ModelWidget* aWidget = dynamic_cast<ModuleBase_ModelWidget*>(aResult);
275   if (aWidget)
276     myModelWidgets.append(aWidget);
277
278   return aResult;
279 }
280
281 ModuleBase_ModelWidget* ModuleBase_WidgetFactory::createWidgetByType(const std::string& theType,
282                                                                      QWidget* theParent)
283 {
284   ModuleBase_ModelWidget* result = NULL;
285
286   if (theType == WDG_INFO) {
287     result = new ModuleBase_WidgetLabel(theParent, myWidgetApi);
288   } else if (theType == WDG_DOUBLEVALUE) {
289     result = new ModuleBase_WidgetDoubleValue(theParent, myWidgetApi);
290   } else if (theType == WDG_DOUBLEVALUELABEL) {
291     result = new ModuleBase_WidgetLabelValue(theParent, myWidgetApi);
292   } else if (theType == WDG_INTEGERVALUE) {
293     result = new ModuleBase_WidgetIntValue(theParent, myWidgetApi);
294   } else if (theType == WDG_SHAPE_SELECTOR) {
295     result = new ModuleBase_WidgetShapeSelector(theParent, myWorkshop, myWidgetApi);
296   } else if (theType == WDG_FEATURE_SELECTOR) {
297     result = new ModuleBase_WidgetFeatureSelector(theParent, myWorkshop, myWidgetApi);
298   } else if (theType == WDG_BOOLVALUE) {
299     result = new ModuleBase_WidgetBoolValue(theParent, myWidgetApi);
300   //} else if (theType == WDG_DOUBLEVALUE_EDITOR) {
301   //  result = new ModuleBase_WidgetEditor(theParent, myWidgetApi);
302   } else if (theType == WDG_FILE_SELECTOR) {
303     result = new ModuleBase_WidgetFileSelector(theParent, myWidgetApi);
304   } else if (theType == WDG_CHOICE) {
305     result = new ModuleBase_WidgetChoice(theParent, myWidgetApi);
306   } else if (theType == WDG_STRINGVALUE) {
307     std::string aPlaceHolder = myWidgetApi->getProperty( WDG_PLACE_HOLDER );
308     result = new ModuleBase_WidgetLineEdit( theParent, myWidgetApi, aPlaceHolder );
309   } else if (theType == WDG_EXPR_EDITOR) {
310     std::string aPlaceHolder = myWidgetApi->getProperty( WDG_PLACE_HOLDER );
311     result = new ModuleBase_WidgetExprEditor( theParent, myWidgetApi, aPlaceHolder );
312   } else if (theType == WDG_MULTISELECTOR) {
313     result = new ModuleBase_WidgetMultiSelector(theParent, myWorkshop, myWidgetApi);
314   } else if (theType == WDG_CONCEALED_OBJECTS_VIEW) {
315     result = new ModuleBase_WidgetConcealedObjects(theParent, myWidgetApi);
316   } else if (theType == WDG_TOOLBOX) {
317     result = new ModuleBase_WidgetToolbox(theParent, myWidgetApi);
318   } else if (theType == WDG_SWITCH) {
319     result = new ModuleBase_WidgetSwitch(theParent, myWidgetApi);
320   } else if (theType == WDG_TOOLBOX_BOX || theType == WDG_SWITCH_CASE ||
321              theType == NODE_VALIDATOR) {
322     // Do nothing for "box" and "case"
323     result = NULL;
324   } else if (theType == WDG_ACTION) {
325     result = new ModuleBase_WidgetAction(theParent, myWidgetApi);
326   } else {
327     result = myWorkshop->module()->createWidgetByType(theType, theParent, myWidgetApi);
328     if (!result)
329       result = ModuleBase_WidgetCreatorFactory::get()->createWidgetByType(theType, theParent,
330                                                               myWidgetApi, myWorkshop);
331     #ifdef _DEBUG
332     if (!result) {
333       qDebug("ModuleBase_WidgetFactory::fillWidget: find bad widget type %s", theType.c_str());
334     }
335     #endif
336   }
337   if (result)
338     myModelWidgets.append(result);
339   return result;
340 }
341
342 QString ModuleBase_WidgetFactory::qs(const std::string& theStdString)
343 {
344   return QString::fromStdString(theStdString);
345 }
346