Salome HOME
Issue #1368: Creation of a Qt panel. Code improvement.
[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
12 #include <ModuleBase_Operation.h>
13 #include <ModuleBase_OperationDescription.h>
14 #include <ModuleBase_WidgetEditor.h>
15 #include <ModuleBase_WidgetSwitch.h>
16 #include <ModuleBase_WidgetShapeSelector.h>
17 #include <ModuleBase_WidgetDoubleValue.h>
18 #include <ModuleBase_WidgetIntValue.h>
19 #include <ModuleBase_WidgetBoolValue.h>
20 #include <ModuleBase_WidgetFileSelector.h>
21 #include <ModuleBase_WidgetChoice.h>
22 #include <ModuleBase_IWorkshop.h>
23 #include <ModuleBase_IModule.h>
24 #include <ModuleBase_Tools.h>
25 #include <ModuleBase_WidgetLineEdit.h>
26 #include <ModuleBase_WidgetMultiSelector.h>
27 #include <ModuleBase_WidgetLabel.h>
28 #include <ModuleBase_WidgetErrorLabel.h>
29 #include <ModuleBase_WidgetToolbox.h>
30 #include <ModuleBase_PageBase.h>
31 #include <ModuleBase_PageGroupBox.h>
32 #include <ModuleBase_WidgetCheckGroupBox.h>
33 #include <ModuleBase_PageWidget.h>
34 #include <ModuleBase_WidgetExprEditor.h>
35 #include <ModuleBase_WidgetCreatorFactory.h>
36
37 #include <ModelAPI_Validator.h>
38 #include <ModelAPI_Session.h>
39
40 #include <Config_Keywords.h>
41 #include <Config_WidgetAPI.h>
42
43 #include <QWidget>
44 #include <QHBoxLayout>
45 #include <QGridLayout>
46 #include <QSpinBox>
47 #include <QMetaProperty>
48 #include <QLabel>
49 #include <QPixmap>
50 #include <QGroupBox>
51 #include <QToolBox>
52
53 #ifdef _DEBUG
54 #include <QDebug>
55 #endif
56
57 #include <cfloat>
58 #include <climits>
59
60 ModuleBase_WidgetFactory::ModuleBase_WidgetFactory(const std::string& theXmlRepresentation,
61                                                    ModuleBase_IWorkshop* theWorkshop)
62     : myWorkshop(theWorkshop)
63 {
64   myWidgetApi = new Config_WidgetAPI(theXmlRepresentation);
65 }
66
67 ModuleBase_WidgetFactory::~ModuleBase_WidgetFactory()
68 {
69   delete myWidgetApi;
70 }
71
72 void ModuleBase_WidgetFactory::createWidget(ModuleBase_PageBase* thePage)
73 {
74   if (!myWidgetApi->toChildWidget())
75     return;
76
77   do {  //Iterate over each node
78     std::string aWdgType = myWidgetApi->widgetType();
79     // Create PageGroup TODO: extract
80     if (myWidgetApi->isGroupBoxWidget() ||
81         ModuleBase_WidgetCreatorFactory::get()->hasPageWidget(aWdgType)) {
82
83       //if current widget is groupbox (container) process it's children recursively
84       ModuleBase_PageBase* aPage = createPageByType(aWdgType, thePage->pageWidget());
85
86       createWidget(aPage);
87       thePage->addPageWidget(aPage);
88     } else {
89       // Create a ModelWidget
90       ModuleBase_ModelWidget* aWidget = createWidgetByType(aWdgType, thePage->pageWidget());
91       if (aWidget) {
92         if (!myWidgetApi->getBooleanAttribute(ATTR_INTERNAL, false)) {
93           thePage->addModelWidget(aWidget);
94         } else {
95           aWidget->setVisible(false);
96         }
97       }
98       // Create PagedContainer TODO: extract
99       if (myWidgetApi->isPagedWidget()) {
100         //If current widget is toolbox or switch-casebox then fetch all
101         //it's pages recursively and setup into the widget.
102         myWidgetApi->toChildWidget();
103         do {
104           QString aPageName = qs(myWidgetApi->getProperty(CONTAINER_PAGE_NAME));
105           QString aCaseId = qs(myWidgetApi->getProperty(_ID));
106           ModuleBase_PageBase* aPage = new ModuleBase_PageWidget(aWidget);
107           createWidget(aPage);
108           if (aWdgType == WDG_SWITCH || aWdgType == WDG_TOOLBOX) {
109             ModuleBase_PagedContainer* aContainer = qobject_cast<ModuleBase_PagedContainer*>(aWidget);
110
111             QString anIconPath = qs( myWidgetApi->getProperty( CONTAINER_PAGE_ICON ) );
112             QPixmap anIcon( anIconPath );
113             aContainer->addPage( aPage, aPageName, aCaseId, anIcon );
114           }
115         } while (myWidgetApi->toNextWidget());
116       }
117     }
118   } while (myWidgetApi->toNextWidget());
119
120   thePage->alignToTop();
121 }
122
123 void ModuleBase_WidgetFactory::createWidget(ModuleBase_PageBase* thePage,
124                                             const std::string& theWidgetId)
125 {
126   bool aFound = false;
127   moveToWidgetId(theWidgetId, aFound);
128   if (aFound) {
129     std::string aWdgType = myWidgetApi->widgetType();
130
131     // Create a ModelWidget
132     ModuleBase_ModelWidget* aWidget = createWidgetByType(aWdgType, thePage->pageWidget());
133     if (aWidget) {
134       if (!myWidgetApi->getBooleanAttribute(ATTR_INTERNAL, false)) {
135         thePage->addModelWidget(aWidget);
136       }
137       else {
138         aWidget->setVisible(false);
139       }
140     }
141   }
142   thePage->alignToTop();
143 }
144
145 void ModuleBase_WidgetFactory::getAttributeTitle(const std::string& theAttributeId,
146                                                  std::string& theTitle)
147 {
148   bool aFound = false;
149   moveToWidgetId(theAttributeId, aFound);
150   if (aFound) {
151     theTitle = QString::fromStdString(myWidgetApi->widgetLabel()).toStdString().c_str();
152     if (theTitle.empty())
153       theTitle = QString::fromStdString(myWidgetApi->getProperty(CONTAINER_PAGE_NAME)).toStdString().c_str();
154   }
155 }
156
157 void ModuleBase_WidgetFactory::getGreedAttribute(std::string& theAttributeId)
158 {
159   if (!theAttributeId.empty())
160     return;
161
162   if (!myWidgetApi->toChildWidget())
163     return;
164
165   do {  //Iterate over each node
166     std::string aWdgType = myWidgetApi->widgetType();
167     // Find title under PageGroup
168     if (myWidgetApi->isGroupBoxWidget() ||
169       ModuleBase_WidgetCreatorFactory::get()->hasPageWidget(aWdgType)) {
170       getGreedAttribute(theAttributeId);
171     }
172     else {
173       // Find title here
174       std::string anAttributeId = myWidgetApi->widgetId();
175       if (myWidgetApi->getBooleanAttribute(ATTR_GREED, false))
176         theAttributeId = anAttributeId;
177       if (theAttributeId.empty() && myWidgetApi->isPagedWidget()) {
178         //If current widget is toolbox or switch-casebox then fetch all
179         //it's pages recursively and setup into the widget.
180         myWidgetApi->toChildWidget();
181         do {
182           getGreedAttribute(theAttributeId);
183         } while (theAttributeId.empty() && myWidgetApi->toNextWidget());
184       }
185     }
186   } while (theAttributeId.empty() && myWidgetApi->toNextWidget());
187 }
188
189 void ModuleBase_WidgetFactory::moveToWidgetId(const std::string& theWidgetId, bool& theFound)
190 {
191   if (theFound)
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       moveToWidgetId(theWidgetId, theFound);
203     }
204     else {
205       // Find title here
206       std::string anAttributeId = myWidgetApi->widgetId();
207       theFound = anAttributeId == theWidgetId;
208       if (!theFound && myWidgetApi->isPagedWidget()) {
209         //If current widget is toolbox or switch-casebox then fetch all
210         //it's pages recursively and setup into the widget.
211         myWidgetApi->toChildWidget();
212         do {
213           moveToWidgetId(theWidgetId, theFound);
214         } while (!theFound && myWidgetApi->toNextWidget());
215       }
216     }
217   } while (!theFound && myWidgetApi->toNextWidget());
218 }
219
220 ModuleBase_PageBase* ModuleBase_WidgetFactory::createPageByType(const std::string& theType,
221                                                                 QWidget* theParent)
222 {
223   ModuleBase_PageBase* aResult = NULL;
224
225   if (theType == WDG_GROUP) {
226     QString aGroupName = qs(myWidgetApi->getProperty(CONTAINER_PAGE_NAME));
227     ModuleBase_PageGroupBox* aPage = new ModuleBase_PageGroupBox(theParent);
228     aPage->setTitle(aGroupName);
229     aResult = aPage;
230   }
231   else if (theType == WDG_CHECK_GROUP) {
232     QString aGroupName = qs(myWidgetApi->getProperty(CONTAINER_PAGE_NAME));
233     ModuleBase_WidgetCheckGroupBox* aPage = new ModuleBase_WidgetCheckGroupBox(theParent,
234                                                                 myWidgetApi);
235     aPage->setTitle(aGroupName);
236     aResult = aPage;
237   }
238   if (!aResult)
239     aResult = ModuleBase_WidgetCreatorFactory::get()->createPageByType(theType, theParent,
240                                                                        myWidgetApi);
241
242   ModuleBase_ModelWidget* aWidget = dynamic_cast<ModuleBase_ModelWidget*>(aResult);
243   if (aWidget)
244     myModelWidgets.append(aWidget);
245
246   return aResult;
247 }
248
249 ModuleBase_ModelWidget* ModuleBase_WidgetFactory::createWidgetByType(const std::string& theType,
250                                                                      QWidget* theParent)
251 {
252   ModuleBase_ModelWidget* result = NULL;
253
254   if (theType == WDG_INFO) {
255     result = new ModuleBase_WidgetLabel(theParent, myWidgetApi);
256   } else if (theType == WDG_ERRORINFO) {
257     result = new ModuleBase_WidgetErrorLabel(theParent, myWidgetApi);
258   } else if (theType == WDG_DOUBLEVALUE) {
259     result = new ModuleBase_WidgetDoubleValue(theParent, myWidgetApi);
260   } else if (theType == WDG_INTEGERVALUE) {
261     result = new ModuleBase_WidgetIntValue(theParent, myWidgetApi);
262   } else if (theType == WDG_SHAPE_SELECTOR) {
263     result = new ModuleBase_WidgetShapeSelector(theParent, myWorkshop, myWidgetApi);
264   } else if (theType == WDG_BOOLVALUE) {
265     result = new ModuleBase_WidgetBoolValue(theParent, myWidgetApi);
266   //} else if (theType == WDG_DOUBLEVALUE_EDITOR) {
267   //  result = new ModuleBase_WidgetEditor(theParent, myWidgetApi);
268   } else if (theType == WDG_FILE_SELECTOR) {
269     result = new ModuleBase_WidgetFileSelector(theParent, myWidgetApi);
270   } else if (theType == WDG_CHOICE) {
271     result = new ModuleBase_WidgetChoice(theParent, myWidgetApi);
272   } else if (theType == WDG_STRINGVALUE) {
273     std::string aPlaceHolder = myWidgetApi->getProperty( WDG_PLACE_HOLDER );
274     result = new ModuleBase_WidgetLineEdit( theParent, myWidgetApi, aPlaceHolder );
275   } else if (theType == WDG_EXPR_EDITOR) {
276     std::string aPlaceHolder = myWidgetApi->getProperty( WDG_PLACE_HOLDER );
277     result = new ModuleBase_WidgetExprEditor( theParent, myWidgetApi, aPlaceHolder );
278   } else if (theType == WDG_MULTISELECTOR) {
279     result = new ModuleBase_WidgetMultiSelector(theParent, myWorkshop, myWidgetApi);
280   } else if (theType == WDG_TOOLBOX) {
281     result = new ModuleBase_WidgetToolbox(theParent, myWidgetApi);
282   } else if (theType == WDG_SWITCH) {
283     result = new ModuleBase_WidgetSwitch(theParent, myWidgetApi);
284   } else if (theType == WDG_TOOLBOX_BOX || theType == WDG_SWITCH_CASE ||
285              theType == NODE_VALIDATOR) {
286     // Do nothing for "box" and "case"
287     result = NULL;
288   } else {
289     result = myWorkshop->module()->createWidgetByType(theType, theParent, myWidgetApi);
290     if (!result)
291       result = ModuleBase_WidgetCreatorFactory::get()->createWidgetByType(theType, theParent,
292                                                               myWidgetApi, myWorkshop);
293     #ifdef _DEBUG
294     if (!result) {
295       qDebug("ModuleBase_WidgetFactory::fillWidget: find bad widget type %s", theType.c_str());
296     }
297     #endif
298   }
299   if (result)
300     myModelWidgets.append(result);
301   return result;
302 }
303
304 QString ModuleBase_WidgetFactory::qs(const std::string& theStdString)
305 {
306   return QString::fromStdString(theStdString);
307 }
308