diff --git a/src/libkiter/commons/KiterRegistry.h b/src/libkiter/commons/KiterRegistry.h
index e6c3369f..4872a9e9 100644
--- a/src/libkiter/commons/KiterRegistry.h
+++ b/src/libkiter/commons/KiterRegistry.h
@@ -92,6 +92,18 @@ class KiterRegistry {
     	return true;
     }
 
+    static const std::vector<std::string>  get_names() {
+        tools_map& m = getSingletonMap();
+        std::vector<std::string> keys;
+        keys.reserve(m.size()); // Reserve memory to improve performance
+        std::transform(m.begin(), m.end(), std::back_inserter(keys),
+                       [](const auto& pair) {
+                           return pair.first;
+                       });
+        return keys;
+
+    }
+
     static const T* get(const std::string& name) {
         tools_map& map = getSingletonMap();
     	if (map.find(name) == map.end()) return nullptr;
diff --git a/src/qiter/CMakeLists.txt b/src/qiter/CMakeLists.txt
index f5d05dc7..00a30d35 100644
--- a/src/qiter/CMakeLists.txt
+++ b/src/qiter/CMakeLists.txt
@@ -13,6 +13,8 @@ set(SOURCE_FILES
         graphwidget.cpp
         qtNode.cpp
         qtEdge.cpp
+        ParameterInputDialog.h
+        ParameterInputDialog.cpp
 )
 
 add_executable(qiter ${SOURCE_FILES})
diff --git a/src/qiter/ParameterInputDialog.cpp b/src/qiter/ParameterInputDialog.cpp
new file mode 100644
index 00000000..02b43842
--- /dev/null
+++ b/src/qiter/ParameterInputDialog.cpp
@@ -0,0 +1,73 @@
+//
+// Created by toky on 3/12/24.
+//
+
+#include "ParameterInputDialog.h"
+#include <QDialogButtonBox>
+#include <QFormLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include "commons/KiterRegistry.h"
+#include "generators/generators.h"
+
+ParameterInputDialog::ParameterInputDialog(const QString &generatorName, QWidget *parent)
+        : QDialog(parent), generatorName(generatorName)
+{
+    setWindowTitle(tr("Parameters for %1").arg(generatorName));
+    layout = new QVBoxLayout(this);
+
+    QLabel *infoLabel = new QLabel(tr("Enter parameters (name and value):"), this);
+    layout->addWidget(infoLabel);
+
+    formLayout = new QFormLayout;
+
+    // Add an initial parameter row
+    QLineEdit *paramNameEdit = new QLineEdit(this);
+    QLineEdit *paramValueEdit = new QLineEdit(this);
+    paramNameEdits.append(paramNameEdit);
+    paramValueEdits.append(paramValueEdit);
+    formLayout->addRow(paramNameEdit, paramValueEdit);
+
+    layout->addLayout(formLayout);
+
+    // Add "Add Parameter" button
+    QPushButton *addParamButton = new QPushButton(tr("Add Parameter"), this);
+    connect(addParamButton, &QPushButton::clicked, this, &ParameterInputDialog::onAddParameterClicked);
+    layout->addWidget(addParamButton);
+
+    // Add OK and Cancel buttons
+    QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
+    connect(buttonBox, &QDialogButtonBox::accepted, this, &ParameterInputDialog::accept);
+    connect(buttonBox, &QDialogButtonBox::rejected, this, &ParameterInputDialog::reject);
+
+    layout->addWidget(buttonBox);
+}
+
+void ParameterInputDialog::onAddParameterClicked()
+{
+    QLineEdit *paramNameEdit = new QLineEdit(this);
+    QLineEdit *paramValueEdit = new QLineEdit(this);
+    paramNameEdits.append(paramNameEdit);
+    paramValueEdits.append(paramValueEdit);
+    formLayout->addRow(paramNameEdit, paramValueEdit);
+}
+
+void ParameterInputDialog::accept()
+{
+    // Collect parameters
+    for (int i = 0; i < paramNameEdits.size(); ++i) {
+        QString paramName = paramNameEdits[i]->text();
+        QString paramValue = paramValueEdits[i]->text();
+        if (!paramName.isEmpty()) {
+            parameters[paramName.toStdString()] = paramValue.toStdString();
+        }
+    }
+
+    QDialog::accept();
+}
+
+parameters_list_t ParameterInputDialog::getParameters() const
+{
+    return parameters;
+}
diff --git a/src/qiter/ParameterInputDialog.h b/src/qiter/ParameterInputDialog.h
new file mode 100644
index 00000000..d25ee679
--- /dev/null
+++ b/src/qiter/ParameterInputDialog.h
@@ -0,0 +1,36 @@
+//
+// Created by toky on 3/12/24.
+//
+
+#ifndef KITER_PARAMETERINPUTDIALOG_H
+#define KITER_PARAMETERINPUTDIALOG_H
+
+#include <QDialog>
+#include <QMap>
+#include <QLineEdit>
+#include <QVBoxLayout>
+#include <QFormLayout>
+#include "printers/printers.h" // For parameters_list_t
+
+class ParameterInputDialog : public QDialog
+{
+Q_OBJECT
+
+public:
+    explicit ParameterInputDialog(const QString &generatorName, QWidget *parent = nullptr);
+    parameters_list_t getParameters() const;
+
+private slots:
+    void accept() override;
+    void onAddParameterClicked();
+
+private:
+    QString generatorName;
+    parameters_list_t parameters;
+    QList<QLineEdit*> paramNameEdits;
+    QList<QLineEdit*> paramValueEdits;
+    QVBoxLayout *layout;
+    QFormLayout *formLayout;
+};
+
+#endif //KITER_PARAMETERINPUTDIALOG_H
diff --git a/src/qiter/graphwidget.h b/src/qiter/graphwidget.h
index 4d5633dd..2bde810d 100644
--- a/src/qiter/graphwidget.h
+++ b/src/qiter/graphwidget.h
@@ -16,6 +16,9 @@ Q_OBJECT
 public:
     GraphWidget(QWidget *parent = nullptr);
     void setDataflow(models::Dataflow *dataflow);
+    inline models::Dataflow * getDataflow() {
+        return this->dataflow;
+    }
     void drawGraph();
     void startLayout();
 
diff --git a/src/qiter/mainwindow.cpp b/src/qiter/mainwindow.cpp
index 45e3c940..3b23596e 100644
--- a/src/qiter/mainwindow.cpp
+++ b/src/qiter/mainwindow.cpp
@@ -2,9 +2,11 @@
 #include "ui_mainwindow.h"
 #include <QFileDialog>
 #include <QMessageBox>
-#include <QDebug> 
+#include <QDebug>
 #include "printers/printers.h"
-
+#include "commons/KiterRegistry.h"
+#include "generators/generators.h"
+#include "ParameterInputDialog.h"
 
 MainWindow::MainWindow(QWidget *parent)
         : QMainWindow(parent)
@@ -19,6 +21,62 @@ MainWindow::MainWindow(QWidget *parent)
     }
 
     connect(ui->actionLoad, &QAction::triggered, this, &MainWindow::loadGraph);
