]> SALOME platform Git repositories - modules/yacs.git/blob - src/pyqt/gui/Appli.py
Salome HOME
mergefrom branch BR_V511_PR tag mergeto_trunk_03feb09
[modules/yacs.git] / src / pyqt / gui / Appli.py
1 #  Copyright (C) 2006-2008  CEA/DEN, EDF R&D
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.
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 """
21 import sys,os
22 from qt import *
23 import Tree
24 import PanelManager
25 import BoxManager
26 import Icons
27 import Items
28 import adapt
29 import Item
30 import logview
31 import pilot
32 import threading
33 import time
34 import CONNECTOR
35 import catalog
36 import traceback
37 import glob
38
39 class ErrorEvent(QCustomEvent):
40   def __init__(self,caption,msg):
41     QCustomEvent.__init__(self,8888)
42     self.caption=caption
43     self.msg=msg
44   def process(self,parent):
45     QMessageBox.warning(parent,self.caption,self.msg)
46
47 class Runner(threading.Thread):
48   def __init__(self,parent,executor,proc):
49     threading.Thread.__init__(self)
50     self.parent=parent
51     self.executor=executor
52     self.proc=proc
53
54   def run(self):
55     try:
56       self.executor.RunW(self.proc,0)
57     except ValueError,ex:
58       #traceback.print_exc()
59       QApplication.postEvent(self.parent, ErrorEvent('YACS execution error',str(ex)))
60
61 class Browser(QVBox):
62   def __init__(self,parent,proc):
63     QVBox.__init__(self,parent)
64     pp=Item.adapt(proc)
65     self.proc=proc
66     self.pproc=pp
67     self.hSplitter = QSplitter(self,"hSplitter")
68     self.objectBrowser=Tree.Tree(self.hSplitter,self.onSelect,self.onDblSelect)
69     self.objectBrowser.additem(pp)
70     self.panelManager=PanelManager.PanelManager(self.hSplitter)
71     self.panelManager.setRootItem(pp)
72     self.boxManager=BoxManager.BoxManager(self.hSplitter)
73     self.boxManager.setRootItem(pp)
74     self.selected=None
75     self.executor=None
76     self.resume=0
77     self.thr=None
78     self.log=logview.LogView()
79
80   def view_log(self):
81     self.log.text.setText(self.proc.getLogger("parser").getStr())
82     self.log.show()
83
84   def onDblSelect(self,item):
85     #item is instance of Item.Item
86     pass
87
88   def onSelect(self,item):
89     #item is instance of Item.Item
90     self.selected=item
91
92   def customEvent(self,ev):
93     if ev.type() == 8888:
94       ev.process(self)
95
96   def run(self):
97     if not self.executor:
98       self.executor = pilot.ExecutorSwig()
99     if self.thr and self.thr.isAlive():
100       return
101     #continue execution mode
102     self.executor.setExecMode(0)
103     #execute it in a thread
104     self.thr = Runner(self, self.executor, self.proc)
105     #as a daemon (no need to join)
106     self.thr.setDaemon(1)
107     #start the thread
108     self.thr.start()
109     time.sleep(0.1)
110     self.resume=0
111
112   def susp(self):
113     """Suspend or resume an executing schema"""
114     if not self.executor:
115       return
116     if not self.thr.isAlive():
117       return
118
119     if self.resume:
120       #continue execution mode
121       self.executor.setExecMode(0)
122       #resume it
123       self.executor.resumeCurrentBreakPoint()
124       self.resume=0
125     else:
126       #step by step execution mode
127       self.executor.setExecMode(1)
128       self.resume=1
129
130   def step(self):
131     """Step on a paused schema"""
132     if not self.executor:
133       self.executor = pilot.ExecutorSwig()
134     if not self.thr or not self.thr.isAlive():
135       #start in step by step mode
136       self.executor.setExecMode(1)
137       self.thr = Runner(self, self.executor, self.proc)
138       self.thr.setDaemon(1)
139       self.thr.start()
140       self.resume=1
141       return
142
143     #step by step execution mode
144     self.resume=1
145     self.executor.setExecMode(1)
146     #resume it
147     self.executor.resumeCurrentBreakPoint()
148
149   def stop(self):
150     """Stop the schema"""
151     if not self.executor:
152       return
153     if not self.thr.isAlive():
154       return
155     self.executor.setExecMode(1)
156     self.executor.waitPause()
157     self.executor.resumeCurrentBreakPoint()
158     #self.executor.stopExecution()
159
160 class Appli(QMainWindow):
161   """
162       Appli()
163       Cree la fenetre principale de l'interface utilisateur
164   """
165   def __init__(self):
166     QMainWindow.__init__(self)
167     self.createWidgets()
168     self.initActions()
169     self.initMenus()
170     self.initToolbar()
171     self.initStatusbar()
172     self.initYACS()
173
174   def createWidgets(self):
175     self.tabWidget = QTabWidget(self)
176     self.currentPanel=None
177     self.connect(self.tabWidget, SIGNAL('currentChanged(QWidget *)'),self.handlePanelChanged)
178     self.setCentralWidget(self.tabWidget)
179     self.resize(800,600)
180
181   def handlePanelChanged(self,panel):
182     self.currentPanel=panel
183
184   def initActions(self):
185     self.actions = []
186
187     self.newAct=QAction('New', QIconSet(Icons.get_image("new")), '&New',
188                           QKeySequence("CTRL+N"),self)
189     self.newAct.setStatusTip('Open an empty editor window')
190     self.newAct.setWhatsThis( """<b>New</b>"""
191             """<p>An empty editor window will be created.</p>""")
192     self.newAct.connect(self.newAct,SIGNAL('activated()'), self.newProc)
193     self.actions.append(self.newAct)
194
195     self.prefAct=QAction('Preferences',QIconSet(Icons.get_image("configure.png")),'&Preferences...',
196                            0, self)
197     self.prefAct.setStatusTip('Set the prefered configuration')
198     self.prefAct.setWhatsThis("""<b>Preferences</b>"""
199                               """<p>Set the configuration items of the application"""
200                               """ with your prefered values.</p>""")
201     self.prefAct.connect(self.prefAct,SIGNAL('activated()'), self.handlePreferences)
202     self.actions.append(self.prefAct)
203
204     self.runAct=QAction('Run',QIconSet(Icons.get_image("run.png")),'&Run',0,self)
205     self.runAct.connect(self.runAct,SIGNAL('activated()'), self.run)
206     self.runAct.setStatusTip('Run the selected schema')
207     self.actions.append(self.runAct)
208
209     self.suspAct=QAction('Suspend/resume',QIconSet(Icons.get_image("suspend-resume.gif")),'&Suspend/resume',0,self)
210     self.suspAct.connect(self.suspAct,SIGNAL('activated()'), self.susp)
211     self.suspAct.setStatusTip('Suspend/resume the selected schema')
212     self.actions.append(self.suspAct)
213
214     self.stepAct=QAction('Step',QIconSet(Icons.get_image("steps.png")),'&Step',0,self)
215     self.stepAct.connect(self.stepAct,SIGNAL('activated()'), self.step)
216     self.stepAct.setStatusTip('Step the selected schema')
217     self.actions.append(self.stepAct)
218
219     self.stopAct=QAction('Stop',QIconSet(Icons.get_image("kill.png")),'&Stop',0,self)
220     self.stopAct.connect(self.stopAct,SIGNAL('activated()'), self.stop)
221     self.stopAct.setStatusTip('Stop the selected schema')
222     self.actions.append(self.stopAct)
223
224     self.cataToolAct=QAction('Catalog Tool',0,self,"catatool")
225     self.cataToolAct.connect(self.cataToolAct,SIGNAL('activated()'), self.cata_tool)
226     self.actions.append(self.cataToolAct)
227
228   def initMenus(self):
229     menubar = self.menuBar()
230
231     #menu file
232     self.fileMenu=QPopupMenu(self)
233     self.newAct.addTo(self.fileMenu)
234     self.fileMenu.insertItem("&Open", self.openFile)
235     self.fileMenu.insertItem("&Open Salome", self.openSalomeFile)
236     self.loadersMenu = QPopupMenu(self)
237     self.fileMenu.insertItem("Loaders", self.loadersMenu)
238     self.loaders=[]
239     for file in glob.glob("/local/chris/SALOME2/SUPERV/YACS/BR_CC/YACS_SRC/src/pyqt/*loader.py"):
240       d,f=os.path.split(file)
241       name=f[:-9]
242       def call_loader(event,obj=self,file=file):
243         obj.openFileWithLoader(file)
244       self.loaders.append(call_loader)
245       self.loadersMenu.insertItem(name, call_loader)
246     menubar.insertItem('&File',self.fileMenu)
247
248     #menu settings
249     self.settingsMenu = QPopupMenu(self)
250     menubar.insertItem('&Settings', self.settingsMenu)
251     self.settingsMenu.insertTearOffHandle()
252     self.prefAct.addTo(self.settingsMenu)
253
254     #menu Edit
255     self.editMenu = QPopupMenu(self)
256     self.editMenu.insertItem("&Add node", self.addNode)
257     menubar.insertItem('&Edit', self.editMenu)
258
259     #menu Canvas
260     #sous menu layout
261     self.layoutMenu = QPopupMenu(self)
262     self.layoutMenu.insertItem("&Left Right", self.LR)
263     self.layoutMenu.insertItem("Right Left", self.RL)
264     self.layoutMenu.insertItem("Top Bottom", self.TB)
265     self.layoutMenu.insertItem("Bottom Top", self.BT)
266     self.canvasMenu = QPopupMenu(self)
267     self.canvasMenu.insertItem("&Zoom in", self.zoomIn)
268     self.canvasMenu.insertItem("Zoom &out", self.zoomOut)
269     self.canvasMenu.insertItem("Layout", self.layoutMenu)
270     self.canvasMenu.insertItem("Ortholinks", self.orthoLinks)
271     self.canvasMenu.insertItem("Clearlinks", self.clearLinks)
272     self.canvasMenu.insertItem("&Update", self.updateCanvas)
273     menubar.insertItem('&Canvas', self.canvasMenu)
274
275     #menu window
276     self.windowMenu = QPopupMenu(self)
277     self.cataToolAct.addTo(self.windowMenu)
278     self.windowMenu.insertItem("&Log", self.view_log)
279     menubar.insertItem('&Window', self.windowMenu)
280     self.connect(self.windowMenu, SIGNAL('aboutToShow()'), self.handleWindowMenu)
281
282     #menu help
283     self.help=QPopupMenu(self)
284     menubar.insertItem('&Help',self.help)
285     self.help.insertItem('&About',self.about,Qt.Key_F1)
286     self.help.insertItem('About &Qt',self.aboutQt)
287
288   def initYACS(self):
289     import pilot
290     import loader
291     import salomeloader
292     self.runtime= pilot.getRuntime()
293     self.loader = loader.YACSLoader()
294     self.executor = pilot.ExecutorSwig()
295     self.salomeloader=salomeloader.SalomeLoader()
296     self.loader.registerProcCataLoader()
297
298   def openSalomeFile(self):
299     fn = QFileDialog.getOpenFileName(QString.null,QString.null,self)
300     if fn.isEmpty():
301       self.statusBar().message('Loading aborted',2000)
302       return
303     fileName = str(fn)
304     proc=self.salomeloader.load(fileName)
305     logger=proc.getLogger("parser")
306     if logger.hasErrors():
307       self.logFile=logview.LogView()
308       self.logFile.text.setText(logger.getStr())
309       self.logFile.show()
310
311     panel=Browser(self.tabWidget,proc)
312     self.currentPanel=panel
313     self.tabWidget.addTab( panel,os.path.basename(fileName))
314     self.tabWidget.showPage(panel)
315
316   def openFile(self):
317     fn = QFileDialog.getOpenFileName(QString.null,QString.null,self)
318     if fn.isEmpty():
319       self.statusBar().message('Loading aborted',2000)
320       return
321     fileName = str(fn)
322     proc=self.loader.load(fileName)
323     logger=proc.getLogger("parser")
324     if logger.hasErrors():
325       self.logFile=logview.LogView()
326       self.logFile.text.setText(logger.getStr())
327       self.logFile.show()
328
329     panel=Browser(self.tabWidget,proc)
330     self.currentPanel=panel
331     self.tabWidget.addTab( panel,os.path.basename(fileName))
332     self.tabWidget.showPage(panel)
333
334   def newProc(self):
335     r=pilot.getRuntime()
336     proc=r.createProc("pr")
337     panel=Browser(self.tabWidget,proc)
338     self.currentPanel=panel
339     self.tabWidget.addTab( panel,proc.getName())
340     self.tabWidget.showPage(panel)
341
342   def openFileWithLoader(self,file):
343     d,f=os.path.split(file)
344     sys.path.insert(0,d)
345     module=__import__(os.path.splitext(f)[0])
346     del sys.path[0]
347     loader=module.Loader()
348
349     fn = QFileDialog.getOpenFileName(QString.null,QString.null,self)
350     if fn.isEmpty():
351       self.statusBar().message('Loading aborted',2000)
352       return
353     fileName = str(fn)
354     proc=loader.load(fileName)
355     logger=proc.getLogger("parser")
356     if logger.hasErrors():
357       self.logFile=logview.LogView()
358       self.logFile.text.setText(logger.getStr())
359       self.logFile.show()
360
361     panel=Browser(self.tabWidget,proc)
362     self.currentPanel=panel
363     self.tabWidget.addTab( panel,os.path.basename(fileName))
364     self.tabWidget.showPage(panel)
365
366   def cata_tool(self):
367     self.catalogTool=catalog.CatalogTool(self)
368     self.catalogTool.show()
369     return
370
371   def view_log(self):
372     if self.currentPanel:
373       self.currentPanel.view_log()
374
375   def LR(self,*args ):self.rankdir("LR")
376   def RL(self,*args ):self.rankdir("RL")
377   def TB(self,*args ):self.rankdir("TB")
378   def BT(self,*args ):self.rankdir("BT")
379
380   def rankdir(self,orient):
381     if self.currentPanel and self.currentPanel.panelManager.visible:
382       self.currentPanel.panelManager.visible.layout(orient)
383
384   def updateCanvas(self):
385     if self.currentPanel.selected:#item selected
386       if isinstance(self.currentPanel.selected,Items.ItemComposedNode):
387         #can update
388         self.currentPanel.selected.graph.editor.updateCanvas()
389
390   def addNode(self,node):
391     if self.currentPanel and self.currentPanel.selected:#item selected
392       if isinstance(self.currentPanel.selected,Items.ItemComposedNode):
393         #can add node
394         self.currentPanel.selected.addNode(node)
395
396   def zoomIn(self):
397     if self.currentPanel and self.currentPanel.panelManager.visible:
398       if isinstance(self.currentPanel.panelManager.visible,Items.ItemComposedNode):
399         #we can zoom
400         self.currentPanel.panelManager.visible.graph.editor.zoomIn()
401
402   def zoomOut(self):
403     if self.currentPanel and self.currentPanel.panelManager.visible:
404       if isinstance(self.currentPanel.panelManager.visible,Items.ItemComposedNode):
405         #we can unzoom 
406         self.currentPanel.panelManager.visible.graph.editor.zoomOut()
407
408   def orthoLinks(self):
409     if self.currentPanel and self.currentPanel.panelManager.visible:
410       if isinstance(self.currentPanel.panelManager.visible,Items.ItemComposedNode):
411         #it is a composed node with a graph
412         self.currentPanel.panelManager.visible.graph.orthoLinks()
413
414   def clearLinks(self):
415     if self.currentPanel and self.currentPanel.panelManager.visible:
416       if isinstance(self.currentPanel.panelManager.visible,Items.ItemComposedNode):
417         #it is a composed node with a graph
418         self.currentPanel.panelManager.visible.graph.clearLinks()
419
420   def handlePreferences(self):
421     pass
422
423   def handleWindowMenu(self):
424     pass
425
426   def about(self):
427     QMessageBox.about(self,'YACS browser GUI', 'YACS browser GUI')
428
429   def aboutQt(self):
430     QMessageBox.aboutQt(self,'YACS browser GUI')
431
432   def run(self):
433     if self.currentPanel:
434       self.currentPanel.run()
435
436   def susp(self):
437     if self.currentPanel:
438       self.currentPanel.susp()
439
440   def step(self):
441     if self.currentPanel:
442       self.currentPanel.step()
443
444   def stop(self):
445     if self.currentPanel:
446       self.currentPanel.stop()
447
448   def initToolbar(self):
449     tb = QToolBar(self)
450     self.newAct.addTo(tb)
451     self.runAct.addTo(tb)
452     self.suspAct.addTo(tb)
453     self.stepAct.addTo(tb)
454     self.stopAct.addTo(tb)
455     self.toolbars={}
456     self.toolbars['File']=tb
457
458   def initStatusbar(self):
459     sb = self.statusBar()
460     self.SBfile=QLabel(sb)
461     sb.addWidget(self.SBfile)
462     QWhatsThis.add(self.SBfile,
463                    """<p>Partie de la statusbar qui donne le nom"""
464                    """du fichier courant. </p>""")
465     self.SBfile.setText("")
466
467
468 if __name__ == "__main__":
469   from Item import Item
470   app = QApplication(sys.argv)
471   t=Appli()
472   t.objectBrowser.additem(Item("item1"))
473   n=t.objectBrowser.additem(Item("item2"))
474   n.additem(Item("item3"))
475   app.setMainWidget(t)
476   t.show()
477   app.exec_loop()
478
479