Salome HOME
dc2ec8c940d8211df374e5d7431928120be4100c
[samples/pylight.git] / src / PYLIGHTGUI / PYLIGHTGUI.py
1 # Copyright (C) 2009-2016  OPEN CASCADE
2 #
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, or (at your option) any later version.
7 #
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.
12 #
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
16 #
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 #
19
20 #  Author : Roman NIKOLAEV, Open CASCADE S.A.S. (roman.nikolaev@opencascade.com)
21 #  Date   : 13/04/2009
22 #
23 import traceback
24 from SalomePyQt import *
25 import PYLIGHT_DataModel
26 from qtsalome import *
27 import libSALOME_Swig
28
29 import os
30 import libSalomePy
31 import vtk
32
33 # Get SALOME PyQt interface
34 sgPyQt = SalomePyQt()
35 # Get SALOME Swig interface
36 sg = libSALOME_Swig.SALOMEGUI_Swig()
37
38 ################################################
39 # GUI context class
40 # Used to store actions, menus, toolbars, etc...
41 ################################################
42
43 class GUIcontext:
44
45     # constructor
46     def __init__( self ):
47         # Load File action
48         sgPyQt.createAction(dict_actions["loadfile"], "Load text File", "Load text file")
49         # Save File action
50         sgPyQt.createAction(dict_actions["savefile"], "Save text File", "Save text file")
51         # Insert Line action
52         sgPyQt.createAction(dict_actions["insertLine"], "Insert Line", "Insert new text line")
53         # Insert new line action
54         sgPyQt.createAction(dict_actions["insertLine"], "Insert Line", "Insert new line")
55         # Edit selected line action
56         sgPyQt.createAction(dict_actions["editLine"], "Edit Line", "Edit selected line")
57         # Remove selected line action
58         sgPyQt.createAction(dict_actions["removeLine"], "Remove Lines", "Remove selected lines")
59         # Clear paragraph
60         sgPyQt.createAction(dict_actions["clearParagraph"], "Clear Paragraph", "Clear selected paragraph")
61         # Clear all paragraphs
62         sgPyQt.createAction(dict_actions["clearAll"], "Clear All", "Clear all paragraphs")
63         # Display line
64         sgPyQt.createAction(dict_actions["displayLine"], "Display Line", "Display selected line")
65         # Erase line
66         sgPyQt.createAction(dict_actions["eraseLine"], "Erase Line", "Erase selected line")
67         # Separator
68         separator = sgPyQt.createSeparator()
69
70         # Get Menu 'File'
71         menuFile = sgPyQt.createMenu( "File", -1, -1 )
72         # Add actions in the menu 'File'
73         sgPyQt.createMenu( separator,                menuFile, -1, 10)
74         sgPyQt.createMenu( dict_actions["loadfile"], menuFile, 10 );
75         sgPyQt.createMenu( dict_actions["savefile"], menuFile, 10 );
76         sgPyQt.createMenu( separator,                menuFile, -1, 10)
77         # Create 'PyLight' menu 
78         menuPyLight = sgPyQt.createMenu( "PyLight", -1, -1, 50)
79         # Add actions in the menu 'PyLight'
80         sgPyQt.createMenu( dict_actions["insertLine"],  menuPyLight, 10 );
81         sgPyQt.createMenu( dict_actions["editLine"],    menuPyLight, 10 );
82         sgPyQt.createMenu( dict_actions["removeLine"],  menuPyLight, 10 );
83         sgPyQt.createMenu( separator,                   menuPyLight, -1, 10);
84         sgPyQt.createMenu( dict_actions["clearAll"],    menuPyLight, 10 );
85         sgPyQt.createMenu( separator,                   menuPyLight, -1, 10);
86         sgPyQt.createMenu( dict_actions["displayLine"], menuPyLight, 10 );
87         sgPyQt.createMenu( dict_actions["eraseLine"],   menuPyLight, 10 );
88
89         # Create DataModel
90         self.DM = PYLIGHT_DataModel.PYLIGHT_DataModel()
91
92         pass # def __init__( self )
93
94     pass # class GUIcontext
95
96 ################################################
97 # Global variables and functions
98 ################################################
99
100 ###
101 # get active study ID
102 ###
103 def _getStudyId():
104     return sgPyQt.getStudyId()
105
106 # verbosity level
107 __verbose__ = None
108
109 ###
110 # Get verbose level
111 ###
112 def verbose():
113     global __verbose__
114     if __verbose__ is None:
115         try:
116             __verbose__ = int( os.getenv( 'SALOME_VERBOSE', 0 ) )
117         except:
118             __verbose__ = 0
119             pass
120         pass
121     return __verbose__
122
123 # study-to-context map
124 __study2context__   = {}
125 # current context
126 __current_context__ = None
127
128 ###
129 # get current GUI context
130 ###
131 def _getContext():
132     global __current_context__
133     return __current_context__
134
135 ###
136 # set and return current GUI context
137 # study ID is passed as parameter
138 ###
139 def _setContext( studyID ):
140     global __study2context__, __current_context__
141     if not __study2context__.has_key(studyID):
142         __study2context__[studyID] = GUIcontext()
143         pass
144     __current_context__ = __study2context__[studyID]
145     return __current_context__
146
147 ################################################
148
149 # Create actions and menus
150 def initialize():
151     if verbose(): print "PYLIGHTGUI::initialize()"
152     return
153
154 # called when module is activated
155 # returns True if activating is successfull and False otherwise
156 def activate():
157     if verbose() : print "PYLIGHTGUI.activate() : study : %d" % _getStudyId()
158     ctx = _setContext( _getStudyId() )
159     return True
160
161 # called when module is deactivated
162 def deactivate():
163     if verbose() : print "PYLIGHTGUI.deactivate() : study : %d" % _getStudyId()
164     pass
165
166 # called when active study is changed
167 # active study ID is passed as parameter
168 def activeStudyChanged( studyID ):
169     if verbose() : print "PYLIGHTGUI.activeStudyChanged(): study : %d" % studyID
170     ctx = _setContext( _getStudyId() )
171     pass
172
173 # Process GUI action
174 def OnGUIEvent(commandID):
175     if verbose() : print "PYLIGHTGUI::OnGUIEvent : commandID = %d" % commandID
176     if dict_command.has_key( commandID ):
177         try:
178             dict_command[commandID]()
179         except:
180             traceback.print_exc()
181     else:
182        if verbose() : print "The command is not implemented: %d" % commandID
183     pass
184
185 # Customize popup menu
186 def createPopupMenu(popup, context):
187     if verbose() : print "PYLIGHTGUI.createPopupMenu(): context = %s" % context
188
189     if context != 'ObjectBrowser':
190         return
191     
192     studyId = _getStudyId()
193     ctx = _setContext( studyId )
194     selcount = sg.SelectedCount()
195     if selcount == 1:
196         entry = sg.getSelected( 0 )
197         obj = ctx.DM.getObject(entry)
198         if obj is not None:
199             if obj.getText() != "\n":
200                 # Line is selected
201                 popup.addAction(sgPyQt.action(dict_actions["editLine"]))
202                 popup.addAction(sgPyQt.action(dict_actions["removeLine"]))
203                 popup.addSeparator()
204                 popup.addAction(sgPyQt.action(dict_actions["displayLine"]))
205                 popup.addAction(sgPyQt.action(dict_actions["displayLine"]))
206                 popup.addAction(sgPyQt.action(dict_actions["eraseLine"]))
207                 pass
208             else:
209                 # Paragraph is selected
210                 popup.addAction(sgPyQt.action(dict_actions["insertLine"]))
211                 popup.addAction(sgPyQt.action(dict_actions["clearParagraph"]))
212                 pass
213             pass
214         else:
215             onlyLines = True
216             pass
217         pass # if selcount == 1
218     pass
219
220 # For saving data in the study
221 def saveFiles(prefix):
222     if verbose(): print "PYLIGHTGUI::saveFile()"
223     ctx = _setContext( _getStudyId() )
224     postfix = "PYLIGHT.txt"
225     filename = prefix+postfix
226     ctx.DM.saveFile(filename)
227     return postfix
228
229 # For restore data from the study
230 def openFiles(filelist):
231     if verbose(): print "PYLIGHTGUI::openFile()"
232     ctx = _setContext( _getStudyId() )
233     filename =  filelist[0]
234     filename.append(filelist[1])
235     ctx.DM.loadFile(filename)
236     return True
237
238 # Loading a text file
239 def loadfile():
240     ctx = _setContext( _getStudyId() )
241     aFilter = "Text files (*.txt)"
242     filename = QFileDialog.getOpenFileName(sgPyQt.getDesktop(), "Open text file", "", aFilter, "Choose a text file to open")
243
244     print filename
245     if isinstance(filename,tuple) and len(filename) >=2:
246        filename = filename[0]
247
248     filename = unicode(filename)
249
250     if len(filename) == 0:
251         return
252     
253     if os.access(str(filename),os.R_OK):
254         ctx.DM.loadFile(filename)
255     else:
256         QMessageBox.warning(sgPyQt.getDesktop(),
257                             "Error!",
258                             "Can not read file:\n%s"%(filename))
259         pass
260     sg.updateObjBrowser(True)
261     pass
262
263 # Saving a text file
264 def savefile():
265     ctx = _setContext( _getStudyId() )
266     aFilter = "Text files (*.txt)"
267     filename = QFileDialog.getSaveFileName(sgPyQt.getDesktop(),"Save text file", "", aFilter, "Choose a text file to save")
268
269     print filename
270     if isinstance(filename,tuple) and len(filename) >=2:
271         filename = filename[0]
272
273     filename = unicode(filename)
274
275     if filename.endswith(".txt") == 0:
276         filename+=".txt"
277         pass
278
279     fn = filename
280     # Get directory name and check access
281     if os.access(str(fn[:fn.rindex(os.path.sep)]), os.W_OK):
282         ctx.DM.saveFile(filename)
283     else:
284         QMessageBox.warning(sgPyQt.getDesktop(),
285                             "Error!",
286                             "Can not save file:\n%s"%(filename))
287         pass
288     pass
289
290 def insertLine():
291     '''
292     Insert new line in the selected paragraph.
293     '''
294     ctx = _setContext( _getStudyId() )
295     #Get result
296     res = QInputDialog.getText(sgPyQt.getDesktop(),
297                                "Add new line",
298                                "Enter the text",
299                                QLineEdit.Normal)
300     if not res[1]: ### user click cancel button
301         return
302     
303     text = res[0]
304     print "RNV: !", res
305     # Nb selected objects
306     selcount = sg.SelectedCount()
307     # Nb object in the Data Model
308     paragrCount = len(ctx.DM.getParagraphs())
309
310     # Create first paragraph
311     if paragrCount == 0:
312         ctx.DM.createObject()
313         # If line not empty create first line
314         if text != "\n":
315             ctx.DM.createObject(text,ctx.DM.getParagraphs()[0])
316         sg.updateObjBrowser(True)
317         return
318     # Create paragraph
319     if text == "\n":
320         ctx.DM.createObject()
321         sg.updateObjBrowser(True)
322         return
323     else:
324         if selcount == 0:
325             QMessageBox.warning(sgPyQt.getDesktop(),
326                                 'Error!',
327                                 'Please, select paragraph!')
328             return
329         if selcount == 1:
330             entry = sg.getSelected( 0 )
331             obj = ctx.DM.getObject(entry)
332             if obj is not None:
333                 # Create line
334                 if(obj.getText() == "\n"):
335                     ctx.DM.createObject(text,entry)
336                     sg.updateObjBrowser(True);
337                     return
338                 else:
339                     QMessageBox.warning(sgPyQt.getDesktop(),
340                                         'Error!',
341                                         'Please, select paragraph!')
342             elif selcount > 1:
343                 QMessageBox.warning(sgPyQt.getDesktop(),
344                                     'Error!',
345                                     'Please, select only one paragraph!')
346     pass
347         
348         
349 # Edit selected line
350 def editLine():
351     ctx = _setContext( _getStudyId() )
352     if sg.SelectedCount() == 1:
353         entry = sg.getSelected( 0 )
354         obj = ctx.DM.getObject(entry)
355         if(obj.getText() != "\n"):
356             #Get text line
357             res = QInputDialog.getText(sgPyQt.getDesktop(),
358                                        "Edit line",
359                                        "Enter the text",
360                                        QLineEdit.Normal,
361                                        PYLIGHT_DataModel.processText(obj.getText()))
362             if not res[1]: ### user click cancel button
363                 return
364             text = res[0]
365             
366             obj.setText(text)
367         else:
368             QMessageBox.information(sgPyQt.getDesktop(),
369                                     'Info',
370                                     'Please, select line!') 
371     else:
372         QMessageBox.information(sgPyQt.getDesktop(),
373                                 'Info',
374                                 'Please, select one line!')
375     sg.updateObjBrowser(True);
376     pass
377
378 # Remove selected lines
379 def removeLine():
380     ctx = _setContext( _getStudyId() )
381     selcount = sg.SelectedCount()
382     onlyLines = True
383     lines = []
384     while selcount != 0:
385         entry = sg.getSelected( selcount - 1)
386         #Check what only lines selected
387         if ctx.DM.getObject(entry).getText() == "\n":
388             onlyLines = False
389             break
390         lines.append(entry)
391         selcount = selcount-1
392         pass
393     if not onlyLines:
394         return
395     else:
396         renderer=libSalomePy.getRenderer()
397         for ln in lines:
398             actor = getActor(ln)
399             if actor is not None:
400                 renderer.RemoveActor(actor)
401                 pass
402             pass
403         ctx.DM.removeObjects(lines)
404         sg.updateObjBrowser(True)
405         pass
406     pass
407
408 # Remove all lines from all paragraphs
409 def clearAll():
410     ctx = _setContext( _getStudyId() )
411     paragraphs = ctx.DM.getParagraphs()
412     for paragr in paragraphs:
413         lines = sgPyQt.getChildren(paragr)
414         ctx.DM.removeObjects(lines)
415         renderer=libSalomePy.getRenderer()
416         for l in lines:
417             actor = getActor(l)
418             if actor is not None:
419                 renderer.RemoveActor(actor)
420                 pass
421             pass
422     sg.updateObjBrowser(True)
423     pass
424
425 # Display the selected line
426 def displayLine():
427     ctx = _setContext( _getStudyId() )
428     if sg.SelectedCount() != 1:
429         return
430     entry = sg.getSelected(0)
431     text = ctx.DM.getObject(entry).getText()
432     if text == "\n":
433         return
434     renderer=libSalomePy.getRenderer()
435     actor = getActor(entry)
436     if actor is None:
437         actor = vtk.vtkTextActor()
438         dict_actors[entry] = actor
439         pass
440     center = renderer.GetCenter()
441     actor.SetInput(str(text))
442     actor.SetPosition(center[0],center[1])
443     txtPr = vtk.vtkTextProperty()
444     txtPr.SetFontSize(30)
445     actor.SetTextProperty(txtPr)
446     for act in  dict_actors.values():
447         renderer.RemoveActor(act)
448     renderer.AddActor(actor)
449     pass
450
451 # Clear remove all lines under selected paragraph
452 def clearParagraph():
453     ctx = _setContext( _getStudyId() )
454     lines = sgPyQt.getChildren(sg.getSelected(0))
455     ctx.DM.removeObjects(lines)
456     sg.updateObjBrowser(True)
457     pass
458
459 # Erase the selected line
460 def eraseLine():
461     ctx = _setContext( _getStudyId() )
462     if sg.SelectedCount() != 1:
463         return
464     entry = sg.getSelected(0)
465     text = ctx.DM.getObject(entry).getText()
466     if text == "\n":
467         return
468     renderer=libSalomePy.getRenderer()
469     actor = getActor(entry)
470     if actor is not None:
471         renderer.RemoveActor(actor)
472         pass
473     pass
474
475 # Return vtkActor by entry
476 def getActor(entry):
477     entry = str(entry)
478     if dict_actors.has_key(entry):
479         return dict_actors[entry]
480     return None
481
482 # Define commands
483 dict_command = {
484     951 : loadfile,
485     952 : savefile,
486     961 : insertLine,
487     962 : editLine,
488     963 : removeLine,
489     964 : clearAll,
490     971 : displayLine,
491     972 : eraseLine,
492     973 : clearParagraph,
493     }
494
495 # Define actions
496 dict_actions = {
497     "loadfile"   :    951,
498     "savefile"   :    952,
499     "insertLine" :    961,
500     "editLine"   :    962,
501     "removeLine" :    963,
502     "clearAll"   :    964,
503     "displayLine":    971,
504     "eraseLine"  :    972,
505     "clearParagraph": 973,
506     }
507
508 # Define Actors
509 dict_actors = {}