+
+    // Create Generate menu dynamically
+    QMenu *generateMenu = new QMenu(tr("&Generate"), this);
+    ui->menubar->addMenu(generateMenu);
+
+    // Get the list of generators from KiterRegistry
+    std::vector<std::string> generatorNames = KiterRegistry<generator_t>::get_names();
+
+    for (const std::string &generatorName : generatorNames) {
+        QAction *action = new QAction(QString::fromStdString(generatorName), this);
+        action->setData(QString::fromStdString(generatorName));
+        generateMenu->addAction(action);
+        connect(action, &QAction::triggered, this, &MainWindow::onGenerateActionTriggered);
+    }
+
+    // Create Transformations menu dynamically
+    QMenu *transformationsMenu = new QMenu(tr("&Transformations"), this);
+    ui->menubar->addMenu(transformationsMenu);
+
+    // Get the list of transformations from KiterRegistry
+    std::vector<std::string> transformationNames = KiterRegistry<transformation_t>::get_names();
+
+    for (const std::string &transformationName : transformationNames) {
+        QAction *action = new QAction(QString::fromStdString(transformationName), this);
+        action->setData(QString::fromStdString(transformationName));
+        transformationsMenu->addAction(action);
+        connect(action, &QAction::triggered, this, &MainWindow::onTransformationActionTriggered);
+    }
+
+    // Create Buffer Sizing menu dynamically
+    QMenu *bufferSizingMenu = new QMenu(tr("&Buffer Sizing"), this);
+    ui->menubar->addMenu(bufferSizingMenu);
+
+    // Get the list of buffer sizings from KiterRegistry
+    std::vector<std::string> bufferSizingNames = KiterRegistry<buffer_sizing_t>::get_names();
+
+    for (const std::string &bufferSizingName : bufferSizingNames) {
+        QAction *action = new QAction(QString::fromStdString(bufferSizingName), this);
+        action->setData(QString::fromStdString(bufferSizingName));
+        bufferSizingMenu->addAction(action);
+        connect(action, &QAction::triggered, this, &MainWindow::onBufferSizingActionTriggered);
+    }
+
+    // Create Printers menu dynamically
+    QMenu *printersMenu = new QMenu(tr("&Printers"), this);
+    ui->menubar->addMenu(printersMenu);
+
+    // Get the list of printers from KiterRegistry
+    std::vector<std::string> printerNames = KiterRegistry<printer_t>::get_names();
+
+    for (const std::string &printerName : printerNames) {
+        QAction *action = new QAction(QString::fromStdString(printerName), this);
+        action->setData(QString::fromStdString(printerName));
+        printersMenu->addAction(action);
+        connect(action, &QAction::triggered, this, &MainWindow::onPrinterActionTriggered);
+    }
 }
 
 MainWindow::~MainWindow()
