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