Add Custom UI Dialogs and Buttons to FreeCAD

Extending FreeCAD with custom user interface elements allows users and developers to automate workflows, solicit user input, and streamline complex modeling tasks. This guide explains how to build custom user interface dialogs using Python and PySide (Qt) and how to integrate them into FreeCAD as clickable toolbar buttons using FreeCAD’s native command architecture.


Understanding the Architecture

FreeCAD's graphical interface is built on the Qt framework, exposed to Python through the PySide library (PySide2 in FreeCAD 0.19–0.21, and transitioning to PySide6 in FreeCAD 1.0).

Adding custom UI functionality involves two main components:

  1. The Command Class: A Python class that defines the button's icon, tooltip, text, and click action, registered into FreeCAD's GUI.
  2. The UI Dialog: A modal or non-modal window created via PySide to gather user input or display data.

Step 1: Create the PySide Dialog

You can build dialogs programmatically or design them using Qt Designer and load the .ui file. The following example builds a simple dialog entirely in Python:

from PySide import QtWidgets, QtCore

class CustomInputDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(CustomInputDialog, self).__init__(parent)
        self.setWindowTitle("Custom Parameter Input")
        self.resize(300, 150)

        # Create Layout
        layout = QtWidgets.QVBoxLayout(self)

        # Add Label and Line Edit
        self.label = QtWidgets.QLabel("Enter Dimension (mm):")
        layout.addWidget(self.label)

        self.input_field = QtWidgets.QLineEdit()
        layout.addWidget(self.input_field)

        # Add Standard OK/Cancel Buttons
        self.button_box = QtWidgets.QDialogButtonBox(
            QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel
        )
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

    def get_value(self):
        return self.input_field.text()

Step 2: Define the FreeCAD Command

FreeCAD requires a specific class structure to represent an action. The class must implement GetResources() to define appearance and Activated() to handle execution.

import FreeCAD as App
import FreeCADGui as Gui

class CustomToolCommand:
    def GetResources(self):
        return {
            'Pixmap': 'Std_Tool1',  # Built-in icon name or absolute path to a .svg/.png
            'MenuText': 'Open Input Dialog',
            'ToolTip': 'Opens a custom dialog to enter dimensions'
        }

    def Activated(self):
        # Retrieve the main FreeCAD window as the parent
        main_window = Gui.getMainWindow()
        
        # Instantiate and display the dialog
        dialog = CustomInputDialog(main_window)
        if dialog.exec_():
            user_value = dialog.get_value()
            App.Console.PrintMessage(f"User entered: {user_value}\n")

    def IsActive(self):
        # Optional: return False if no document is open
        return App.ActiveDocument is not None

Step 3: Register the Command and Add the Button

To make the command accessible to the user, register it with the GUI system and append it to a toolbar or workbench.

Register the Command

Gui.addCommand('CustomTool_Command', CustomToolCommand())

Add to an Existing Workbench Toolbar

To immediately test the button, you can inject it into an active workbench's toolbar directly via the Python console or a macro:

# Add to the current workbench toolbar
workbench = Gui.activeWorkbench()
workbench.addToolbarItem("Custom Tools", ["CustomTool_Command"])

Making the Customization Persistent

To ensure your custom buttons and dialogs persist across FreeCAD sessions:

  1. Save as a Macro: Save the complete script into your FreeCAD macro directory (accessible via Macro > Macros...).
  2. Add to a Custom Toolbar via UI:
    • Go to Tools > Customize > Toolbars.
    • Select a workbench where the button should appear.
    • Click New to create a custom toolbar category.
    • Select Macros from the command category drop-down list.
    • Select your registered macro command and click the right arrow to add it to the toolbar.
  3. Package as a Workbench: For complex tools, create an InitGui.py file within an addon directory inside ~/.FreeCAD/Mod/ (Linux/macOS) or %APPDATA%\FreeCAD\Mod\ (Windows) to automatically create workbenches, toolbars, and menus on application startup.