@@ -26,6 +84,7 @@ MainWindow::~MainWindow()
     delete ui;
 }
 
+
 void MainWindow::loadGraph()
 {
     qInfo() << "Attempting to open file dialog for XML file selection...";
@@ -35,7 +94,7 @@ void MainWindow::loadGraph()
 
     if (fileName.isEmpty()) {
         qInfo() << "No file selected or dialog canceled.";
-        return; 
+        return;
     }
 
     qInfo() << "Selected file:" << fileName;
@@ -53,3 +112,129 @@ void MainWindow::loadGraph()
 
     graphWidget->setDataflow(dataflow);
 }
+void MainWindow::onTransformationActionTriggered()
+{
+    handleAction<transformation_t, void>(
+            [this](const transformation_t *actionInstance, const parameters_list_t &parameters) {
+                // Ensure dataflow is loaded
+                models::Dataflow *dataflow = graphWidget->getDataflow();
+                if (!dataflow) {
+                    QMessageBox::warning(this, tr("No Dataflow"), tr("Please load or generate a dataflow graph first."));
+                    throw std::runtime_error("No dataflow loaded");
+                }
+                // Perform the action
+                actionInstance->fun(dataflow, parameters);
+            },
+            [this]() {
+                // Post-action processing
+                graphWidget->update(); // Update the graph display
+            });
+}
+
+
+void MainWindow::onPrinterActionTriggered()
+{
+    handleAction<printer_t, void>(
+            [this](const printer_t *actionInstance, const parameters_list_t &parameters) {
+                models::Dataflow *dataflow = graphWidget->getDataflow();
+                if (!dataflow) {
+                    QMessageBox::warning(this, tr("No Dataflow"), tr("Please load or generate a dataflow graph first."));
+                    throw std::runtime_error("No dataflow loaded");
+                }
+                actionInstance->fun(dataflow, parameters);
+            },
+            []() {
+                // Post-action processing
+                qInfo() << "Printer executed successfully.";
+            });
+}
+
+
+void MainWindow::onBufferSizingActionTriggered()
+{
+    handleAction<buffer_sizing_t, BufferSizingResult>(
+            [this](const buffer_sizing_t *actionInstance, const parameters_list_t &parameters) -> BufferSizingResult {
+                models::Dataflow *dataflow = graphWidget->getDataflow();
+                if (!dataflow) {
+                    QMessageBox::warning(this, tr("No Dataflow"), tr("Please load or generate a dataflow graph first."));
+                    throw std::runtime_error("No dataflow loaded");
+                }
+                return actionInstance->fun(dataflow, parameters);
+            },
+            [this](const BufferSizingResult &res) {
+                // Post-action processing
+                qInfo() << "Total buffer size:" << res.total_size();
+                QMessageBox::information(this, tr("Buffer Sizing Result"),
+                                         tr("Total buffer size: %1").arg(res.total_size()));
+            });
+}
+
+
+
+void MainWindow::onGenerateActionTriggered()
+{
+    handleAction<generator_t, models::Dataflow *>(
+            [](const generator_t *actionInstance, const parameters_list_t &parameters) -> models::Dataflow * {
+                return actionInstance->fun(parameters);
+            },
+            [this](models::Dataflow *newDataflow) {
+                if (!newDataflow) {
+                    QMessageBox::critical(this, tr("Error"), tr("Failed to generate the graph."));
+                    qWarning() << "Failed to generate the graph.";
+                    return;
+                }
+                qInfo() << "Dataflow generated successfully, updating graph widget...";
+                graphWidget->setDataflow(newDataflow);
+            });
+}
+
+template <typename ActionType, typename ResultType, typename ActionFunction, typename PostAction>
+void MainWindow::handleAction(ActionFunction actionFunction, PostAction postAction) {
+    try {
+        QAction *actionSender = qobject_cast<QAction *>(sender());
+        if (!actionSender) {
+            qWarning() << "Sender is not a QAction!";
+            return;
+        }
+        QString actionName = actionSender->data().toString();
+        qInfo() << "Action selected:" << actionName;
+
+        // Show a dialog to input parameters
+        ParameterInputDialog dialog(actionName, this);
+        if (dialog.exec() != QDialog::Accepted) {
+            qInfo() << "Action dialog canceled.";
+            return;
+        }
+
+        parameters_list_t parameters = dialog.getParameters();
+
+        const ActionType *actionInstance = KiterRegistry<ActionType>::get(actionName.toStdString());
+        if (!actionInstance) {
+            QMessageBox::critical(this, tr("Error"), tr("Action not found."));
+            qWarning() << "Action not found:" << actionName;
+            return;
+        }
+
+        qInfo() << "Performing action...";
+
+        // Run the action on the main thread
+        if constexpr (std::is_same<ResultType, void>::value) {
+            // If ResultType is void, call the function without assigning to a variable
+            actionFunction(actionInstance, parameters);
+            qInfo() << "Action completed.";
+            // Process the result using the provided post-action function
+            postAction();
+        } else {
+            // If ResultType is not void, assign the result to a variable
+            ResultType result = actionFunction(actionInstance, parameters);
+            qInfo() << "Action completed.";
+            // Process the result using the provided post-action function
+            postAction(result);
+        }
+
+
+    } catch (const std::exception &e) {
+        QMessageBox::critical(this, tr("Error"), e.what());
+        qWarning() << "Exception occurred:" << e.what();
+    }
+}
diff --git a/src/qiter/mainwindow.h b/src/qiter/mainwindow.h
index 493bc33b..a5e73c87 100644
--- a/src/qiter/mainwindow.h
+++ b/src/qiter/mainwindow.h
@@ -18,9 +18,16 @@ Q_OBJECT
 
 private slots:
     void loadGraph();
+    void onGenerateActionTriggered();
+    void onTransformationActionTriggered();
+    void onBufferSizingActionTriggered();
+    void onPrinterActionTriggered();
 
 private:
     Ui::MainWindow *ui;
-    GraphWidget *graphWidget; 
+    GraphWidget *graphWidget;
+
+    template <typename ActionType, typename ResultType, typename ActionFunction, typename PostAction>
+    void handleAction(ActionFunction actionFunction, PostAction postAction) ;
 };
 #endif // MAINWINDOW_H