Skip to content
💻 🧠 Code 1001 > 📚 Learning Materials > How to Create Addons for FreeCAD > Lesson 5. Saving and Loading Settings

Lesson 5. Saving and Loading Settings

📘 Tutorial: Creating Addons for FreeCAD

Lesson Goal: Make the “Box Builder” addon remember the last entered dimensions and restore them on the next launch.


💾 Part 1. How FreeCAD stores settings?

FreeCAD provides a built-in mechanism for storing user parameters — through the Parameter Manager.

It works with a hierarchical parameter database, similar to the Windows Registry.

Main methods:

# Get a parameter group
params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/MyAddon")

# Save a value
params.SetFloat("LastLength", 30.0)
params.SetString("LastName", "MyBox")

# Load a value (with a default value)
length = params.GetFloat("LastLength", 10.0)  # 10.0 — if such a parameter does not exist
name = params.GetString("LastName", "DefaultBox")

💡 The path "User parameter:BaseApp/Preferences/..." — is the standard location for user settings.


🛠 Part 2. Updated Addon: “Box Builder with Memory”

We will modify the previous addon by adding saving and loading of the last values.

File box_builder_workbench.py (updated version)

# box_builder_workbench.py
import FreeCAD, FreeCADGui
from PySide import QtGui, QtCore

# === PATH TO SETTINGS ===
PARAM_PATH = "User parameter:BaseApp/Preferences/BoxBuilderAddon"

def get_saved_settings():
    """Loads saved settings or returns default values"""
    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):
    """Saves current settings"""
    params = FreeCAD.ParamGet(PARAM_PATH)
    params.SetFloat("LastLength", length)
    params.SetFloat("LastWidth", width)
    params.SetFloat("LastHeight", height)
    params.SetString("LastName", name)


# === BOX CREATION FUNCTION ===
def create_box(length, width, height, name="CustomBox"):
    doc = FreeCAD.ActiveDocument
    if not doc:
        doc = FreeCAD.newDocument("BoxBuilder")

    # Unique name
    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


# === DIALOG WINDOW ===
class BoxBuilderDialog(QtGui.QDialog):
    def __init__(self):
        super(BoxBuilderDialog, self).__init__()
        self.setWindowTitle("Box Builder")
        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
        self.resize(300, 180)

        # Load saved settings
        settings = get_saved_settings()

        # Input fields
        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"])

        # Buttons
        self.create_button = QtGui.QPushButton("Create Box")
        self.cancel_button = QtGui.QPushButton("Cancel")

        # Connection
        self.create_button.clicked.connect(self.on_create)
        self.cancel_button.clicked.connect(self.reject)

        # Layout
        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")

            # Create object
            create_box(length, width, height, name)

            # Save settings
            save_settings(length, width, height, name)

            self.accept()

        except ValueError as e:
            QtGui.QMessageBox.warning(self, "Input Error", f"Invalid input:\n{str(e)}")


# === COMMAND AND WORKBENCH (unchanged) ===
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())

🔍 What has changed?

  1. Functions added:
  • get_saved_settings() — loads the last values
  • save_settings() — saves the current values
  1. Path to parameters:
   PARAM_PATH = "User parameter:BaseApp/Preferences/BoxBuilderAddon"

→ All settings are stored in a separate group, without interfering with other addons.

  1. Field for name added to the interface.
  2. When the window starts — fields are filled with saved values.
  3. After creation — current values are saved automatically.

▶️ Checking the operation

  1. Launch FreeCAD
  2. Open Box Builder
  3. Enter, for example:
  • Name: MyTestBox
  • Length: 50
  • Width: 30
  • Height: 20
  1. Click Create Box
  2. Close FreeCAD
  3. Launch again
  4. Open Box Builder

✅ The fields should be filled with the same values!


📂 Where are these settings stored?

  • Windows: in the registry (HKEY_CURRENT_USER\SOFTWARE\FreeCAD\...)
  • Linux/macOS: in the user.cfg file inside the FreeCAD folder

But you don’t need to know this — FreeCAD manages storage itself.


🧪 Practical Task

  1. Add a checkbox “Center on origin” and save its state between launches.
  2. Make sure that on the first launch of the addon, reasonable default values are used (already implemented).
  3. Add a “Reset to defaults” button that resets the fields to default values and clears saved settings.

Hint for resetting:

def reset_settings():
    params = FreeCAD.ParamGet(PARAM_PATH)
    params.RemGroup("BoxBuilderAddon")  # Removes the entire group

💡 Tips

  • Always specify a default value in GetFloat(), GetString() etc.
  • Don’t save too much — only what the user really needs
  • Use a unique path (BoxBuilderAddon) to avoid conflicts with other addons

▶️ What’s next?

In Lesson 6 we will:

  • Add icons to buttons and the workbench
  • Learn how to use SVG and PNG in the interface
  • Make the addon visually appealing

Leave a Reply

Your email address will not be published. Required fields are marked *