📘 Cours : Création d’add-ons pour FreeCAD
Objectif de la leçon : faire en sorte que l’add-on «Box Builder» mémorise les dernières dimensions saisies et les restaure au prochain démarrage.
💾 Partie 1. Comment FreeCAD stocke-t-il les paramètres ?
FreeCAD fournit un mécanisme intégré pour stocker les paramètres utilisateur — via le Gestionnaire de paramètres.
Il fonctionne avec une base de paramètres hiérarchique, similaire au Registre Windows.
Méthodes principales :
# Obtenir un groupe de paramètres
params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/MyAddon")
# Enregistrer une valeur
params.SetFloat("LastLength", 30.0)
params.SetString("LastName", "MyBox")
# Charger une valeur (avec une valeur par défaut)
length = params.GetFloat("LastLength", 10.0) # 10.0 — si le paramètre n'existe pas
name = params.GetString("LastName", "DefaultBox")
💡 Le chemin
"User parameter:BaseApp/Preferences/..."— est l’emplacement standard pour les paramètres utilisateur.
🛠 Partie 2. Add-on mis à jour : «Box Builder avec mémoire»
Nous allons modifier l’add-on précédent en ajoutant l’enregistrement et le chargement des dernières valeurs.
Fichier box_builder_workbench.py (version mise à jour)
# box_builder_workbench.py
import FreeCAD, FreeCADGui
from PySide import QtGui, QtCore
# === CHEMIN VERS LES PARAMÈTRES ===
PARAM_PATH = "User parameter:BaseApp/Preferences/BoxBuilderAddon"
def get_saved_settings():
"""Charge les paramètres enregistrés ou renvoie les valeurs par défaut"""
params = FreeCAD.ParamGet(PARAM_PATH)
return {
"length": params.GetFloat("LastLength", 30.0),
"width": params.GetFloat("LastWidth", 20.0),
"height": params.GetFloat("LastHeight", 10.0),
"name": params.GetString("LastName", "CustomBox")
}
def save_settings(length, width, height, name):
"""Enregistre les paramètres actuels"""
params = FreeCAD.ParamGet(PARAM_PATH)
params.SetFloat("LastLength", length)
params.SetFloat("LastWidth", width)
params.SetFloat("LastHeight", height)
params.SetString("LastName", name)
# === FONCTION DE CRÉATION DE BOÎTE ===
def create_box(length, width, height, name="CustomBox"):
doc = FreeCAD.ActiveDocument
if not doc:
doc = FreeCAD.newDocument("BoxBuilder")
# Nom unique
base_name = name
index = 1
obj_name = base_name
while obj_name in [obj.Name for obj in doc.Objects]:
obj_name = f"{base_name}_{index}"
index += 1
box = doc.addObject("Part::Box", obj_name)
box.Length = length
box.Width = width
box.Height = height
doc.recompute()
return box
# === FENÊTRE DE DIALOGUE ===
class BoxBuilderDialog(QtGui.QDialog):
def __init__(self):
super(BoxBuilderDialog, self).__init__()
self.setWindowTitle("Box Builder")
self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
self.resize(300, 180)
# Charge les paramètres enregistrés
settings = get_saved_settings()
# Champs de saisie
self.length_input = QtGui.QLineEdit(str(settings["length"]))
self.width_input = QtGui.QLineEdit(str(settings["width"]))
self.height_input = QtGui.QLineEdit(str(settings["height"]))
self.name_input = QtGui.QLineEdit(settings["name"])
# Boutons
self.create_button = QtGui.QPushButton("Create Box")
self.cancel_button = QtGui.QPushButton("Cancel")
# Connexion
self.create_button.clicked.connect(self.on_create)
self.cancel_button.clicked.connect(self.reject)
# Disposition
layout = QtGui.QFormLayout()
layout.addRow("Name:", self.name_input)
layout.addRow("Length (mm):", self.length_input)
layout.addRow("Width (mm):", self.width_input)
layout.addRow("Height (mm):", self.height_input)
button_layout = QtGui.QHBoxLayout()
button_layout.addWidget(self.create_button)
button_layout.addWidget(self.cancel_button)
main_layout = QtGui.QVBoxLayout()
main_layout.addLayout(layout)
main_layout.addLayout(button_layout)
self.setLayout(main_layout)
def on_create(self):
try:
name = self.name_input.text().strip()
if not name:
name = "CustomBox"
length = float(self.length_input.text())
width = float(self.width_input.text())
height = float(self.height_input.text())
if length <= 0 or width <= 0 or height <= 0:
raise ValueError("All dimensions must be positive")
# Crée l'objet
create_box(length, width, height, name)
# Enregistre les paramètres
save_settings(length, width, height, name)
self.accept()
except ValueError as e:
QtGui.QMessageBox.warning(self, "Input Error", f"Invalid input:\n{str(e)}")
# === COMMANDE ET ENVIRONNEMENT DE TRAVAIL (sans changement) ===
class BoxBuilderCommand:
def GetResources(self):
return {"MenuText": "Box Builder", "ToolTip": "Create a box with custom dimensions"}
def Activated(self):
dialog = BoxBuilderDialog()
dialog.exec_()
def IsActive(self):
return True
class BoxBuilderWorkbench(FreeCADGui.Workbench):
MenuText = "Box Builder"
ToolTip = "Create custom boxes with GUI"
def Initialize(self):
self.list = ["BoxBuilderCommand"]
self.appendToolbar("Box Tools", self.list)
self.appendMenu("Box Builder", self.list)
def GetClassName(self):
return "Gui::PythonWorkbench"
FreeCADGui.addCommand("BoxBuilderCommand", BoxBuilderCommand())
🔍 Ce qui a changé ?
- Fonctions ajoutées :
get_saved_settings()— charge les dernières valeurssave_settings()— enregistre les valeurs actuelles
- Chemin vers les paramètres :
PARAM_PATH = "User parameter:BaseApp/Preferences/BoxBuilderAddon"
→ Tous les paramètres sont stockés dans un groupe séparé, sans interférer avec d’autres add-ons.
- Champ pour le nom ajouté à l’interface.
- Au démarrage de la fenêtre — les champs sont remplis avec les valeurs enregistrées.
- Après la création — les valeurs actuelles sont enregistrées automatiquement.
▶️ Vérification du fonctionnement
- Démarrez FreeCAD
- Ouvrez Box Builder
- Saisissez, par exemple :
- Nom :
MyTestBox - Longueur :
50 - Largeur :
30 - Hauteur :
20
- Cliquez sur Create Box
- Fermez FreeCAD
- Redémarrez
- Ouvrez Box Builder
✅ Les champs devraient être remplis avec les mêmes valeurs !
📂 Où sont stockés ces paramètres ?
- Windows : dans le registre (
HKEY_CURRENT_USER\SOFTWARE\FreeCAD\...) - Linux/macOS : dans le fichier
user.cfgà l’intérieur du dossier FreeCAD
Mais vous n’avez pas besoin de le savoir — FreeCAD gère le stockage lui-même.
🧪 Exercice pratique
- Ajoutez une case à cocher «Center on origin» et enregistrez son état entre les démarrages.
- Faites en sorte qu’au premier démarrage de l’add-on, des valeurs par défaut raisonnables soient utilisées (déjà implémenté).
- Ajoutez un bouton «Reset to defaults», qui réinitialise les champs aux valeurs par défaut et efface les paramètres enregistrés.
Indice pour la réinitialisation :
def reset_settings():
params = FreeCAD.ParamGet(PARAM_PATH)
params.RemGroup("BoxBuilderAddon") # Supprime tout le groupe
💡 Conseils
- Spécifiez toujours une valeur par défaut dans
GetFloat(),GetString()etc. - N’enregistrez pas trop — seulement ce qui est réellement nécessaire à l’utilisateur
- Utilisez un chemin unique (
BoxBuilderAddon) pour éviter les conflits avec d’autres add-ons
▶️ Et ensuite ?
Dans la Leçon 6, nous allons :
- Ajouter des icônes aux boutons et à l’environnement de travail
- Apprendre à utiliser SVG et PNG dans l’interface
- Rendre l’add-on visuellement attrayant
« `