freecad-cam/Mod/Fem/femexamples/examplesgui.py
2026-02-01 01:59:24 +01:00

272 lines
11 KiB
Python

# ***************************************************************************
# * Copyright (c) 2020 Bernd Hahnebach <bernd@bimstatik.org> *
# * Copyright (c) 2020 Sudhanshu Dubey <sudhanshu.thethunder@gmail.com> *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
"""
https://forum.freecad.org/viewtopic.php?f=10&t=48427
"""
import os
from importlib import import_module
from PySide import QtCore
from PySide import QtGui
import FreeCADGui
class FemExamples(QtGui.QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def __del__(
self,
):
# need as fix for qt event error
# --> see https://forum.freecad.org/viewtopic.php?f=18&t=10732&start=10#p86493
return
def init_ui(self):
# init widgets
self.view = QtGui.QTreeWidget()
path = os.path.dirname(os.path.realpath(__file__))
files = [f for f in os.listdir(str(path))]
not_files = [
"__init__.py",
"__pycache__",
"boxanalysis_base.py",
"ccx_cantilever_base_edge.py",
"ccx_cantilever_base_face.py",
"ccx_cantilever_base_solid.py",
"examplesgui.py",
"manager.py",
"meshes",
]
files = [str(f) for f in files if f not in not_files]
# Slicing the .py from every file
files = [f[:-3] for f in files if f.endswith(".py")]
files.sort()
files_info = {}
self.files_name = {}
constraints = set()
meshtypes = set()
mesheles = set()
solvers = set()
equations = set()
materials = set()
for f in files:
module = import_module("femexamples." + f)
if hasattr(module, "get_information"):
info = getattr(module, "get_information")()
files_info[f] = info
self.files_name[info["name"]] = f
meshtypes.add(info["meshtype"])
mesheles.add(info["meshelement"])
file_equations = info["equations"]
for equation in file_equations:
equations.add(equation)
materials.add(info["material"])
file_solvers = info["solvers"]
for solver in file_solvers:
solvers.add(solver)
file_constraints = info["constraints"]
for constraint in file_constraints:
constraints.add(constraint)
constraints = sorted(constraints)
meshtypes = sorted(meshtypes)
mesheles = sorted(mesheles)
solvers = sorted(solvers)
equations = sorted(equations)
materials = sorted(materials)
all_examples = QtGui.QTreeWidgetItem(self.view, ["All"])
for example, info in files_info.items():
QtGui.QTreeWidgetItem(all_examples, [info["name"]])
self.view.addTopLevelItem(all_examples)
all_constraints = QtGui.QTreeWidgetItem(self.view, ["Constraints"])
for constraint in constraints:
constraint_item = QtGui.QTreeWidgetItem(all_constraints, [constraint])
for example, info in files_info.items():
file_constraints = info["constraints"]
if constraint in file_constraints:
QtGui.QTreeWidgetItem(constraint_item, [info["name"]])
self.view.addTopLevelItem(all_constraints)
all_equations = QtGui.QTreeWidgetItem(self.view, ["Equations"])
for equation in equations:
equation_item = QtGui.QTreeWidgetItem(all_equations, [equation])
for example, info in files_info.items():
file_equations = info["equations"]
if equation in file_equations:
QtGui.QTreeWidgetItem(equation_item, [info["name"]])
self.view.addTopLevelItem(all_equations)
all_materials = QtGui.QTreeWidgetItem(self.view, ["Materials"])
for material in materials:
material_item = QtGui.QTreeWidgetItem(all_materials, [material])
for example, info in files_info.items():
if info["material"] == material:
QtGui.QTreeWidgetItem(material_item, [info["name"]])
self.view.addTopLevelItem(all_materials)
all_meshtypes = QtGui.QTreeWidgetItem(self.view, ["MeshTypes"])
for mesh in meshtypes:
mesh_item = QtGui.QTreeWidgetItem(all_meshtypes, [mesh])
for example, info in files_info.items():
if info["meshtype"] == mesh:
QtGui.QTreeWidgetItem(mesh_item, [info["name"]])
self.view.addTopLevelItem(all_meshtypes)
all_mesheles = QtGui.QTreeWidgetItem(self.view, ["MeshElements"])
for mesh in mesheles:
mesh_item = QtGui.QTreeWidgetItem(all_mesheles, [mesh])
for example, info in files_info.items():
if info["meshelement"] == mesh:
QtGui.QTreeWidgetItem(mesh_item, [info["name"]])
self.view.addTopLevelItem(all_mesheles)
all_solvers = QtGui.QTreeWidgetItem(self.view, ["Solvers"])
for solver in solvers:
solver_item = QtGui.QTreeWidgetItem(all_solvers, [solver])
for example, info in files_info.items():
file_solvers = info["solvers"]
if solver in file_solvers:
QtGui.QTreeWidgetItem(solver_item, [info["name"]])
self.view.addTopLevelItem(all_solvers)
self.view.setHeaderHidden(True)
self.view.itemClicked.connect(self.enable_buttons)
self.view.itemDoubleClicked.connect(self.double_clicked)
# Ok buttons:
self.button_box = QtGui.QDialogButtonBox(self)
self.button_box.setOrientation(QtCore.Qt.Horizontal)
self.setup_button = QtGui.QPushButton(QtGui.QIcon.fromTheme("document-new"), "Setup")
self.setup_button.setEnabled(False)
self.button_box.addButton(self.setup_button, QtGui.QDialogButtonBox.AcceptRole)
self.run_button = QtGui.QPushButton(QtGui.QIcon.fromTheme("system-run"), "Run")
self.run_button.setEnabled(False)
self.button_box.addButton(self.run_button, QtGui.QDialogButtonBox.ApplyRole)
self.close_button = QtGui.QPushButton(QtGui.QIcon.fromTheme("window-close"), "Close")
self.button_box.addButton(self.close_button, QtGui.QDialogButtonBox.RejectRole)
self.button_box.clicked.connect(self.clicked)
# Layout:
layout = QtGui.QGridLayout()
layout.addWidget(self.view, 2, 0, 1, 2)
layout.addWidget(self.button_box, 3, 1)
self.setLayout(layout)
def clicked(self, button):
if self.button_box.buttonRole(button) == QtGui.QDialogButtonBox.AcceptRole:
self.accept()
elif self.button_box.buttonRole(button) == QtGui.QDialogButtonBox.ApplyRole:
self.run()
elif self.button_box.buttonRole(button) == QtGui.QDialogButtonBox.RejectRole:
self.reject()
def accept(self):
QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
item = self.view.selectedItems()[0]
name = item.text(0)
example = self.files_name[name]
solver = None
parent = item.parent()
if parent is not None:
grand_parent = parent.parent()
if grand_parent is not None:
grand_parent_name = grand_parent.text(0)
if grand_parent_name == "Solvers":
solver = parent.text(0)
# if done this way the Python commands are printed in Python console
FreeCADGui.doCommand(f"from femexamples.{str(example)} import setup")
if solver is not None:
FreeCADGui.doCommand(f'setup(solvertype="{str(solver)}")')
else:
FreeCADGui.doCommand("setup()")
QtGui.QApplication.restoreOverrideCursor()
def reject(self):
self.close()
def closeEvent(self, ev):
pw = self.parentWidget()
if pw and pw.inherits("QDockWidget"):
pw.deleteLater()
def run(self):
QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
item = self.view.selectedItems()[0]
name = item.text(0)
example = self.files_name[name]
solver = None
parent = item.parent()
if parent is not None:
grand_parent = parent.parent()
if grand_parent is not None:
grand_parent_name = grand_parent.text(0)
if grand_parent_name == "Solvers":
solver = parent.text(0)
# if done this way the Python commands are printed in Python console
FreeCADGui.doCommand("from femexamples.manager import run_example")
if solver is not None:
FreeCADGui.doCommand(
f'run_example("{str(example)}", solver="{str(solver)}", run_solver=True)'
)
else:
FreeCADGui.doCommand(f'run_example("{str(example)}", run_solver=True)')
QtGui.QApplication.restoreOverrideCursor()
def enable_buttons(self):
# only enable buttons if a example is selected
sel_item_text = self.view.selectedItems()[0].text(0)
if sel_item_text in self.files_name:
self.run_button.setEnabled(True)
self.setup_button.setEnabled(True)
else:
self.run_button.setEnabled(False)
self.setup_button.setEnabled(False)
def double_clicked(self):
# setup an example when it is double clicked
sel_item_text = self.view.selectedItems()[0].text(0)
if sel_item_text in self.files_name:
self.accept()
def show_examplegui():
QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
mw = FreeCADGui.getMainWindow()
example_widget = QtGui.QDockWidget("FEM Examples", mw)
example_widget.setWidget(FemExamples())
mw.addDockWidget(QtCore.Qt.RightDockWidgetArea, example_widget)
QtGui.QApplication.restoreOverrideCursor()