1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2008-2024 EDF R&D
5 # This file is part of SALOME ADAO module
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.
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.
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
21 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
25 This file centralizes the definitions and implementations of ui components used
26 in the GUI part of the module.
29 __author__ = "aribes/gboulant"
32 from PyQt5.QtCore import QObject
33 from PyQt5.QtWidgets import QScrollArea
35 sgPyQt = SalomePyQt.SalomePyQt()
37 from daUtils.enumerate import Enumerate
38 from daGuiImpl.adaoCase import AdaoCase
39 from daEficasWrapper.adaoEficasWrapper import AdaoEficasWrapper
41 from daUtils.adaoEficasEvent import *
42 from . import adaoGuiHelper
43 from . import adaoStudyEditor
44 from daUtils import adaoLogger
49 # ==============================================================================
50 # Classes to manage the building of UI components
51 # ==============================================================================
53 UI_ELT_IDS = Enumerate([
58 'SAVE_AS_ADAOCASE_ID',
59 'VALIDATE_ADAOCASE_ID',
60 'SHOWTREE_ADAOCASE_ID',
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",
79 class AdaoCaseManager(EficasObserver):
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)
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()
92 # Creation des deux managers
93 self.salome_manager = AdaoGuiUiComponentBuilder()
94 self.eficas_manager = AdaoEficasWrapper(parent=SalomePyQt.SalomePyQt().getDesktop())
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
99 self.eficas_manager.addObserver(self)
101 # Creation du GUI Eficas
102 self.eficas_manager.init_gui()
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)
112 self.eficas_viewId = sgPyQt.createView(wmType, area)
114 # On interdit que la vue soit fermee
115 # Cela simplifier grandement le code
116 sgPyQt.setViewClosable(self.eficas_viewId, False)
118 # On s'abonne au gestionnaire de selection
119 self.selection_manager = sgPyQt.getSelection()
120 self.selection_manager.currentSelectionChanged.connect(self.currentSelectionChanged)
124 # Gestion de l'activation/desactivation du module
129 self.eficas_manager.setEnabled(True)
130 sgPyQt.activateView(self.eficas_viewId)
131 self.harmonizeSelectionFromEficas()
133 def deactivate(self):
134 self.eficas_manager.setEnabled(False)
138 # Gestion de la selection entre le GUI d'Eficas
139 # et l'arbre d'etude de SALOME
143 # Depuis l'etude SALOME
144 def currentSelectionChanged(self):
146 Cette methode permet de changer le tab vu dans eficas
147 selon la selection de l'utilisateur dans l'etude SALOME
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)
158 def _processEficasTabChanged(self, eficasWrapper, eficasEvent):
160 Gestion de la synchonisation entre le tab courant d'Eficas
161 et la selection dans l'etude SALOME
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())
169 # On remet la selection dans SALOME grâce au tab dans Eficas
170 def harmonizeSelectionFromEficas(self):
172 Cette methode permet d'harmoniser la selection dans l'etude
173 grâce au tab courant d'Eficas
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
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())
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
193 def newAdaoCase(self):
194 adaoLogger.debug("Creation d'un nouveau cas adao")
195 self.eficas_manager.adaofileNew(AdaoCase())
197 def _processEficasNewEvent(self, eficasWrapper, eficasEvent):
198 adao_case = eficasEvent.callbackId
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
209 self.cases[adao_case.eficas_editor] = adao_case
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
219 # Rq: l'ouverture d'un cas adao est un cas particulier de la creation d'un cas adao
221 def openAdaoCase(self):
222 adaoLogger.debug("Ouverture d'un cas adao")
223 self.eficas_manager.adaoFileOpen(AdaoCase())
225 def _processEficasOpenEvent(self, eficasWrapper, eficasEvent):
226 self._processEficasNewEvent(eficasWrapper, eficasEvent)
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
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)
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)
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())
271 self.cases[adao_case.name] = adao_case
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
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)
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)
302 self.cases.pop(editor)
303 # Refresh GUI -> appelle currentSelectionChanged()
304 adaoGuiHelper.refreshObjectBrowser()
308 # Gestion de la validation d'un cas
309 # 1: la fonction validateAdaoCase est appelee par le GUI SALOME
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)
325 # Gestion de l'affichage de l'arbre EFICAS
326 # 1: la fonction showTreeAdaoCase est appelée par le GUI SALOME
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()
341 # Gestion de la connexion avec YACS
342 # 1: la fonction exportCaseToYACS exporte l'étude vers YACS
346 def exportCaseToYACS(self):
347 adaoLogger.debug("Export du cas vers YACS")
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():
356 msg = adao_case.exportCaseToYACS()
357 # If msg is not empty -> error found
359 adaoGuiHelper.gui_warning(SalomePyQt.SalomePyQt().getDesktop(), msg)
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.")
366 # Gestion de l'export en TUI
367 # 1: la fonction exportTUIFile exporte l'étude en TUI
371 def exportTUIFile(self):
372 adaoLogger.debug("Export du cas en TUI")
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():
381 msg = adao_case.exportTUIFile()
382 adaoGuiHelper.gui_information(SalomePyQt.SalomePyQt().getDesktop(), msg)
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.")
389 # Methodes secondaires permettant de rediriger les evenements
390 # de SALOME et d'Eficas vers les bonnes methodes de la classe
394 # Gestion des evenements venant du manager Eficas
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"
405 def processEficasEvent(self, eficasWrapper, eficasEvent):
407 Implementation of the interface EficasObserver. The implementation is a
408 switch on the possible types of events defined in EficasEvent.EVENT_TYPES.
411 functionName = self.__processOptions.get(eficasEvent.eventType, lambda : "_processEficasUnknownEvent")
412 return getattr(self,functionName)(eficasWrapper, eficasEvent)
414 def _processEficasUnknownEvent(self, eficasWrapper, eficasEvent):
415 adaoLogger.error("Unknown Eficas Event")
417 # Gestion des evenements venant du GUI de SALOME
418 def processGUIEvent(self, actionId):
420 Main switch function for ui actions processing
422 if actionId in ACTIONS_MAP:
424 functionName = ACTIONS_MAP[actionId]
425 getattr(self,functionName)()
427 traceback.print_exc()
429 adaoLogger.warning("The requested action is not implemented: " + str(actionId))
431 class AdaoGuiUiComponentBuilder:
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.
438 self.initUiComponents()
440 def initUiComponents(self):
444 # create top-level menu
445 mid = sgPyQt.createMenu( "ADAO", -1, UI_ELT_IDS.ADAO_MENU_ID, sgPyQt.defaultMenuGroup() )
447 tid = sgPyQt.createTool( "ADAO" )
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)
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", "" )
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 ) )