1 # Copyright (C) 2009-2011 EDF R&D
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.
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.
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
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
27 from PyQt4 import QtCore, QtGui
32 from salome.kernel.studyedit import getStudyEditor
33 from salome.kernel.parametric import study_exchange_vars
35 # Get SALOME PyQt interface
37 sgPyQt = SalomePyQt.SalomePyQt()
39 from salome.kernel.logger import Logger
40 from salome.kernel import termcolor
41 logger = Logger("GENERICSOLVERGUI", color = termcolor.RED_FG)
42 logger.setLevel(logging.INFO)
46 VARS_ICON = "icon_variables.png"
47 SOLVER_ENGINE_NAME = "DEVIATION"
49 ################################################
51 # Used to store actions, menus, toolbars, etc...
52 ################################################
56 MODULE_NAME = "GENERICSOLVER"
58 MODULE_PIXMAP = "GENERICSOLVER_small.png"
63 # menus/toolbars/actions IDs
64 GENERICSOLVER_MENU_ID = 90
74 DEFAULT_CASE_NAME = "Case"
78 # create top-level menu
79 mid = sgPyQt.createMenu( "Genericsolver", -1, GUIcontext.GENERICSOLVER_MENU_ID,
80 sgPyQt.defaultMenuGroup() )
82 tid = sgPyQt.createTool( "Genericsolver" )
83 # create actions and fill menu and toolbar with actions
84 a = sgPyQt.createAction( GUIcontext.CREATE_CASE_ID, "Create case", "Create case",
85 "Create a new case", "CaseGENERICSOLVER.png" )
86 sgPyQt.createMenu( a, mid )
87 sgPyQt.createTool( a, tid )
88 a = sgPyQt.createSeparator()
89 sgPyQt.createMenu( a, mid )
90 ag = sgPyQt.createActionGroup( GUIcontext.OPTIONS_ID )
91 ag.setText( "Creation mode" )
92 ag.setUsesDropDown(True)
93 a = sgPyQt.createAction( GUIcontext.OPTION_1_ID, "Default name", "Default name",
94 "Use default name for the objects" )
95 a.setCheckable( True )
97 a = sgPyQt.createAction( GUIcontext.OPTION_2_ID, "Generate name", "Generate name",
98 "Generate name for the objects" )
99 a.setCheckable( True )
101 a = sgPyQt.createAction( GUIcontext.OPTION_3_ID, "Ask name", "Ask name",
102 "Request object name from the user" )
103 a.setCheckable( True )
105 sgPyQt.createMenu( ag, mid )
106 sgPyQt.createTool( ag, tid )
107 default_mode = sgPyQt.integerSetting( "GENERICSOLVER", "creation_mode", 0 )
108 sgPyQt.action( GUIcontext.OPTION_1_ID + default_mode ).setChecked( True )
109 # the following action are used in context popup
110 a = sgPyQt.createAction( GUIcontext.DELETE_ALL_ID, "Delete all", "Delete all",
111 "Delete all objects" )
112 a = sgPyQt.createAction( GUIcontext.SET_VALUE_ID, "Set value", "Set Value",
113 "Set a new value to variable" )
114 a = sgPyQt.createAction( GUIcontext.SOLVER_ID, "Run Solver", "Run Solver",
115 "Run Solver on selected case", "ExecGENERICSOLVER.png" )
117 ################################################
119 ################################################
121 # study-to-context map
122 __study2context__ = {}
124 __current_context__ = None
128 ################################################
130 ################################################
133 # get active study ID
136 return sgPyQt.getStudyId()
142 studyId = getStudyId()
143 study = salome.myStudyManager.GetStudyByID( studyId )
147 # returns True if object has children
149 def hasChildren( sobj ):
152 iter = study.NewChildIterator( sobj )
154 name = iter.Value().GetName()
163 # get current GUI context
166 global __current_context__
167 return __current_context__
170 # set and return current GUI context
171 # study ID is passed as parameter
173 def setContext( studyID ):
174 global __study2context__, __current_context__
175 if not __study2context__.has_key(studyID):
176 __study2context__[studyID] = GUIcontext()
178 __current_context__ = __study2context__[studyID]
179 return __current_context__
181 ################################################
183 ################################################
185 # called when module is initialized
186 # perform initialization actions
188 logger.debug("GENERICSOLVERGUI.initialize() : study : %d" % getStudyId())
189 # set default preferences values
190 if not sgPyQt.hasSetting( "GENERICSOLVER", "def_case_name"):
191 sgPyQt.addSetting( "GENERICSOLVER", "def_case_name", GUIcontext.DEFAULT_CASE_NAME )
192 if not sgPyQt.hasSetting( "GENERICSOLVER", "creation_mode"):
193 sgPyQt.addSetting( "GENERICSOLVER", "creation_mode", 0 )
196 # called when module is initialized
197 # return map of popup windows to be used by the module
199 logger.debug("GENERICSOLVERGUI.windows() : study : %d" % getStudyId())
201 wm[SalomePyQt.WT_ObjectBrowser] = QtCore.Qt.LeftDockWidgetArea
202 wm[SalomePyQt.WT_PyConsole] = QtCore.Qt.BottomDockWidgetArea
205 # called when module is initialized
206 # return list of 2d/3d views to be used ny the module
208 logger.debug("GENERICSOLVERGUI.views() : study : %d" % getStudyId())
211 # called when module is initialized
212 # export module's preferences
213 def createPreferences():
214 logger.debug("GENERICSOLVERGUI.createPreferences() : study : %d" % getStudyId())
215 gid = sgPyQt.addPreference( "General" )
216 gid = sgPyQt.addPreference( "Object creation", gid )
217 pid = sgPyQt.addPreference( "Default case name", gid, SalomePyQt.PT_String,
218 "GENERICSOLVER", "def_case_name" )
219 pid = sgPyQt.addPreference( "Default creation mode", gid, SalomePyQt.PT_Selector,
220 "GENERICSOLVER", "creation_mode" )
221 strings = QStringList()
222 strings.append( "Default name" )
223 strings.append( "Generate name" )
224 strings.append( "Ask name" )
226 indexes.append( QVariant(0) )
227 indexes.append( QVariant(1) )
228 indexes.append( QVariant(2) )
229 sgPyQt.setPreferenceProperty( pid, "strings", QVariant( strings ) )
230 sgPyQt.setPreferenceProperty( pid, "indexes", QVariant( indexes ) )
233 # called when module is activated
234 # returns True if activating is successfull and False otherwise
236 logger.debug("GENERICSOLVERGUI.activate() : study : %d" % getStudyId())
237 ctx = setContext( getStudyId() )
240 # called when module is deactivated
242 logger.debug("GENERICSOLVERGUI.deactivate() : study : %d" % getStudyId())
245 # called when active study is changed
246 # active study ID is passed as parameter
247 def activeStudyChanged( studyID ):
248 logger.debug("GENERICSOLVERGUI.activeStudyChanged(): study : %d" % studyID)
249 ctx = setContext( getStudyId() )
252 # called when popup menu is invoked
253 # popup menu and menu context are passed as parameters
254 def createPopupMenu( popup, context ):
255 logger.debug("GENERICSOLVERGUI.createPopupMenu(): context = %s" % context)
256 ed = getStudyEditor()
257 ctx = setContext(ed.studyId)
258 if salome.sg.SelectedCount() == 1: # one object is selected
259 typeId = ed.getTypeId(ed.study.FindObjectID(salome.sg.getSelected(0)))
260 if typeId == GUIcontext.MODULE_ID:
262 popup.addAction( sgPyQt.action( GUIcontext.DELETE_ALL_ID ) )
263 elif typeId == GUIcontext.CASE_ID:
265 popup.addAction( sgPyQt.action( GUIcontext.SOLVER_ID ) )
266 elif typeId == GUIcontext.VARIABLE_ID:
268 popup.addAction( sgPyQt.action( GUIcontext.SET_VALUE_ID ) )
270 # called when GUI action is activated
271 # action ID is passed as parameter
272 def OnGUIEvent( commandID ):
273 logger.debug("GENERICSOLVERGUI.OnGUIEvent(): command = %d" % commandID)
274 if dict_command.has_key( commandID ):
276 dict_command[commandID]()
278 traceback.print_exc()
279 elif commandID in (GUIcontext.OPTION_1_ID, GUIcontext.OPTION_2_ID, GUIcontext.OPTION_3_ID):
280 pass # Option selection does not trigger a method
282 logger.error("The command is not implemented: %d" % commandID)
285 # called when module's preferences are changed
286 # preference's resources section and setting name are passed as parameters
287 def preferenceChanged( section, setting ):
288 logger.debug("GENERICSOLVERGUI.preferenceChanged(): %s / %s" % ( section, setting ))
291 # called when active view is changed
292 # view ID is passed as parameter
293 def activeViewChanged( viewID ):
294 logger.debug("GENERICSOLVERGUI.activeViewChanged(): %d" % viewID)
297 # called when active view is cloned
298 # cloned view ID is passed as parameter
299 def viewCloned( viewID ):
300 logger.debug("GENERICSOLVERGUI.viewCloned(): %d" % viewID)
303 # called when active view is viewClosed
304 # view ID is passed as parameter
305 def viewClosed( viewID ):
306 logger.debug("GENERICSOLVERGUI.viewClosed(): %d" % viewID)
309 ################################################
310 # GUI actions implementation
311 ################################################
314 # Create a deterministic case
317 logger.debug("GENERICSOLVERGUI.CreateCase : enter")
318 default_case_name = str( sgPyQt.stringSetting( "GENERICSOLVER", "def_case_name",
319 GUIcontext.DEFAULT_CASE_NAME ).trimmed() )
322 if sgPyQt.action( GUIcontext.OPTION_3_ID ).isChecked():
323 # request object name from the user
324 name, ok = QtGui.QInputDialog.getText(sgPyQt.getDesktop(),
327 QtGui.QLineEdit.Normal,
330 name = str( name.trimmed() )
331 elif sgPyQt.action( GUIcontext.OPTION_2_ID ).isChecked():
332 # generate object name
334 name = "%s %d" % ( default_case_name, __id__ )
336 name = default_case_name
340 # generate object name
342 name = "%s %d" % ( default_case_name, __id__ )
345 ed = getStudyEditor()
346 father = ed.findOrCreateComponent(GUIcontext.MODULE_NAME, icon = GUIcontext.MODULE_PIXMAP)
347 ed.setTypeId(father, GUIcontext.MODULE_ID)
348 case = ed.findItem(father, name)
350 case = ed.createItem(father, name, typeId = GUIcontext.CASE_ID)
351 varE = ed.createItem(case, "E", typeId = GUIcontext.VARIABLE_ID)
352 ed.setAttributeValue(varE, "AttributeReal", 210.e9)
353 varF = ed.createItem(case, "F", typeId = GUIcontext.VARIABLE_ID)
354 ed.setAttributeValue(varF, "AttributeReal", 1000.)
355 varL = ed.createItem(case, "L", typeId = GUIcontext.VARIABLE_ID)
356 ed.setAttributeValue(varL, "AttributeReal", 1.5)
357 varI = ed.createItem(case, "I", typeId = GUIcontext.VARIABLE_ID)
358 ed.setAttributeValue(varI, "AttributeReal", 2.e-6)
360 inputVarList = [study_exchange_vars.Variable("E"),
361 study_exchange_vars.Variable("F"),
362 study_exchange_vars.Variable("L"),
363 study_exchange_vars.Variable("I")]
364 outputVarList = [study_exchange_vars.Variable("dev")]
365 exchVars = study_exchange_vars.ExchangeVariables(inputVarList, outputVarList)
366 study_exchange_vars.createSObjectForExchangeVariables(case, exchVars, icon = VARS_ICON)
368 salome.sg.updateObjBrowser( True )
369 logger.debug("GENERICSOLVERGUI.CreateCase : exit")
375 ed = getStudyEditor()
377 entry = salome.sg.getSelected(0)
378 assert entry is not None
379 sobj = ed.study.FindObjectID(entry)
381 assert ed.getTypeId(sobj) == GUIcontext.CASE_ID
382 assert hasChildren(sobj)
384 # Initialize and run the solver
385 solver_engine = salome.lcc.FindOrLoadComponent("FactoryServer", SOLVER_ENGINE_NAME)
386 solver_engine.Init(getStudyId(), entry)
388 param_input = SALOME_TYPES.ParametricInput(inputVarList = [],
389 outputVarList = ["dev"],
390 inputValues = [[[]]],
391 specificParameters = [])
395 param_output = solver_engine.Exec(param_input)
396 except SALOME.SALOME_Exception, exc:
397 error = exc.details.text
399 solver_engine.Finalize()
401 if error is not None:
402 QtGui.QMessageBox.critical(sgPyQt.getDesktop(), "Error", error)
403 elif param_output.returnCode != 0:
404 QtGui.QMessageBox.critical(sgPyQt.getDesktop(), "Error", param_output.errorMessage)
406 # Add result to deterministic case in object browser
407 var = ed.findOrCreateItem(sobj, "Deviation")
408 ed.setAttributeValue(var, "AttributeReal", param_output.outputValues[0][0][0][0])
409 salome.sg.updateObjBrowser(0)
416 father = study.FindComponent( GUIcontext.MODULE_NAME )
418 iter = study.NewChildIterator( father )
419 builder = study.NewBuilder()
423 builder.RemoveObjectWithChildren( sobj )
425 salome.sg.updateObjBrowser( True )
430 # Set value to variable
433 ed = getStudyEditor()
434 entry = salome.sg.getSelected(0)
435 assert entry is not None
436 sobj = ed.study.FindObjectID(entry)
438 oldvalue = ed.getAttributeValue(sobj, "AttributeReal", 0.0)
439 name, ok = QtGui.QInputDialog.getText(sgPyQt.getDesktop(),
442 QtGui.QLineEdit.Normal,
444 value = float( name.trimmed() )
445 if not ok or not value: return
446 ed.setAttributeValue(sobj, "AttributeReal", value)
447 salome.sg.updateObjBrowser(0)
450 # Commands dictionary
453 GUIcontext.SOLVER_ID : RunSOLVER,
454 GUIcontext.CREATE_CASE_ID : CreateCase,
455 GUIcontext.DELETE_ALL_ID : DeleteAll,
456 GUIcontext.SET_VALUE_ID : SetValue,