Salome HOME
porting to SALOME 9.3: 2to3
[modules/hydrosolver.git] / src / HYDROGUI / HYDROSOLVERGUI.py
1 #  Copyright (C) 2012-2013 EDF
2 #
3 #  This file is part of SALOME HYDRO module.
4 #
5 #  SALOME HYDRO module is free software: you can redistribute it and/or modify
6 #  it under the terms of the GNU General Public License as published by
7 #  the Free Software Foundation, either version 3 of the License, or
8 #  (at your option) any later version.
9 #
10 #  SALOME HYDRO module is distributed in the hope that it will be useful,
11 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #  GNU General Public License for more details.
14 #
15 #  You should have received a copy of the GNU General Public License
16 #  along with SALOME HYDRO module.  If not, see <http://www.gnu.org/licenses/>.
17
18 import sys
19 import os
20 import traceback
21 import logging
22
23 from PyQt5.QtWidgets import QMessageBox, QApplication, QDialog
24
25 import salome
26 import SALOME
27 import SalomePyQt
28 sgPyQt = SalomePyQt.SalomePyQt()
29 from salome.kernel.studyedit import getStudyEditor
30 from salome.kernel.logger import Logger
31 from salome.kernel import termcolor
32 logger = Logger("HYDROGUI", color = termcolor.BLUE)
33 #logger.setLevel(logging.ERROR)
34
35 import HYDROSOLVER_ORB
36
37 from salome.hydro.interpolz_gui import InterpolzDlg
38 from salome.hydro.assignStrickler_gui import assignStricklerDlg
39 from salome.hydro.gui_utils import HSGUIException, wait_cursor, \
40                                    get_and_check_selected_file_path
41 import salome.hydro.study as hydro_study
42 from salome.hydro.run_study.eficas.appli import EficasForRunStudyAppli
43 from salome.hydro.param_study.eficas.appli import EficasForParamStudyAppli
44 from salome.hydro.telma.eficas.appli import EficasForTelmaAppli
45 from salome.hydro.run_study.gui import create_case_study, \
46                                    run_selected_case_study, \
47                                    edit_selected_case_study, \
48                                    generate_job_for_selected_case_study
49 from eficasSalome import runEficas
50
51 from BndConditionsDialog import BoundaryConditionsDialog
52 from LiquidBoundariesDialog import LiquidBoundariesDialog
53 from BreachesDialog import BreachesDialog
54 from InitialConditionsDialog import InitialConditionsDialog
55
56 ################################################
57 # GUI context class
58 # Used to store actions, menus, toolbars, etc...
59 ################################################
60
61 class GUIcontext:
62   
63     # --- menus/toolbars/actions IDs
64     
65     HYDRO_MENU_ID = 90
66     CREATE_STUDY_ID = 951
67     EDIT_STUDY_ID = 952
68     RUN_STUDY_ID = 953
69     GEN_STUDY_BATCH_ID = 954
70
71     CREATE_TELMA_CAS_ID = 955
72     EDIT_TELMA_CAS_ID = 956
73
74     GENERATE_INTERPOLZ_PY_ID = 957
75     GENERATE_ASSIGNSTRICKLER_PY_ID = 958
76
77     # TODO Add create and edit ?
78     EDIT_BOUNDARY_CONDITIONS_FILE_ID = 959
79     EDIT_LIQUID_BOUNDARY_FILE_ID = 960
80     EDIT_BREACHES_FILE_ID = 961
81     EDIT_INITIAL_CONDITIONS_FILE_ID = 962
82
83     CREATE_PARAM_STUDY_ID = 963
84     EDIT_PARAM_STUDY_ID = 964
85     GEN_PARAM_STUDY_PYTHON_ID = 965
86     GEN_PARAM_STUDY_YACS_ID = 966
87
88     def __init__(self):
89         # create top-level menu
90         mid = sgPyQt.createMenu("Hydro", -1, GUIcontext.HYDRO_MENU_ID,
91                                 sgPyQt.defaultMenuGroup())
92         # create toolbar
93         tid = sgPyQt.createTool("Hydro")
94         # create actions and fill menu and toolbar with actions
95         act = sgPyQt.createAction(\
96                 GUIcontext.GENERATE_INTERPOLZ_PY_ID,
97                 "Generate interpolz.py",
98                 "Generate interpolz.py",
99                 "Generate interpolation script for altitudes",
100                 "generate_interpolz_py.png")
101         sgPyQt.createMenu(act, mid)
102         sgPyQt.createTool(act, tid)
103
104         act = sgPyQt.createAction(\
105                 GUIcontext.GENERATE_ASSIGNSTRICKLER_PY_ID,
106                 "Generate assignStrickler.py",
107                 "Generate assignStrickler.py",
108                 "Generate assignation script for bottom friction coefficients",
109                  "generate_interpolz_py.png" )
110         sgPyQt.createMenu( act, mid )
111         sgPyQt.createTool( act, tid )
112         
113         act = sgPyQt.createSeparator()
114
115         act = sgPyQt.createAction(\
116                 GUIcontext.EDIT_BOUNDARY_CONDITIONS_FILE_ID,
117                 "Edit boundary conditions file",
118                 "Edit boundary conditions file",
119                 "Create/edit the boundary conditions file for Telemac",
120                 "edit_boundary_conditions_file.png")
121         sgPyQt.createMenu(act, mid)
122         sgPyQt.createTool(act, tid)
123
124         act = sgPyQt.createAction(\
125                 GUIcontext.EDIT_LIQUID_BOUNDARY_FILE_ID,
126                 "Edit liquid boundary conditions file",
127                 "Edit liquid boundary conditions file",
128                 "Create/edit the liquid boundary conditions file for Telemac",
129                 "edit_liquid_boundary_conditions_file.png")
130         sgPyQt.createMenu(act, mid)
131         sgPyQt.createTool(act, tid)
132
133         act = sgPyQt.createAction(\
134                 GUIcontext.EDIT_BREACHES_FILE_ID,
135                 "Edit breaches file",
136                 "Edit breaches file",
137                 "Create/edit the breaches file for Telemac",
138                 "edit_breaches_file.png")
139         sgPyQt.createMenu(act, mid)
140         sgPyQt.createTool(act, tid)
141         
142         act = sgPyQt.createAction(\
143                 GUIcontext.EDIT_INITIAL_CONDITIONS_FILE_ID,
144                 "Edit initial conditions file",
145                 "Edit initial conditions file",
146                 "Create/edit the initial conditions file for Telemac",
147                 "edit_boundary_conditions_file.png" )
148         sgPyQt.createMenu( act, mid )
149         sgPyQt.createTool( act, tid )
150
151         act = sgPyQt.createAction(\
152                 GUIcontext.CREATE_TELMA_CAS_ID,
153                 "Edit cas file (English)",
154                 "Edit cas file (English)",
155                 "Create/edit act .cas file for Telemac (English)",
156                 "create_telma_cas.png")
157         sgPyQt.createMenu(act, mid)
158         sgPyQt.createTool(act, tid)
159
160         act = sgPyQt.createAction(\
161                 GUIcontext.CREATE_STUDY_ID,
162                 "Execute a steering file",
163                 "Execute a steering file",
164                 "Fill formular for a normal execution",
165                 "create_study.png")
166
167         sgPyQt.createMenu(act, mid)
168         sgPyQt.createTool(act, tid)
169
170         act = sgPyQt.createAction(\
171                 GUIcontext.CREATE_PARAM_STUDY_ID,
172                 "Create Parameter Study",
173                 "Create Parameter Study",
174                 "Create act new Parameter Study",
175                 "create_param_study.png")
176         sgPyQt.createMenu(act, mid)
177         sgPyQt.createTool(act, tid)
178
179         act = sgPyQt.createSeparator()
180
181         # the following action are used in context popup
182
183         sgPyQt.createAction(\
184                 GUIcontext.EDIT_PARAM_STUDY_ID,
185                 "Edit param study",
186                 "Edit param study",
187                 "Edit study using python launcher")
188         sgPyQt.createAction(\
189                 GUIcontext.GEN_PARAM_STUDY_PYTHON_ID,
190                 "Generate Python script",
191                 "Generate Python script",
192                 "Generate act Python script from the eficas date")
193         sgPyQt.createAction(\
194                 GUIcontext.GEN_PARAM_STUDY_YACS_ID,
195                 "Generate YACS script",
196                 "Generate YACS script",
197                 "Generate act YACS script from the eficas date")
198
199         sgPyQt.createAction(\
200                 GUIcontext.RUN_STUDY_ID,
201                 "Compute study",
202                 "Compute study",
203                 "Compute study using python launcher")
204         sgPyQt.createAction(\
205                 GUIcontext.EDIT_STUDY_ID,
206                 "Edit study",
207                 "Edit study",
208                 "Edit the selected study")
209         sgPyQt.createAction(\
210                 GUIcontext.GEN_STUDY_BATCH_ID,
211                 "Generate batch job",
212                 "Generate batch job",
213                 "Generate a batch job to run the selected study")
214
215         sgPyQt.createAction(\
216                 GUIcontext.EDIT_TELMA_CAS_ID,
217                 "Edit Steering file",
218                 "Edit Steering file",
219                 "Edit a Telemac-Mascaret steering file")
220
221
222 ################################################
223 # Global variables
224 ################################################
225
226 # study-to-context map
227 __study2context__ = {}
228 # current context
229 __current_context__ = None
230 # object counter
231 __objectid__ = 0
232
233 ################################################
234 # Internal methods
235 ################################################
236
237 ###
238 # get active study ID
239 ###
240 def _getStudyId():
241     return sgPyQt.getStudyId()
242
243 ###
244 # get active study
245 ###
246 def _getStudy():
247     studyId = _getStudyId()
248     study = getStudyManager().GetStudyByID(studyId)
249     return study
250
251 ###
252 # returns True if object has children
253 ###
254 def _hasChildren(sobj):
255     if sobj:
256         study = _getStudy()
257         iter  = study.NewChildIterator(sobj)
258         while iter.More():
259             name = iter.Value().GetName()
260             if name:
261                 return True
262             iter.Next()
263             pass
264         pass
265     return False
266
267 ###
268 # get current GUI context
269 ###
270 def _getContext():
271     global __current_context__
272     return __current_context__
273
274 ###
275 # set and return current GUI context
276 # study ID is passed as parameter
277 ###
278 def _setContext(studyID):
279     global __study2context__, __current_context__
280     if studyID not in __study2context__:
281         __study2context__[studyID] = GUIcontext()
282         pass
283     __current_context__ = __study2context__[studyID]
284     return __current_context__
285
286 ###
287 # increment object counter in the map
288 ###
289 def _incObjToMap(m, id):
290     if id not in m: m[id] = 0
291     m[id] += 1
292     pass
293
294 ################################################
295 # Callback functions
296 ################################################
297
298 # called when module is activated
299 # returns True if activating is successfull and False otherwise
300 def activate():
301     ctx = _setContext(_getStudyId())
302     return True
303
304 # called when module is deactivated
305 def deactivate():
306     pass
307
308 # called when active study is changed
309 # active study ID is passed as parameter
310 def activeStudyChanged(studyID):
311     ctx = _setContext(_getStudyId())
312     pass
313
314 # called when popup menu is invoked
315 # popup menu and menu context are passed as parameters
316 def createPopupMenu(popup, context):
317     ed = getStudyEditor()
318     _setContext(ed.studyId)
319     if salome.sg.SelectedCount() == 1:
320         # one object is selected
321         sobj = ed.study.FindObjectID(salome.sg.getSelected(0))
322         selectedType = ed.getTypeId(sobj)
323         if selectedType == hydro_study.TELMA_TYPE_ID:
324             popup.addAction(sgPyQt.action(GUIcontext.EDIT_TELMA_CAS_ID))
325         elif selectedType == hydro_study.PARAM_STUDY_TYPE_ID:
326             popup.addAction(sgPyQt.action(GUIcontext.EDIT_PARAM_STUDY_ID))
327             popup.addAction(sgPyQt.action(GUIcontext.GEN_PARAM_STUDY_PYTHON_ID))
328             popup.addAction(sgPyQt.action(GUIcontext.GEN_PARAM_STUDY_YACS_ID))
329         elif selectedType == hydro_study.STUDY_TYPE_ID:
330             popup.addAction(sgPyQt.action(GUIcontext.EDIT_STUDY_ID))
331             popup.addAction(sgPyQt.action(GUIcontext.RUN_STUDY_ID))
332             popup.addAction(sgPyQt.action(GUIcontext.GEN_STUDY_BATCH_ID))
333
334 # called when GUI action is activated
335 # action ID is passed as parameter
336 def OnGUIEvent(commandID):
337     try:
338         dict_command[commandID]()
339     except HSGUIException as exc:
340         QMessageBox.critical(sgPyQt.getDesktop(),
341                                    QApplication.translate("OnGUIEvent", "Error"),
342                                    str(exc))
343     except:
344         logger.exception("Unhandled exception caught in HYDROSOLVER GUI")
345         msg = QApplication.translate("OnGUIEvent",
346             "Unhandled error happened in HYDROSOLVER module. Please report a bug on "
347             '<a href="https://forge-pleiade.der.edf.fr/projects/salome-rex/issues">SALOME bugtracker</a>, '
348             'category "HYDROSOLVER", describing how you got there and including the following traceback:')
349         msgBox = QMessageBox(QMessageBox.Critical,
350                                    QApplication.translate("OnGUIEvent", "Error"),
351                                    msg,
352                                    parent=sgPyQt.getDesktop())
353         msgBox.setDetailedText(traceback.format_exc())
354         msgBox.exec_()
355
356 ################################################
357 # GUI actions implementation
358 ################################################
359
360 ###
361 # Open Eficas for a new parametric study
362 ###
363 def create_param_study():
364     EficasForParamStudyAppli()
365 ###
366 # Open Eficas to edit a new parametric study
367 ###
368 def edit_param_study():
369     EficasForParamStudyAppli(get_and_check_selected_file_path())
370
371 ###
372 # Generate a python script from the eficas file
373 ###
374 def generate_param_study_python():
375     try:
376         with wait_cursor:
377             ed = hydro_study.HydroStudyEditor()
378             sobj = get_and_check_selected_file_path()
379             ed.generate_study_script(sobj)
380     except SALOME.SALOME_Exception as exc:
381         salome.sg.updateObjBrowser(0)
382         msg = str(QApplication.translate("generate_telemac2d_python",
383                       "An error happened while trying to generate telemac2d Python script:"))
384         msg += "\n" + exc.details.text
385         raise HSGUIException(msg)
386
387 ###
388 # Generate a python script from the eficas file
389 ###
390 def generate_param_study_yacs():
391     try:
392         with wait_cursor:
393             ed = hydro_study.HydroStudyEditor()
394             sobj = get_and_check_selected_file_path()
395             ed.generate_study_yacs(sobj)
396     except SALOME.SALOME_Exception as exc:
397         salome.sg.updateObjBrowser(0)
398         msg = str(QApplication.translate("generate_telemac2d_yacs",
399                       "An error happened while trying to generate telemac2d Python script:"))
400         msg += "\n" + exc.details.text
401         raise HSGUIException(msg)
402
403 def open_schema_in_yacs():
404     ed = getStudyEditor()
405     sobj = ed.study.FindObjectID(salome.sg.getSelected(0))
406     filename = sobj.GetComment()
407     if filename.endswith(".comm"):
408         filename = filename[:-5] + ".xml"
409     if not os.path.isfile(filename):
410         raise HSGUIException(QApplication.translate("open_schema_in_yacs",
411                                   "Schema file %1 does not exist").arg(filename))
412     yg = salome.ImportComponentGUI("YACS")
413     yg.loadSchema(filename)
414
415 ###
416 # Open dialog for boundary conditions edition
417 ###
418 def edit_boundary_conditions_file():
419     desktop = sgPyQt.getDesktop()
420     dlg = BoundaryConditionsDialog(desktop)
421     dlg.exec_()
422
423 ###
424 # Open dialog for liquid boundaries edition
425 ###
426 def edit_liquid_boundaries_file():
427     desktop = sgPyQt.getDesktop()
428     dlg = LiquidBoundariesDialog(desktop)
429     dlg.exec_()
430
431 ###
432 # Open dialog for breaches edition
433 ###
434 def edit_breaches_file():
435     desktop = sgPyQt.getDesktop()
436     dlg = BreachesDialog(desktop)
437     dlg.exec_()
438
439 ###
440 # Open dialog for initial conditions edition
441 ###
442 def edit_initial_conditions_file():
443     desktop = sgPyQt.getDesktop()
444     dlg = InitialConditionsDialog(desktop)
445     dlg.exec_()
446
447 ###
448 # Open dialog for liquid boundary conditions edition
449 ###
450 def edit_liquid_boundary_file():
451     # TODO: Implement gui
452     QMessageBox.warning(sgPyQt.getDesktop(),
453                         "",
454                         "Liquid boundary file handling not implemented yet")
455     return
456
457 ###
458 # Open dialog for breaches file edition
459 ###
460 def edit_breaches_file():
461     # TODO: Implement gui
462     QMessageBox.warning(sgPyQt.getDesktop(),
463                         "",
464                         "Breaches file handling not implemented yet")
465     return
466
467 ###
468 # Open dialog for interpolz.py script generation
469 ###
470 def generate_interpolz_py():
471     desktop = sgPyQt.getDesktop()
472     dlg = InterpolzDlg(desktop)
473     dlg.show()
474
475 ###
476 # Open dialog for assignStrickler.py script generation
477 ###
478 def generate_assignStrickler_py():
479     desktop = sgPyQt.getDesktop()
480     dlg = assignStricklerDlg(desktop)
481     dlg.show()
482
483 ###
484 # Open dialog for boundary conditions edition
485 ###
486 def generate_interpolks_py():
487     QMessageBox.warning(sgPyQt.getDesktop(),
488                         "",
489                         "Generation of interpolks.py not implemented yet")
490     return
491
492 ###
493 # Open dialog for creation of steering file
494 ###
495 def create_telma_cas():
496     EficasForTelmaAppli(code='TELEMAC', lang='en')
497
498 ###
499 # Open dialog for edition of steering file
500 ###
501 def edit_telma_cas():
502     # TODO: See how to detect module
503     EficasForTelmaAppli(fichier=get_and_check_selected_file_path(),
504                         code='TELEMAC', lang='en')
505
506 ###
507 # Commands dictionary
508 ###
509 dict_command = {
510     GUIcontext.CREATE_STUDY_ID: create_case_study,
511     GUIcontext.EDIT_STUDY_ID: edit_selected_case_study,
512     GUIcontext.RUN_STUDY_ID: run_selected_case_study,
513     GUIcontext.GEN_STUDY_BATCH_ID: generate_job_for_selected_case_study,
514     GUIcontext.CREATE_TELMA_CAS_ID: create_telma_cas,
515     GUIcontext.EDIT_TELMA_CAS_ID: edit_telma_cas,
516     GUIcontext.GENERATE_INTERPOLZ_PY_ID: generate_interpolz_py,
517     GUIcontext.GENERATE_ASSIGNSTRICKLER_PY_ID: generate_assignStrickler_py,
518     GUIcontext.EDIT_LIQUID_BOUNDARY_FILE_ID: edit_liquid_boundary_file,
519     GUIcontext.EDIT_BOUNDARY_CONDITIONS_FILE_ID: edit_boundary_conditions_file,
520     GUIcontext.EDIT_BREACHES_FILE_ID: edit_breaches_file,
521     GUIcontext.EDIT_INITIAL_CONDITIONS_FILE_ID: edit_initial_conditions_file,
522     GUIcontext.CREATE_PARAM_STUDY_ID: create_param_study,
523     GUIcontext.EDIT_PARAM_STUDY_ID: edit_param_study,
524     GUIcontext.GEN_PARAM_STUDY_PYTHON_ID: generate_param_study_python,
525     GUIcontext.GEN_PARAM_STUDY_YACS_ID: generate_param_study_yacs,
526     }