AutoParam System

The AutoParam system provides a mechanism to automatically generate Qt-based configuration forms from C++ structs. It leverages compile-time reflection (via reflect-cpp) to create a runtime schema, which is then used to build the UI dynamically.

Source Location

AutoParamWidget lives in its own static library at src/WhiskerToolbox/AutoParamWidget/. It depends only on Qt6::Widgets and ParameterSchema — it has no dependency on TransformsV2 or any other domain library, making it reusable by any widget that needs schema-driven parameter forms (e.g., TransformsV2_Widget, TriageSession_Widget).

The CMake target is AutoParamWidget. Link it directly when you need the form widget:

target_link_libraries(MyWidget PUBLIC AutoParamWidget)

Include Path

#include "AutoParamWidget/AutoParamWidget.hpp"

Core Components

1. Parameter Structs

The foundation of the system is a simple C++ struct that defines your parameters.

struct MyTransformParams {
    float threshold = 0.5f;
    int iterations = 10;
    std::string mode = "Fast";
    bool enable_logging = true;
};

2. ParameterSchema

At runtime, we need a description of this struct to build the UI. ParameterSchema is a data structure that holds this information: * Fields: Name, type, default value. * Constraints: Min/max values for numbers. * UI Hints: Tooltips, display names, grouping.

This schema is extracted automatically using reflect-cpp.

3. AutoParamWidget

The AutoParamWidget is a generic Qt widget that takes a ParameterSchema and builds a form. * float/double -> QDoubleSpinBox * int -> QSpinBox * bool -> QCheckBox * std::string -> QLineEdit or QComboBox (if allowed values are provided) * std::optional<T> -> Checkbox-gated widget

Customization

You can customize the generated UI without changing the AutoParamWidget code by using ParameterUIHints.

ParameterUIHints

Specialize the ParameterUIHints template for your struct to provide additional metadata.

template<>
struct ParameterUIHints<MyTransformParams> {
    static void annotate(ParameterSchema& schema) {
        // Add a tooltip
        if (auto* f = schema.field("threshold")) {
            f->tooltip = "Signal detection threshold (0.0 to 1.0)";
            f->min_value = 0.0;
            f->max_value = 1.0;
        }

        // Define allowed values for a string (creates a ComboBox)
        if (auto* f = schema.field("mode")) {
            f->allowed_values = {"Fast", "Accurate", "Debug"};
        }
    }
};

Custom Widgets

If the standard widgets aren’t enough, you can register a completely custom widget definition for your parameter type using the ParamWidgetRegistry.

ParamWidgetRegistry::instance().registerCustomWidget<MyComplexParams>(
    [](QWidget* parent) { return new MyCustomEditor(parent); }
);

If a custom widget is registered, the AutoParamWidget is bypassed entirely for that type.