Salome HOME
Minor source update for OM compatibility
[modules/adao.git] / src / daSalome / daGUI / daGuiImpl / adaoGuiManager.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2008-2024 EDF R&D
4 #
5 # This file is part of SALOME ADAO module
6 #
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License.
11 #
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 # Lesser General Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
20 #
21 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #
23
24 """
25 This file centralizes the definitions and implementations of ui components used
26 in the GUI part of the module.
27 """
28
29 __author__ = "aribes/gboulant"
30
31 import traceback
32 from PyQt5.QtCore import QObject
33 from PyQt5.QtWidgets import QScrollArea
34 import SalomePyQt
35 sgPyQt = SalomePyQt.SalomePyQt()
36
37 from daUtils.enumerate import Enumerate
38 from daGuiImpl.adaoCase import AdaoCase
39 from daEficasWrapper.adaoEficasWrapper import AdaoEficasWrapper
40
41 from daUtils.adaoEficasEvent import *
42 from . import adaoGuiHelper
43 from . import adaoStudyEditor
44 from daUtils import adaoLogger
45
46 __cases__ = {}
47
48 #
49 # ==============================================================================
50 # Classes to manage the building of UI components
51 # ==============================================================================
52 #
53 UI_ELT_IDS = Enumerate([
54         'ADAO_MENU_ID',
55         'NEW_ADAOCASE_ID',
56         'OPEN_ADAOCASE_ID',
57         'SAVE_ADAOCASE_ID',
58         'SAVE_AS_ADAOCASE_ID',
59         'VALIDATE_ADAOCASE_ID',
60         'SHOWTREE_ADAOCASE_ID',
61         'CLOSE_ADAOCASE_ID',
62         'TUI_EXPORT_ID',
63         'YACS_EXPORT_ID',
64         ],offset=6950)
65
66 ACTIONS_MAP={
67     UI_ELT_IDS.NEW_ADAOCASE_ID:"newAdaoCase",
68     UI_ELT_IDS.OPEN_ADAOCASE_ID:"openAdaoCase",
69     UI_ELT_IDS.SAVE_ADAOCASE_ID:"saveAdaoCase",
70     UI_ELT_IDS.SAVE_AS_ADAOCASE_ID:"saveasAdaoCase",
71     UI_ELT_IDS.VALIDATE_ADAOCASE_ID:"validateAdaoCase",
72     UI_ELT_IDS.SHOWTREE_ADAOCASE_ID:"showTreeAdaoCase",
73     UI_ELT_IDS.CLOSE_ADAOCASE_ID:"closeAdaoCase",
74     UI_ELT_IDS.YACS_EXPORT_ID:"exportCaseToYACS",
75     UI_ELT_IDS.TUI_EXPORT_ID:"exportTUIFile",
76 }
77
78
79 class AdaoCaseManager(EficasObserver):
80   """
81   Cette classe gere les cas ADAO et coordonne les GUI de SALOME (l'etude)
82   et le GUI de l'objet Eficas (heritage du module Eficas)
83   """
84
85   def __init__(self):
86
87     # Creation d'un dictionnaire de cas
88     # Key   == ref objet editor eficas (on est sur qu'elle est unique, cas duplication)
89     # Value == objet AdaoCase()
90     self.cases = {}
91
92     # Creation des deux managers
93     self.salome_manager = AdaoGuiUiComponentBuilder()
94     self.eficas_manager = AdaoEficasWrapper(parent=SalomePyQt.SalomePyQt().getDesktop())
95
96     # On s'enregistre comme observer pour les evenements venant d'Eficas
97     # Les evenements du salome_manager viennent par le biais de la methode
98     # processGUIEvent
99     self.eficas_manager.addObserver(self)
100
101     # Creation du GUI Eficas
102     self.eficas_manager.init_gui()
103
104     # Creation du viewer QT
105     # Scroll Widget (pour les petites resolutions)
106     area = QScrollArea(SalomePyQt.SalomePyQt().getDesktop());
107     from PyQt5.QtWidgets  import QGridLayout
108     gridLayout = QGridLayout(area)
109     gridLayout.addWidget(self.eficas_manager)
110     area.setWidgetResizable(1)
111     wmType = "ADAO View"
112     self.eficas_viewId = sgPyQt.createView(wmType, area)
113
114     # On interdit que la vue soit fermee
115     # Cela simplifier grandement le code
116     sgPyQt.setViewClosable(self.eficas_viewId, False)
117
118     # On s'abonne au gestionnaire de selection
119     self.selection_manager = sgPyQt.getSelection()
120     self.selection_manager.currentSelectionChanged.connect(self.currentSelectionChanged)
121
122 ######
123 #
124 # Gestion de l'activation/desactivation du module
125 #
126 ######
127
128   def activate(self):
129     self.eficas_manager.setEnabled(True)
130     sgPyQt.activateView(self.eficas_viewId)
131     self.harmonizeSelectionFromEficas()
132
133   def deactivate(self):
134     self.eficas_manager.setEnabled(False)
135
136 #######
137 #
138 # Gestion de la selection entre le GUI d'Eficas
139 # et l'arbre d'etude de SALOME
140 #
141 #######
142
143   # Depuis l'etude SALOME
144   def currentSelectionChanged(self):
145     """
146     Cette methode permet de changer le tab vu dans eficas
147     selon la selection de l'utilisateur dans l'etude SALOME
148     """
149     adaoLogger.debug("currentSelectionChanged")
150     salomeStudyItem = adaoGuiHelper.getSelectedItem()
151     if salomeStudyItem is not None:
152       for case_editor, adao_case in self.cases.items():
153         if hasattr(salomeStudyItem,"GetID") and adao_case.salome_study_item.GetID() == salomeStudyItem.GetID():
154           self.eficas_manager.selectCase(adao_case.eficas_editor)
155           break
156
157   # Depuis Eficas
158   def _processEficasTabChanged(self, eficasWrapper, eficasEvent):
159     """
160     Gestion de la synchonisation entre le tab courant d'Eficas
161     et la selection dans l'etude SALOME
162     """
163     editor = eficasEvent.callbackId
164     for case_editor, adao_case in self.cases.items():
165       if case_editor is editor:
166         adaoGuiHelper.selectItem(adao_case.salome_study_item.GetID())
167         break
168
169   # On remet la selection dans SALOME grâce au tab dans Eficas
170   def harmonizeSelectionFromEficas(self):
171     """
172     Cette methode permet d'harmoniser la selection dans l'etude
173     grâce au tab courant d'Eficas
174     """
175     if self.cases:
176       # 1: Get current tab index in Eficas
177       editor = self.eficas_manager.getCurrentEditor()
178       # 2: sync with SALOME GUI is a tab is opened
179       if editor:
180         for case_editor, adao_case in self.cases.items():
181           if case_editor is editor:
182             adaoGuiHelper.selectItem(adao_case.salome_study_item.GetID())
183             break
184
185 #######
186 #
187 # Gestion de la creation d'un nouveau cas
188 # 1: la fonction newAdaoCase est appelee par le GUI SALOME
189 # 2: la fonction _processEficasNewEvent est appelee par le manager EFICAS
190 #
191 #######
192
193   def newAdaoCase(self):
194     adaoLogger.debug("Creation d'un nouveau cas adao")
195     self.eficas_manager.adaofileNew(AdaoCase())
196
197   def _processEficasNewEvent(self, eficasWrapper, eficasEvent):
198     adao_case = eficasEvent.callbackId
199     # Ajout dand l'etude
200     #~ salomeStudyId   = adaoGuiHelper.getActiveStudyId()
201     salomeStudyItem = adaoStudyEditor.addInStudy( adao_case ) # salomeStudyId, adao_case)
202     # Affichage correct dans l'etude
203     adaoGuiHelper.refreshObjectBrowser()
204     adaoGuiHelper.selectItem(salomeStudyItem.GetID())
205     # Finalisation des donnees du cas
206     #~ adao_case.salome_study_id   = salomeStudyId
207     adao_case.salome_study_item = salomeStudyItem
208     # Ajout du cas
209     self.cases[adao_case.eficas_editor] = adao_case
210
211 #######
212 #
213 # Gestion de l'ouverture d'un cas
214 # 1: la fonction openAdaoCase est appelee par le GUI SALOME
215 # 2: la fonction _processEficasOpenEvent est appelee par le manager EFICAS
216 #
217 #######
218
219 # Rq: l'ouverture d'un cas adao est un cas particulier de la creation d'un cas adao
220
221   def openAdaoCase(self):
222     adaoLogger.debug("Ouverture d'un cas adao")
223     self.eficas_manager.adaoFileOpen(AdaoCase())
224
225   def _processEficasOpenEvent(self, eficasWrapper, eficasEvent):
226     self._processEficasNewEvent(eficasWrapper, eficasEvent)
227
228 #######
229 #
230 # Gestion de la sauvegarde d'un cas
231 # 1: la fonction saveAdaoCase est appelee par le GUI SALOME
232 # 1 bis: la fonction saveasAdaoCase est appelee par le GUI SALOME
233 # 2: la fonction _processEficasSaveEvent est appelee par le manager EFICAS
234 #
235 #######
236
237   def saveAdaoCase(self):
238     adaoLogger.debug("Sauvegarde du cas s'il y a modification (version save)")
239     # A priori, l'utilisateur s'attend a sauvegarder le cas qui est ouvert
240     # dans le GUI d'Eficas
241     self.harmonizeSelectionFromEficas()
242     salomeStudyItem = adaoGuiHelper.getSelectedItem()
243     for case_name, adao_case in self.cases.items():
244       if hasattr(salomeStudyItem,"GetID") and adao_case.salome_study_item.GetID() == salomeStudyItem.GetID():
245         if not adao_case.isOk():
246           adaoLogger.debug("Cas invalide, donc il est sauvegarde, mais il ne peut pas etre exporte vers YACS ensuite")
247         self.eficas_manager.adaoFileSave(adao_case)
248         break
249
250   def saveasAdaoCase(self):
251     adaoLogger.debug("Sauvegarde du cas s'il y a modification (version save as)")
252     # A priori, l'utilisateur s'attend a sauvegarder le cas qui est ouvert
253     # dans le GUI d'Eficas
254     self.harmonizeSelectionFromEficas()
255     salomeStudyItem = adaoGuiHelper.getSelectedItem()
256     for case_name, adao_case in self.cases.items():
257       if hasattr(salomeStudyItem,"GetID") and adao_case.salome_study_item.GetID() == salomeStudyItem.GetID():
258         if not adao_case.isOk():
259           adaoLogger.debug("Cas invalide, donc il est sauvegarde, mais il ne peut pas etre exporte vers YACS ensuite")
260         self.eficas_manager.adaoFileSaveAs(adao_case)
261         break
262
263   def _processEficasSaveEvent(self, eficasWrapper, eficasEvent):
264     adao_case = eficasEvent.callbackId
265     # On met a jour l'etude
266     adaoStudyEditor.updateItem(adao_case.salome_study_item, adao_case) # adao_case.salome_study_id, adao_case.salome_study_item, adao_case)
267     # Affichage correct dans l'etude
268     adaoGuiHelper.refreshObjectBrowser()
269     adaoGuiHelper.selectItem(adao_case.salome_study_item.GetID())
270     # Ajout du cas
271     self.cases[adao_case.name] = adao_case
272
273 #######
274 #
275 # Gestion de la fermeture d'un cas
276 # 1: la fonction closeAdaoCase est appelee par le GUI SALOME
277 # 2: la fonction _processEficasCloseEvent est appelee par le manager EFICAS
278 #
279 #######
280
281   def closeAdaoCase(self):
282     adaoLogger.debug("Fermeture d'un cas")
283     # A priori, l'utilisateur s'attend a sauvegarder le cas qui est ouvert
284     # dans le GUI d'Eficas
285     self.harmonizeSelectionFromEficas()
286     salomeStudyItem = adaoGuiHelper.getSelectedItem()
287     for case_name, adao_case in self.cases.items():
288       if hasattr(salomeStudyItem,"GetID") and adao_case.salome_study_item.GetID() == salomeStudyItem.GetID():
289         self.eficas_manager.adaoFileClose(adao_case)
290         break
291
292   def _processEficasCloseEvent(self, eficasWrapper, eficasEvent):
293     from Extensions.param2 import originalMath
294     originalMath.toOriginal()
295     adaoLogger.debug("Destruction d'un cas")
296     editor = eficasEvent.callbackId
297     # Recuperation du cas
298     adao_case = self.cases[editor]
299     # Suppression de l'objet dans l'etude
300     adaoStudyEditor.removeItem(adao_case.salome_study_item) # adao_case.salome_study_id, adao_case.salome_study_item)
301     # Suppression du cas
302     self.cases.pop(editor)
303     # Refresh GUI -> appelle currentSelectionChanged()
304     adaoGuiHelper.refreshObjectBrowser()
305
306 #######
307 #
308 # Gestion de la validation d'un cas
309 # 1: la fonction validateAdaoCase est appelee par le GUI SALOME
310 #
311 #######
312
313   def validateAdaoCase(self):
314     adaoLogger.debug("Validation du cas par un rapport sur le JDC")
315     self.harmonizeSelectionFromEficas()
316     salomeStudyItem = adaoGuiHelper.getSelectedItem()
317     for case_name, adao_case in self.cases.items():
318       if hasattr(salomeStudyItem,"GetID") and adao_case.salome_study_item.GetID() == salomeStudyItem.GetID():
319         msg = adao_case.validationReportforJDC()
320         adaoGuiHelper.gui_information(SalomePyQt.SalomePyQt().getDesktop(), msg)
321         break
322
323 #######
324 #
325 # Gestion de l'affichage de l'arbre EFICAS
326 # 1: la fonction showTreeAdaoCase est appelée par le GUI SALOME
327 #
328 #######
329
330   def showTreeAdaoCase(self):
331     adaoLogger.debug("Validation du cas par un rapport sur le JDC")
332     self.harmonizeSelectionFromEficas()
333     salomeStudyItem = adaoGuiHelper.getSelectedItem()
334     for case_name, adao_case in self.cases.items():
335       if hasattr(salomeStudyItem,"GetID") and adao_case.salome_study_item.GetID() == salomeStudyItem.GetID():
336         msg = adao_case.showTreeAdaoCase()
337         break
338
339 #######
340 #
341 # Gestion de la connexion avec YACS
342 # 1: la fonction exportCaseToYACS exporte l'étude vers YACS
343 #
344 #######
345
346   def exportCaseToYACS(self):
347     adaoLogger.debug("Export du cas vers YACS")
348
349     # A priori, l'utilisateur s'attend a exporter le cas qui est ouvert
350     # dans le GUI d'Eficas
351     self.harmonizeSelectionFromEficas()
352     salomeStudyItem = adaoGuiHelper.getSelectedItem()
353     for case_name, adao_case in self.cases.items():
354       if hasattr(salomeStudyItem,"GetID") and adao_case.salome_study_item.GetID() == salomeStudyItem.GetID():
355         if adao_case.isOk():
356           msg = adao_case.exportCaseToYACS()
357           # If msg is not empty -> error found
358           if msg != "":
359             adaoGuiHelper.gui_warning(SalomePyQt.SalomePyQt().getDesktop(), msg)
360         else:
361           adaoGuiHelper.gui_warning(SalomePyQt.SalomePyQt().getDesktop(), "ADAO/EFICAS case can't be exported to ADAO/YACS, it is incomplete or invalid. Please return to ADAO/EFICAS edition stage.")
362         break
363
364 #######
365 #
366 # Gestion de l'export en TUI
367 # 1: la fonction exportTUIFile exporte l'étude en TUI
368 #
369 #######
370
371   def exportTUIFile(self):
372     adaoLogger.debug("Export du cas en TUI")
373
374     # A priori, l'utilisateur s'attend a exporter le cas qui est ouvert
375     # dans le GUI d'Eficas
376     self.harmonizeSelectionFromEficas()
377     salomeStudyItem = adaoGuiHelper.getSelectedItem()
378     for case_name, adao_case in self.cases.items():
379       if hasattr(salomeStudyItem,"GetID") and adao_case.salome_study_item.GetID() == salomeStudyItem.GetID():
380         if adao_case.isOk():
381           msg = adao_case.exportTUIFile()
382           adaoGuiHelper.gui_information(SalomePyQt.SalomePyQt().getDesktop(), msg)
383         else:
384           adaoGuiHelper.gui_warning(SalomePyQt.SalomePyQt().getDesktop(), "ADAO/EFICAS case can't be exported to ADAO/TUI, it is incomplete or invalid. Please return to ADAO/EFICAS edition stage.")
385         break
386
387 #######
388 #
389 # Methodes secondaires permettant de rediriger les evenements
390 # de SALOME et d'Eficas vers les bonnes methodes de la classe
391 #
392 #######
393
394   # Gestion des evenements venant du manager Eficas
395   __processOptions={
396       EficasEvent.EVENT_TYPES.CLOSE      : "_processEficasCloseEvent",
397       EficasEvent.EVENT_TYPES.SAVE       : "_processEficasSaveEvent",
398       EficasEvent.EVENT_TYPES.NEW        : "_processEficasNewEvent",
399       EficasEvent.EVENT_TYPES.CLOSE      : "_processEficasCloseEvent",
400       EficasEvent.EVENT_TYPES.OPEN       : "_processEficasOpenEvent",
401       EficasEvent.EVENT_TYPES.TABCHANGED : "_processEficasTabChanged",
402       EficasEvent.EVENT_TYPES.REOPEN     : "_processEficasReOpenEvent"
403       }
404
405   def processEficasEvent(self, eficasWrapper, eficasEvent):
406       """
407       Implementation of the interface EficasObserver. The implementation is a
408       switch on the possible types of events defined in EficasEvent.EVENT_TYPES.
409       @overload
410       """
411       functionName = self.__processOptions.get(eficasEvent.eventType, lambda : "_processEficasUnknownEvent")
412       return getattr(self,functionName)(eficasWrapper, eficasEvent)
413
414   def _processEficasUnknownEvent(self, eficasWrapper, eficasEvent):
415     adaoLogger.error("Unknown Eficas Event")
416
417   # Gestion des evenements venant du GUI de SALOME
418   def processGUIEvent(self, actionId):
419     """
420     Main switch function for ui actions processing
421     """
422     if actionId in ACTIONS_MAP:
423       try:
424           functionName = ACTIONS_MAP[actionId]
425           getattr(self,functionName)()
426       except:
427           traceback.print_exc()
428     else:
429       adaoLogger.warning("The requested action is not implemented: " + str(actionId))
430
431 class AdaoGuiUiComponentBuilder:
432     """
433     The initialisation of this class creates the graphic components involved
434     in the GUI (menu, menu item, toolbar). A ui component builder should be
435     created for each opened study and associated to its context.
436     """
437     def __init__(self):
438         self.initUiComponents()
439
440     def initUiComponents(self):
441
442         objectTR = QObject()
443
444         # create top-level menu
445         mid = sgPyQt.createMenu( "ADAO", -1, UI_ELT_IDS.ADAO_MENU_ID, sgPyQt.defaultMenuGroup() )
446         # create toolbar
447         tid = sgPyQt.createTool( "ADAO" )
448
449         a = sgPyQt.createAction( UI_ELT_IDS.NEW_ADAOCASE_ID, "New case", "New case", "Create a new ADAO case", "eficas_new.png" )
450         sgPyQt.createMenu(a, mid)
451         sgPyQt.createTool(a, tid)
452         a = sgPyQt.createAction( UI_ELT_IDS.OPEN_ADAOCASE_ID, "Open a case", "Open a case", "Open an ADAO case", "eficas_open.png" )
453         sgPyQt.createMenu(a, mid)
454         sgPyQt.createTool(a, tid)
455         a = sgPyQt.createAction( UI_ELT_IDS.SAVE_ADAOCASE_ID, "Save the case", "Save the case", "Save the ADAO case", "eficas_save.png" )
456         sgPyQt.createMenu(a, mid)
457         sgPyQt.createTool(a, tid)
458         a = sgPyQt.createAction( UI_ELT_IDS.SAVE_AS_ADAOCASE_ID, "Save the case as", "Save the case as", "Save the ADAO case as", "eficas_saveas.png" )
459         sgPyQt.createMenu(a, mid)
460         sgPyQt.createTool(a, tid)
461         a = sgPyQt.createAction( UI_ELT_IDS.VALIDATE_ADAOCASE_ID, "Validate the case", "Validate the case", "Validate the ADAO case", "eficas_valid.png" )
462         sgPyQt.createMenu(a, mid)
463         sgPyQt.createTool(a, tid)
464         a = sgPyQt.createAction( UI_ELT_IDS.SHOWTREE_ADAOCASE_ID, "Show tree", "Show tree", "Show the commands tree", "eficas_tree.png" )
465         sgPyQt.createMenu(a, mid)
466         sgPyQt.createTool(a, tid)
467         a = sgPyQt.createAction( UI_ELT_IDS.TUI_EXPORT_ID, "Export the case to TUI", "Export the case to TUI", "Generate the ADAO TUI version of this case", "eficas_totui.png" )
468         sgPyQt.createMenu(a, mid)
469         sgPyQt.createTool(a, tid)
470         a = sgPyQt.createAction( UI_ELT_IDS.CLOSE_ADAOCASE_ID, "Close the case", "Close the case", "Close the ADAO case", "eficas_close.png" )
471         sgPyQt.createMenu(a, mid)
472         sgPyQt.createTool(a, tid)
473         a = sgPyQt.createAction( UI_ELT_IDS.YACS_EXPORT_ID, "Export the case to YACS", "Export the case to YACS", "Generate the YACS graph to execute this case", "eficas_yacs.png" )
474         sgPyQt.createMenu(a, mid)
475         sgPyQt.createTool(a, tid)
476
477         # the following action are used in context popup
478         a = sgPyQt.createAction( UI_ELT_IDS.CLOSE_ADAOCASE_ID, "Close the case", "Close the case", "Close the ADAO case", "" )
479         a = sgPyQt.createAction( UI_ELT_IDS.YACS_EXPORT_ID, "Export the case to YACS", "Export the case to YACS", "Generate the YACS graph to execute this case", "" )
480
481     def createPopupMenuOnItem(self,popup,item): # salomeSudyId, item):
482         if adaoStudyEditor.isValidAdaoCaseItem(item): # Attention : appel ancien avec un coquille (StudyId) : (salomeSudyId, item):
483           popup.addAction( sgPyQt.action( UI_ELT_IDS.CLOSE_ADAOCASE_ID ) )
484           popup.addAction( sgPyQt.action( UI_ELT_IDS.YACS_EXPORT_ID ) )
485         return popup