Salome HOME
Merge from V6_main_20120808 08Aug12
[samples/pyhello.git] / src / PYHELLOGUI / PYHELLOGUI.py
1 # Copyright (C) 2007-2012  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 # ---
24 # File   : PYHELLOGUI.py
25 # Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
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     PASSWORD_ID      = 947
50     PYHELLO_TB_ID    = 90
51     DELETE_ALL_ID    = 951
52     SHOW_ME_ID       = 952
53     DELETE_ME_ID     = 953
54     RENAME_ME_ID     = 954
55     # default object name
56     DEFAULT_NAME     = "Object"
57     # default password
58     DEFAULT_PASSWD   = "Passwd"
59
60     # constructor
61     def __init__( self ):
62         # create top-level menu
63         mid = sgPyQt.createMenu( "PyHello", -1, GUIcontext.PYHELLO_MENU_ID, sgPyQt.defaultMenuGroup() )
64         # create toolbar
65         tid = sgPyQt.createTool( "PyHello" )
66         # create actions and fill menu and toolbar with actions
67         a = sgPyQt.createAction( GUIcontext.HELLO_ID, "Hello", "Hello", "Show hello dialog box", "ExecPYHELLO.png" )
68         sgPyQt.createMenu( a, mid )
69         sgPyQt.createTool( a, tid )
70         a = sgPyQt.createSeparator()
71         sgPyQt.createMenu( a, mid )
72         a = sgPyQt.createAction( GUIcontext.CREATE_OBJECT_ID, "Create object", "Create object", "Create object" )
73         sgPyQt.createMenu( a, mid )
74         a = sgPyQt.createSeparator()
75         sgPyQt.createMenu( a, mid )
76         try:
77             ag = sgPyQt.createActionGroup( GUIcontext.OPTIONS_ID )
78             ag.setText( "Creation mode" )
79             ag.setUsesDropDown(True)
80             a = sgPyQt.createAction( GUIcontext.OPTION_1_ID, "Default name", "Default name", "Use default name for the objects" )
81             a.setCheckable( True )
82             ag.add( a )
83             a = sgPyQt.createAction( GUIcontext.OPTION_2_ID, "Generate name", "Generate name", "Generate name for the objects" )
84             a.setCheckable( True )
85             ag.add( a )
86             a = sgPyQt.createAction( GUIcontext.OPTION_3_ID, "Ask name", "Ask name", "Request object name from the user" )
87             a.setCheckable( True )
88             ag.add( a )
89             sgPyQt.createMenu( ag, mid )
90             sgPyQt.createTool( ag, tid )
91             default_mode = sgPyQt.integerSetting( "PYHELLO", "creation_mode", 0 )
92             sgPyQt.action( GUIcontext.OPTION_1_ID + default_mode ).setChecked( True )
93         except:
94             pass
95         a = sgPyQt.createSeparator()
96         a = sgPyQt.createAction( GUIcontext.PASSWORD_ID, "Display password", "Display password", "Display password" )
97         sgPyQt.createMenu( a, mid )
98         
99         # the following action are used in context popup
100         a = sgPyQt.createAction( GUIcontext.DELETE_ALL_ID, "Delete all", "Delete all", "Delete all objects" )
101         a = sgPyQt.createAction( GUIcontext.SHOW_ME_ID,    "Show",       "Show",       "Show object name" )
102         a = sgPyQt.createAction( GUIcontext.DELETE_ME_ID,  "Delete",     "Delete",     "Remove object" )
103         a = sgPyQt.createAction( GUIcontext.RENAME_ME_ID,  "Rename",     "Rename",     "Rename object" )
104         pass
105     pass
106
107 ################################################
108 # Global variables
109 ################################################
110
111 # study-to-context map
112 __study2context__   = {}
113 # current context
114 __current_context__ = None
115 # object counter
116 __objectid__ = 0
117
118 ################################################
119        
120 # Get SALOME PyQt interface
121 import SalomePyQt
122 sgPyQt = SalomePyQt.SalomePyQt()
123
124 # Get SALOME Swig interface
125 import libSALOME_Swig
126 sg = libSALOME_Swig.SALOMEGUI_Swig()
127
128 ################################################
129
130 ################################################
131 # Internal methods
132 ################################################
133
134 ###
135 # get active study ID
136 ###
137 def _getStudyId():
138     return sgPyQt.getStudyId()
139
140 ###
141 # get active study
142 ###
143 def _getStudy():
144     studyId = _getStudyId()
145     study = getStudyManager().GetStudyByID( studyId )
146     return study
147
148 ###
149 # returns True if object has children
150 ###
151 def _hasChildren( sobj ):
152     if sobj:
153         study = _getStudy()
154         iter  = study.NewChildIterator( sobj )
155         while iter.More():
156             name = iter.Value().GetName()
157             if name:
158                 return True
159             iter.Next()
160             pass
161         pass
162     return False
163
164 ###
165 # get current GUI context
166 ###
167 def _getContext():
168     global __current_context__
169     return __current_context__
170
171 ###
172 # set and return current GUI context
173 # study ID is passed as parameter
174 ###
175 def _setContext( studyID ):
176     global __study2context__, __current_context__
177     if not __study2context__.has_key(studyID):
178         __study2context__[studyID] = GUIcontext()
179         pass
180     __current_context__ = __study2context__[studyID]
181     return __current_context__
182
183 ###
184 # increment object counter in the map
185 ###
186 def _incObjToMap( m, id ):
187     if id not in m: m[id] = 0
188     m[id] += 1
189     pass
190
191 ###
192 # analyse selection
193 ###
194 def _getSelection():
195     selcount = sg.SelectedCount()
196     seltypes = {}
197     for i in range( selcount ):
198         _incObjToMap( seltypes, getObjectID( _getStudy(), sg.getSelected( i ) ) )
199         pass
200     return selcount, seltypes
201
202 ################################################
203 # Callback functions
204 ################################################
205
206 # called when module is initialized
207 # perform initialization actions
208 def initialize():
209     if verbose() : print "PYHELLOGUI.initialize() : study : %d" % _getStudyId()
210     # set default preferences values
211     if not sgPyQt.hasSetting( "PYHELLO", "def_obj_name"):
212         sgPyQt.addSetting( "PYHELLO", "def_obj_name", GUIcontext.DEFAULT_NAME )
213     if not sgPyQt.hasSetting( "PYHELLO", "creation_mode"):
214         sgPyQt.addSetting( "PYHELLO", "creation_mode", 0 )
215     if not sgPyQt.hasSetting( "PYHELLO", "Password"):
216         sgPyQt.addSetting( "PYHELLO", "Password", GUIcontext.DEFAULT_PASSWD )
217     pass
218
219 # called when module is initialized
220 # return map of popup windows to be used by the module
221 def windows():
222     if verbose() : print "PYHELLOGUI.windows() : study : %d" % _getStudyId()
223     wm = {}
224     wm[SalomePyQt.WT_ObjectBrowser] = Qt.LeftDockWidgetArea
225     wm[SalomePyQt.WT_PyConsole]     = Qt.BottomDockWidgetArea
226     return wm
227
228 # called when module is initialized
229 # return list of 2d/3d views to be used ny the module
230 def views():
231     if verbose() : print "PYHELLOGUI.views() : study : %d" % _getStudyId()
232     return []
233
234 # called when module is initialized
235 # export module's preferences
236 def createPreferences():
237     if verbose() : print "PYHELLOGUI.createPreferences() : study : %d" % _getStudyId()
238     gid = sgPyQt.addPreference( "General" )
239     gid = sgPyQt.addPreference( "Object creation", gid )
240     pid = sgPyQt.addPreference( "Default name",  gid, SalomePyQt.PT_String,   "PYHELLO", "def_obj_name" )
241     pid = sgPyQt.addPreference( "Default creation mode", gid, SalomePyQt.PT_Selector, "PYHELLO", "creation_mode" )
242     strings = QStringList()
243     strings.append( "Default name" )
244     strings.append( "Generate name" )
245     strings.append( "Ask name" )
246     indexes = []
247     indexes.append( QVariant(0) )
248     indexes.append( QVariant(1) )
249     indexes.append( QVariant(2) )
250     sgPyQt.setPreferenceProperty( pid, "strings", QVariant( strings ) )
251     sgPyQt.setPreferenceProperty( pid, "indexes", QVariant( indexes ) )
252     pid = sgPyQt.addPreference( "Password",  gid, SalomePyQt.PT_String,   "PYHELLO", "Password" )
253     sgPyQt.setPreferenceProperty( pid, "echo", QVariant( 2 ) )
254     pass
255
256 # called when module is activated
257 # returns True if activating is successfull and False otherwise
258 def activate():
259     if verbose() : print "PYHELLOGUI.activate() : study : %d" % _getStudyId()
260     ctx = _setContext( _getStudyId() )
261     return True
262
263 # called when module is deactivated
264 def deactivate():
265     if verbose() : print "PYHELLOGUI.deactivate() : study : %d" % _getStudyId()
266     pass
267
268 # called when active study is changed
269 # active study ID is passed as parameter
270 def activeStudyChanged( studyID ):
271     if verbose() : print "PYHELLOGUI.activeStudyChanged(): study : %d" % studyID
272     ctx = _setContext( _getStudyId() )
273     pass
274
275 # called when popup menu is invoked
276 # popup menu and menu context are passed as parameters
277 def createPopupMenu( popup, context ):
278     if verbose() : print "PYHELLOGUI.createPopupMenu(): context = %s" % context
279     ctx = _setContext( _getStudyId() )
280     study = _getStudy()
281     selcount, selected = _getSelection()
282     if verbose() : print selcount, selected
283     if selcount == 1:
284         # one object is selected
285         if moduleID() in selected:
286             # menu for component
287             popup.addAction( sgPyQt.action( GUIcontext.DELETE_ALL_ID ) )
288         elif objectID() in selected:
289             # menu for object
290             popup.addAction( sgPyQt.action( GUIcontext.SHOW_ME_ID ) )
291             popup.addAction( sgPyQt.action( GUIcontext.RENAME_ME_ID ) )
292             popup.addSeparator()
293             popup.addAction( sgPyQt.action( GUIcontext.DELETE_ME_ID ) )
294             pass
295         pass
296     elif selcount > 1:
297         # several objects are selected
298         if len( selected ) == 1:
299             if moduleID() in selected:
300                 # menu for component
301                 popup.addAction( sgPyQt.action( GUIcontext.DELETE_ALL_ID ) )
302             elif objectID() in selected:
303                 # menu for list of objects
304                 popup.addAction( sgPyQt.action( GUIcontext.DELETE_ME_ID ) )
305                 pass
306             pass
307         pass
308     pass
309
310 # called when GUI action is activated
311 # action ID is passed as parameter
312 def OnGUIEvent( commandID ):
313     if verbose() : print "PYHELLOGUI.OnGUIEvent(): command = %d" % commandID
314     if dict_command.has_key( commandID ):
315         try:
316             dict_command[commandID]()
317         except:
318             traceback.print_exc()
319     else:
320         if verbose() : print "The command is not implemented: %d" % commandID
321     pass
322
323 # called when module's preferences are changed
324 # preference's resources section and setting name are passed as parameters
325 def preferenceChanged( section, setting ):
326     if verbose() : print "PYHELLOGUI.preferenceChanged(): %s / %s" % ( section, setting )
327     pass
328
329 # called when active view is changed
330 # view ID is passed as parameter
331 def activeViewChanged( viewID ):
332     if verbose() : print "PYHELLOGUI.activeViewChanged(): %d" % viewID
333     pass
334
335 # called when active view is cloned
336 # cloned view ID is passed as parameter
337 def viewCloned( viewID ):
338     if verbose() : print "PYHELLOGUI.viewCloned(): %d" % viewID
339     pass
340
341 # called when active view is viewClosed
342 # view ID is passed as parameter
343 def viewClosed( viewID ):
344     if verbose() : print "PYHELLOGUI.viewClosed(): %d" % viewID
345     pass
346
347 # called when study is opened
348 # returns engine IOR
349 def engineIOR():
350     if verbose() : print "PYHELLOGUI.engineIOR()"
351     return getEngineIOR()
352
353 # called to check if object can be dragged
354 # returns True if drag operation is allowed for this object
355 def isDraggable(what):
356     if verbose() : print "PYHELLOGUI.isDraggable()"
357     # return True if object is draggable
358     return False
359
360 # called to check if object allows dropping on it
361 # returns True if drop operation is allowed for this object
362 def isDropAccepted(where):
363     if verbose() : print "PYHELLOGUI.isDropAccepted()"
364     # return True if object accept drops
365     return False
366
367 # called when drag and drop operation is finished
368 # performs corresponding data re-arrangement if allowed
369 def dropObjects(what, where, row, action):
370     if verbose() :
371         print "PYHELLOGUI.dropObjects()"
372         # 'what' is a list of entries of objects being dropped
373         for i in what: print "- dropped:", i
374         # 'where' is a parent object's entry
375         print "- dropping on:", where
376         # 'row' is an position in the parent's children list;
377         # -1 if appending to the end of children list is performed
378         print "- dropping position:", row
379         # 'action' is a dropping action being performed:
380         # - 0x01 (Qt::CopyAction) for copy
381         # - 0x02 (Qt::MoveAction) for move
382         print "- drop action:", action
383         pass
384     pass
385
386 ################################################
387 # GUI actions implementation
388 ################################################
389
390 ###
391 # 'HELLO' dialog box
392 ###
393 class MyDialog( QDialog ):
394     # constructor
395     def __init__( self, parent = None, modal = 0):
396         QDialog.__init__( self, parent )
397         self.setObjectName( "MyDialog" )
398         self.setModal( modal )
399         self.setWindowTitle( "HELLO!" )
400         vb = QVBoxLayout( self )
401         vb.setMargin( 8 )
402
403         hb0 = QHBoxLayout( self )
404         label = QLabel( "Prenom: ", self )
405         hb0.addWidget( label )
406         self.entry = QLineEdit( self )
407         self.entry.setMinimumWidth( 200 )
408         hb0.addWidget( self.entry )
409         vb.addLayout( hb0 )
410         
411         hb1 = QHBoxLayout( self )
412         bOk = QPushButton( "&OK", self )
413         bOk.setIcon( sgPyQt.loadIcon( 'PYHELLO', 'ICO_HANDSHAKE' ) )
414         self.connect( bOk, SIGNAL( 'clicked()' ), self, SLOT( 'accept()' ) )
415         hb1.addWidget( bOk )
416         
417         hb1.addStretch( 10 )
418         
419         bCancel = QPushButton( "&Cancel", self )
420         bCancel.setIcon( sgPyQt.loadIcon( 'PYHELLO', 'ICO_STOP' ) )
421         self.connect( bCancel, SIGNAL( 'clicked()' ), self, SLOT( 'close()' ) )
422         hb1.addWidget( bCancel )
423         
424         vb.addLayout( hb1 )
425         pass
426     
427     # OK button slot
428     def accept( self ):
429         name = str( self.entry.text() )
430         if name != "":
431             banner = getEngine().makeBanner( name )
432             QMessageBox.information( self, 'Info', banner )
433             self.close()
434         else:
435             QMessageBox.warning( self, 'Error!', 'Please, enter the name!' )
436         pass
437
438 ###
439 # Show 'HELLO' dialog box
440 ###
441 def ShowHELLO():
442     # create dialog box
443     d = MyDialog( sgPyQt.getDesktop(), 1 )
444     # show dialog box
445     d.exec_()
446     pass
447
448 ###
449 # Create new object
450 ###
451 def CreateObject():
452     global __objectid__
453     default_name = str( sgPyQt.stringSetting( "PYHELLO", "def_obj_name", GUIcontext.DEFAULT_NAME ).trimmed() )
454     try:
455         if sgPyQt.action( GUIcontext.OPTION_3_ID ).isChecked():
456             # request object name from the user
457             name, ok = QInputDialog.getText( sgPyQt.getDesktop(),
458                                              "Create Object",
459                                              "Enter object name:",
460                                              QLineEdit.Normal,
461                                              default_name )
462             if not ok: return
463             name = str( name.trimmed() )
464         elif sgPyQt.action( GUIcontext.OPTION_2_ID ).isChecked():
465             # generate object name
466             __objectid__  = __objectid__ + 1
467             name = "%s %d" % ( default_name, __objectid__ )
468         else:
469             name = default_name
470             pass
471         pass
472     except:
473         # generate object name
474         __objectid__  = __objectid__ + 1
475         name = "%s %d" % ( default_name, __objectid__ )
476         pass
477     if not name: return
478     getEngine().createObject( _getStudy(), name )
479     sg.updateObjBrowser( True )
480     pass
481
482 ###
483 # Delete all objects
484 ###
485 def DeleteAll():
486     study = _getStudy()
487     father = study.FindComponent( moduleName() )
488     if father:
489         iter = study.NewChildIterator( father )
490         builder = study.NewBuilder()
491         while iter.More():
492             sobj = iter.Value()
493             iter.Next()
494             builder.RemoveObjectWithChildren( sobj )
495             pass
496         sg.updateObjBrowser( True )
497         pass
498     pass
499
500 ###
501 # Show object's name
502 ###
503 def ShowMe():
504     study = _getStudy()
505     entry = sg.getSelected( 0 )
506     if entry != '':
507         sobj = study.FindObjectID( entry )
508         if ( sobj ):
509             test, attr = sobj.FindAttribute( "AttributeName" )
510             if test:
511                 QMessageBox.information( sgPyQt.getDesktop(), 'Info', "My name is '%s'" % attr.Value() )
512                 pass
513             pass
514         pass
515     pass
516
517 ###
518 # Delete selected object(s)
519 ###
520 def Delete():
521     study = _getStudy()
522     builder = study.NewBuilder()
523     if sg.SelectedCount() <= 0: return
524     for i in range( sg.SelectedCount() ):
525         entry = sg.getSelected( i )
526         if entry != '':
527             sobj = study.FindObjectID( entry )
528             if ( sobj ):
529                 builder.RemoveObject( sobj )
530                 pass
531             pass
532         pass
533     sg.updateObjBrowser( True )
534     pass
535
536 ###
537 # Rename selected object
538 ###
539 def Rename():
540     study = _getStudy()
541     builder = study.NewBuilder()
542     entry = sg.getSelected( 0 )
543     if entry != '':
544         sobj = study.FindObjectID( entry )
545         if ( sobj ):
546             name, ok = QInputDialog.getText( sgPyQt.getDesktop(),
547                                              "Object name",
548                                              "Enter object name:",
549                                              QLineEdit.Normal,
550                                              sobj.GetName() )
551             name = str( name.trimmed() )
552             if not ok or not name: return
553             attr = builder.FindOrCreateAttribute( sobj, "AttributeName" )
554             attr.SetValue( name )
555             sg.updateObjBrowser( True )
556             pass
557         pass
558     pass
559
560 ###
561 # Display password stored in the preferences
562 ###
563 def Password():
564   passwd = str( sgPyQt.stringSetting( "PYHELLO", "Password", GUIcontext.DEFAULT_PASSWD ).trimmed() )
565   QMessageBox.information(sgPyQt.getDesktop(),
566                           "Password",
567                           passwd)
568
569 ###
570 # Commands dictionary
571 ###
572 dict_command = {
573     GUIcontext.HELLO_ID         : ShowHELLO,
574     GUIcontext.CREATE_OBJECT_ID : CreateObject,
575     GUIcontext.DELETE_ALL_ID    : DeleteAll,
576     GUIcontext.SHOW_ME_ID       : ShowMe,
577     GUIcontext.DELETE_ME_ID     : Delete,
578     GUIcontext.RENAME_ME_ID     : Rename,
579     GUIcontext.PASSWORD_ID      : Password,
580     }