Salome HOME
e931a440910b312c7a4da82fd248a30a13f2c6f3
[samples/pyhello.git] / src / PYHELLOGUI / PYHELLOGUI.py
1 #  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 #
3 #  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 #  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 #
6 #  This library is free software; you can redistribute it and/or
7 #  modify it under the terms of the GNU Lesser General Public
8 #  License as published by the Free Software Foundation; either
9 #  version 2.1 of the License.
10 #
11 #  This library is distributed in the hope that it will be useful,
12 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 #  Lesser General Public License for more details.
15 #
16 #  You should have received a copy of the GNU Lesser General Public
17 #  License along with this library; if not, write to the Free Software
18 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 #
20 #  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 #
22 # ---
23 # File   : PYHELLOGUI.py
24 # Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
25 # ---
26 #
27
28 import traceback
29 import os
30 from PyQt4.QtGui import *
31 from PyQt4.QtCore import *
32
33 from PYHELLO_utils import *
34
35 ################################################
36 # GUI context class
37 # Used to store actions, menus, toolbars, etc...
38 ################################################
39
40 class GUIcontext:
41     # menus/toolbars/actions IDs
42     PYHELLO_MENU_ID  = 90
43     HELLO_ID         = 941
44     CREATE_OBJECT_ID = 942
45     OPTIONS_ID       = 943
46     OPTION_1_ID      = 944
47     OPTION_2_ID      = 945
48     OPTION_3_ID      = 946
49     PYHELLO_TB_ID    = 90
50     DELETE_ALL_ID    = 951
51     SHOW_ME_ID       = 952
52     DELETE_ME_ID     = 953
53     RENAME_ME_ID     = 954
54     # default object name
55     DEFAULT_NAME     = "Object"
56
57     # constructor
58     def __init__( self ):
59         # create top-level menu
60         mid = sgPyQt.createMenu( "PyHello", -1, GUIcontext.PYHELLO_MENU_ID, sgPyQt.defaultMenuGroup() )
61         # create toolbar
62         tid = sgPyQt.createTool( "PyHello" )
63         # create actions and fill menu and toolbar with actions
64         a = sgPyQt.createAction( GUIcontext.HELLO_ID, "Hello", "Hello", "Show hello dialog box", "ExecPYHELLO.png" )
65         sgPyQt.createMenu( a, mid )
66         sgPyQt.createTool( a, tid )
67         a = sgPyQt.createSeparator()
68         sgPyQt.createMenu( a, mid )
69         a = sgPyQt.createAction( GUIcontext.CREATE_OBJECT_ID, "Create object", "Create object", "Create object" )
70         sgPyQt.createMenu( a, mid )
71         a = sgPyQt.createSeparator()
72         sgPyQt.createMenu( a, mid )
73         try:
74             ag = sgPyQt.createActionGroup( GUIcontext.OPTIONS_ID )
75             ag.setText( "Creation mode" )
76             ag.setUsesDropDown(True)
77             a = sgPyQt.createAction( GUIcontext.OPTION_1_ID, "Default name", "Default name", "Use default name for the objects" )
78             a.setCheckable( True )
79             ag.add( a )
80             a = sgPyQt.createAction( GUIcontext.OPTION_2_ID, "Generate name", "Generate name", "Generate name for the objects" )
81             a.setCheckable( True )
82             ag.add( a )
83             a = sgPyQt.createAction( GUIcontext.OPTION_3_ID, "Ask name", "Ask name", "Request object name from the user" )
84             a.setCheckable( True )
85             ag.add( a )
86             sgPyQt.createMenu( ag, mid )
87             sgPyQt.createTool( ag, tid )
88             default_mode = sgPyQt.integerSetting( "PYHELLO", "creation_mode", 0 )
89             sgPyQt.action( GUIcontext.OPTION_1_ID + default_mode ).setChecked( True )
90         except:
91             pass
92         # the following action are used in context popup
93         a = sgPyQt.createAction( GUIcontext.DELETE_ALL_ID, "Delete all", "Delete all", "Delete all objects" )
94         a = sgPyQt.createAction( GUIcontext.SHOW_ME_ID,    "Show",       "Show",       "Show object name" )
95         a = sgPyQt.createAction( GUIcontext.DELETE_ME_ID,  "Delete",     "Delete",     "Remove object" )
96         a = sgPyQt.createAction( GUIcontext.RENAME_ME_ID,  "Rename",     "Rename",     "Rename object" )
97         pass
98     pass
99
100 ################################################
101 # Global variables
102 ################################################
103
104 # study-to-context map
105 __study2context__   = {}
106 # current context
107 __current_context__ = None
108 # object counter
109 __id__ = 0
110
111 ################################################
112        
113 # Get SALOME PyQt interface
114 import SalomePyQt
115 sgPyQt = SalomePyQt.SalomePyQt()
116
117 # Get SALOME Swig interface
118 import libSALOME_Swig
119 sg = libSALOME_Swig.SALOMEGUI_Swig()
120
121 ################################################
122
123 ################################################
124 # Internal methods
125 ################################################
126
127 ###
128 # get active study ID
129 ###
130 def _getStudyId():
131     return sgPyQt.getStudyId()
132
133 ###
134 # get active study
135 ###
136 def _getStudy():
137     studyId = _getStudyId()
138     study = getStudyManager().GetStudyByID( studyId )
139     return study
140
141 ###
142 # returns True if object has children
143 ###
144 def _hasChildren( sobj ):
145     if sobj:
146         study = _getStudy()
147         iter  = study.NewChildIterator( sobj )
148         while iter.More():
149             name = iter.Value().GetName()
150             if name:
151                 return True
152             iter.Next()
153             pass
154         pass
155     return False
156
157 ###
158 # get current GUI context
159 ###
160 def _getContext():
161     global __current_context__
162     return __current_context__
163
164 ###
165 # set and return current GUI context
166 # study ID is passed as parameter
167 ###
168 def _setContext( studyID ):
169     global __study2context__, __current_context__
170     if not __study2context__.has_key(studyID):
171         __study2context__[studyID] = GUIcontext()
172         pass
173     __current_context__ = __study2context__[studyID]
174     return __current_context__
175
176 ###
177 # increment object counter in the map
178 ###
179 def _incObjToMap( m, id ):
180     if id not in m: m[id] = 0
181     m[id] += 1
182     pass
183
184 ###
185 # analyse selection
186 ###
187 def _getSelection():
188     selcount = sg.SelectedCount()
189     seltypes = {}
190     for i in range( selcount ):
191         _incObjToMap( seltypes, getObjectID( _getStudy(), sg.getSelected( i ) ) )
192         pass
193     return selcount, seltypes
194
195 ################################################
196 # Callback functions
197 ################################################
198
199 # called when module is initialized
200 # perform initialization actions
201 def initialize():
202     if verbose() : print "PYHELLOGUI.initialize() : study : %d" % _getStudyId()
203     # set default preferences values
204     if not sgPyQt.hasSetting( "PYHELLO", "def_obj_name"):
205         sgPyQt.addSetting( "PYHELLO", "def_obj_name", GUIcontext.DEFAULT_NAME )
206     if not sgPyQt.hasSetting( "PYHELLO", "creation_mode"):
207         sgPyQt.addSetting( "PYHELLO", "creation_mode", 0 )
208     pass
209
210 # called when module is initialized
211 # return map of popup windows to be used by the module
212 def windows():
213     if verbose() : print "PYHELLOGUI.windows() : study : %d" % _getStudyId()
214     wm = {}
215     wm[SalomePyQt.WT_ObjectBrowser] = Qt.LeftDockWidgetArea
216     wm[SalomePyQt.WT_PyConsole]     = Qt.BottomDockWidgetArea
217     return wm
218
219 # called when module is initialized
220 # return list of 2d/3d views to be used ny the module
221 def views():
222     if verbose() : print "PYHELLOGUI.views() : study : %d" % _getStudyId()
223     return []
224
225 # called when module is initialized
226 # export module's preferences
227 def createPreferences():
228     if verbose() : print "PYHELLOGUI.createPreferences() : study : %d" % _getStudyId()
229     gid = sgPyQt.addPreference( "General" )
230     gid = sgPyQt.addPreference( "Object creation", gid )
231     pid = sgPyQt.addPreference( "Default name",  gid, SalomePyQt.PT_String,   "PYHELLO", "def_obj_name" )
232     pid = sgPyQt.addPreference( "Default creation mode", gid, SalomePyQt.PT_Selector, "PYHELLO", "creation_mode" )
233     strings = QStringList()
234     strings.append( "Default name" )
235     strings.append( "Generate name" )
236     strings.append( "Ask name" )
237     indexes = []
238     indexes.append( QVariant(0) )
239     indexes.append( QVariant(1) )
240     indexes.append( QVariant(2) )
241     sgPyQt.setPreferenceProperty( pid, "strings", QVariant( strings ) )
242     sgPyQt.setPreferenceProperty( pid, "indexes", QVariant( indexes ) )
243     pass
244
245 # called when module is activated
246 # returns True if activating is successfull and False otherwise
247 def activate():
248     if verbose() : print "PYHELLOGUI.activate() : study : %d" % _getStudyId()
249     ctx = _setContext( _getStudyId() )
250     return True
251
252 # called when module is deactivated
253 def deactivate():
254     if verbose() : print "PYHELLOGUI.deactivate() : study : %d" % _getStudyId()
255     pass
256
257 # called when active study is changed
258 # active study ID is passed as parameter
259 def activeStudyChanged( studyID ):
260     if verbose() : print "PYHELLOGUI.activeStudyChanged(): study : %d" % studyID
261     ctx = _setContext( _getStudyId() )
262     pass
263
264 # called when popup menu is invoked
265 # popup menu and menu context are passed as parameters
266 def createPopupMenu( popup, context ):
267     if verbose() : print "PYHELLOGUI.createPopupMenu(): context = %s" % context
268     ctx = _setContext( _getStudyId() )
269     study = _getStudy()
270     selcount, selected = _getSelection()
271     if verbose() : print selcount, selected
272     if selcount == 1:
273         # one object is selected
274         if moduleID() in selected:
275             # menu for component
276             popup.addAction( sgPyQt.action( GUIcontext.DELETE_ALL_ID ) )
277         elif objectID() in selected:
278             # menu for object
279             popup.addAction( sgPyQt.action( GUIcontext.SHOW_ME_ID ) )
280             popup.addAction( sgPyQt.action( GUIcontext.RENAME_ME_ID ) )
281             popup.addSeparator()
282             popup.addAction( sgPyQt.action( GUIcontext.DELETE_ME_ID ) )
283             pass
284         pass
285     elif selcount > 1:
286         # several objects are selected
287         if len( selected ) == 1:
288             if moduleID() in selected:
289                 # menu for component
290                 popup.addAction( sgPyQt.action( GUIcontext.DELETE_ALL_ID ) )
291             elif objectID() in selected:
292                 # menu for list of objects
293                 popup.addAction( sgPyQt.action( GUIcontext.DELETE_ME_ID ) )
294                 pass
295             pass
296         pass
297     pass
298
299 # called when GUI action is activated
300 # action ID is passed as parameter
301 def OnGUIEvent( commandID ):
302     if verbose() : print "PYHELLOGUI.OnGUIEvent(): command = %d" % commandID
303     if dict_command.has_key( commandID ):
304         try:
305             dict_command[commandID]()
306         except:
307             traceback.print_exc()
308     else:
309         if verbose() : print "The command is not implemented: %d" % commandID
310     pass
311
312 # called when module's preferences are changed
313 # preference's resources section and setting name are passed as parameters
314 def preferenceChanged( section, setting ):
315     if verbose() : print "PYHELLOGUI.preferenceChanged(): %s / %s" % ( section, setting )
316     pass
317
318 # called when active view is changed
319 # view ID is passed as parameter
320 def activeViewChanged( viewID ):
321     if verbose() : print "PYHELLOGUI.activeViewChanged(): %d" % viewID
322     pass
323
324 # called when active view is cloned
325 # cloned view ID is passed as parameter
326 def viewCloned( viewID ):
327     if verbose() : print "PYHELLOGUI.viewCloned(): %d" % viewID
328     pass
329
330 # called when active view is viewClosed
331 # view ID is passed as parameter
332 def viewClosed( viewID ):
333     if verbose() : print "PYHELLOGUI.viewClosed(): %d" % viewID
334     pass
335
336 # called when study is opened
337 # returns engine IOR
338 def engineIOR():
339     if verbose() : print "PYHELLOGUI.engineIOR()"
340     return getEngineIOR()
341
342 ################################################
343 # GUI actions implementation
344 ################################################
345
346 ###
347 # 'HELLO' dialog box
348 ###
349 class MyDialog( QDialog ):
350     # constructor
351     def __init__( self, parent = None, modal = 0):
352         QDialog.__init__( self, parent )
353         self.setObjectName( "MyDialog" )
354         self.setModal( modal )
355         self.setWindowTitle( "HELLO!" )
356         vb = QVBoxLayout( self )
357         vb.setMargin( 8 )
358
359         hb0 = QHBoxLayout( self )
360         label = QLabel( "Prenom: ", self )
361         hb0.addWidget( label )
362         self.entry = QLineEdit( self )
363         self.entry.setMinimumWidth( 200 )
364         hb0.addWidget( self.entry )
365         vb.addLayout( hb0 )
366         
367         hb1 = QHBoxLayout( self )
368         bOk = QPushButton( "&OK", self )
369         self.connect( bOk, SIGNAL( 'clicked()' ), self, SLOT( 'accept()' ) )
370         hb1.addWidget( bOk )
371         
372         hb1.addStretch( 10 )
373         
374         bCancel = QPushButton( "&Cancel", self )
375         self.connect( bCancel, SIGNAL( 'clicked()' ), self, SLOT( 'close()' ) )
376         hb1.addWidget( bCancel )
377         
378         vb.addLayout( hb1 )
379         pass
380     
381     # OK button slot
382     def accept( self ):
383         name = str( self.entry.text() )
384         if name != "":
385             banner = getEngine().makeBanner( name )
386             QMessageBox.information( self, 'Info', banner )
387             self.close()
388         else:
389             QMessageBox.warning( self, 'Error!', 'Please, enter the name!' )
390         pass
391
392 ###
393 # Show 'HELLO' dialog box
394 ###
395 def ShowHELLO():
396     # create dialog box
397     d = MyDialog( sgPyQt.getDesktop(), 1 )
398     # show dialog box
399     d.exec_()
400     pass
401
402 ###
403 # Create new object
404 ###
405 def CreateObject():
406     default_name = str( sgPyQt.stringSetting( "PYHELLO", "def_obj_name", GUIcontext.DEFAULT_NAME ).trimmed() )
407     try:
408         if sgPyQt.action( GUIcontext.OPTION_3_ID ).isChecked():
409             # request object name from the user
410             name, ok = QInputDialog.getText( sgPyQt.getDesktop(),
411                                              "Create Object",
412                                              "Enter object name:",
413                                              QLineEdit.Normal,
414                                              default_name )
415             if not ok: return
416             name = str( name.trimmed() )
417         elif sgPyQt.action( GUIcontext.OPTION_2_ID ).isChecked():
418             # generate object name
419             global __id__
420             __id__  = __id__ + 1
421             name = "%s %d" % ( default_name, __id__ )
422         else:
423             name = default_name
424             pass
425         pass
426     except:
427         # generate object name
428         global __id__
429         __id__  = __id__ + 1
430         name = "%s %d" % ( default_name, __id__ )
431         pass
432     if not name: return
433     getEngine().createObject( _getStudy(), name )
434     sg.updateObjBrowser( True )
435     pass
436
437 ###
438 # Delete all objects
439 ###
440 def DeleteAll():
441     study = _getStudy()
442     father = study.FindComponent( moduleName() )
443     if father:
444         iter = study.NewChildIterator( father )
445         builder = study.NewBuilder()
446         while iter.More():
447             sobj = iter.Value()
448             iter.Next()
449             builder.RemoveObjectWithChildren( sobj )
450             pass
451         sg.updateObjBrowser( True )
452         pass
453     pass
454
455 ###
456 # Show object's name
457 ###
458 def ShowMe():
459     study = _getStudy()
460     entry = sg.getSelected( 0 )
461     if entry != '':
462         sobj = study.FindObjectID( entry )
463         if ( sobj ):
464             test, attr = sobj.FindAttribute( "AttributeName" )
465             if test:
466                 QMessageBox.information( sgPyQt.getDesktop(), 'Info', "My name is '%s'" % attr.Value() )
467                 pass
468             pass
469         pass
470     pass
471
472 ###
473 # Delete selected object(s)
474 ###
475 def Delete():
476     study = _getStudy()
477     builder = study.NewBuilder()
478     if sg.SelectedCount() <= 0: return
479     for i in range( sg.SelectedCount() ):
480         entry = sg.getSelected( i )
481         if entry != '':
482             sobj = study.FindObjectID( entry )
483             if ( sobj ):
484                 builder.RemoveObject( sobj )
485                 pass
486             pass
487         pass
488     sg.updateObjBrowser( True )
489     pass
490
491 ###
492 # Rename selected object
493 ###
494 def Rename():
495     study = _getStudy()
496     builder = study.NewBuilder()
497     entry = sg.getSelected( 0 )
498     if entry != '':
499         sobj = study.FindObjectID( entry )
500         if ( sobj ):
501             name, ok = QInputDialog.getText( sgPyQt.getDesktop(),
502                                              "Object name",
503                                              "Enter object name:",
504                                              QLineEdit.Normal,
505                                              sobj.GetName() )
506             name = str( name.trimmed() )
507             if not ok or not name: return
508             attr = builder.FindOrCreateAttribute( sobj, "AttributeName" )
509             attr.SetValue( name )
510             sg.updateObjBrowser( True )
511             pass
512         pass
513     pass
514
515 ###
516 # Commands dictionary
517 ###
518 dict_command = {
519     GUIcontext.HELLO_ID         : ShowHELLO,
520     GUIcontext.CREATE_OBJECT_ID : CreateObject,
521     GUIcontext.DELETE_ALL_ID    : DeleteAll,
522     GUIcontext.SHOW_ME_ID       : ShowMe,
523     GUIcontext.DELETE_ME_ID     : Delete,
524     GUIcontext.RENAME_ME_ID     : Rename,
525     }