Archetype: cpp_qt_controller.cpp.mustache

Table of Contents

Dialog lifecycle and service calls. Qt UI component: model/view class or dialog wired to the service layer via request/response messages.

See the Template variable reference for the complete list of available variables and their semantics.

Template

The full template source. Edit here and re-tangle with compass build --direct tangle_codegen_templates to regenerate library/templates/cpp_qt_controller.cpp.mustache.

{{! GENERATED FILE — tangled from projects/ores.codegen/library/templates/cpp_qt.org. Edit the org source. }}
{{! Template to generate Qt controller source for domain entities }}
{{{cpp_license}}}
#include "ores.qt/{{domain_entity.entity_pascal}}Controller.hpp"
{{#domain_entity.qt.has_change_reason_cache}}
#include "ores.qt/ChangeReasonCache.hpp"
{{/domain_entity.qt.has_change_reason_cache}}
{{#domain_entity.qt.changed_event_class}}
#include "ores.eventing.api/domain/event_traits.hpp"
#include "{{domain_entity.qt.changed_event_include}}"
{{/domain_entity.qt.changed_event_class}}
#include <QMdiSubWindow>
#include <QMessageBox>
#include <QPointer>
#include "ores.qt/IconUtils.hpp"
#include "ores.qt/{{domain_entity.entity_pascal}}MdiWindow.hpp"
#include "ores.qt/{{domain_entity.entity_pascal}}DetailDialog.hpp"
#include "ores.qt/{{domain_entity.entity_pascal}}HistoryDialog.hpp"
#include "ores.qt/DetachableMdiSubWindow.hpp"
#include "ores.qt/UiPersistence.hpp"

namespace ores::qt {

using namespace ores::logging;

{{#domain_entity.qt.changed_event_class}}
namespace {
constexpr std::string_view {{domain_entity.qt.item_var}}_event_name =
    eventing::domain::event_traits<{{domain_entity.qt.changed_event_class}}>::name;
}

{{/domain_entity.qt.changed_event_class}}
{{domain_entity.entity_pascal}}Controller::{{domain_entity.entity_pascal}}Controller(
    QMainWindow* mainWindow,
    QMdiArea* mdiArea,
    ClientManager* clientManager,
{{#domain_entity.qt.has_change_reason_cache}}
    ChangeReasonCache* changeReasonCache,
{{/domain_entity.qt.has_change_reason_cache}}
    const QString& username,
{{#domain_entity.qt.has_badge_columns}}
    BadgeCache* badgeCache,
{{/domain_entity.qt.has_badge_columns}}
    QObject* parent)
    : EntityController(mainWindow, mdiArea, clientManager, username,
{{#domain_entity.qt.changed_event_class}}
          {{domain_entity.qt.item_var}}_event_name,
{{/domain_entity.qt.changed_event_class}}
{{^domain_entity.qt.changed_event_class}}
          std::string_view{},
{{/domain_entity.qt.changed_event_class}}
          parent),
{{#domain_entity.qt.has_change_reason_cache}}
      changeReasonCache_(changeReasonCache),
{{/domain_entity.qt.has_change_reason_cache}}
{{#domain_entity.qt.has_badge_columns}}
      badgeCache_(badgeCache),
{{/domain_entity.qt.has_badge_columns}}
      listWindow_(nullptr),
      listMdiSubWindow_(nullptr) {

    BOOST_LOG_SEV(lg(), debug) << "{{domain_entity.entity_pascal}}Controller created";
}

void {{domain_entity.entity_pascal}}Controller::showListWindow() {
    BOOST_LOG_SEV(lg(), debug) << "showListWindow called";

    const QString key = build_window_key("list", "{{domain_entity.entity_plural}}");
    if (try_reuse_window(key)) {
        BOOST_LOG_SEV(lg(), debug) << "Reusing existing list window";
        return;
    }

    // Create new window
{{#domain_entity.qt.has_badge_columns}}
    listWindow_ = new {{domain_entity.entity_pascal}}MdiWindow(clientManager_, username_, badgeCache_);
{{/domain_entity.qt.has_badge_columns}}
{{^domain_entity.qt.has_badge_columns}}
    listWindow_ = new {{domain_entity.entity_pascal}}MdiWindow(clientManager_, username_);
{{/domain_entity.qt.has_badge_columns}}

    // Connect signals
    connect(listWindow_, &{{domain_entity.entity_pascal}}MdiWindow::statusChanged,
            this, &{{domain_entity.entity_pascal}}Controller::statusMessage);
    connect(listWindow_, &{{domain_entity.entity_pascal}}MdiWindow::errorOccurred,
            this, &{{domain_entity.entity_pascal}}Controller::errorMessage);
    connect(listWindow_, &{{domain_entity.entity_pascal}}MdiWindow::show{{domain_entity.entity_pascal_short}}Details,
            this, &{{domain_entity.entity_pascal}}Controller::onShowDetails);
    connect(listWindow_, &{{domain_entity.entity_pascal}}MdiWindow::addNewRequested,
            this, &{{domain_entity.entity_pascal}}Controller::onAddNewRequested);
    connect(listWindow_, &{{domain_entity.entity_pascal}}MdiWindow::show{{domain_entity.entity_pascal_short}}History,
            this, &{{domain_entity.entity_pascal}}Controller::onShowHistory);

    // Create MDI subwindow
    listMdiSubWindow_ = new DetachableMdiSubWindow(mainWindow_);
    listMdiSubWindow_->setWidget(listWindow_);
    listMdiSubWindow_->setWindowTitle("{{domain_entity.qt.window_title}}");
    listMdiSubWindow_->setWindowIcon(IconUtils::createRecoloredIcon(
        Icon::{{domain_entity.qt.icon}}, IconUtils::DefaultIconColor));
    listMdiSubWindow_->setAttribute(Qt::WA_DeleteOnClose);
    listMdiSubWindow_->resize(listWindow_->sizeHint());

    mdiArea_->addSubWindow(listMdiSubWindow_);
    listMdiSubWindow_->show();

    // Track window
    track_window(key, listMdiSubWindow_);
    register_detachable_window(listMdiSubWindow_);
    listMdiSubWindow_->setGeometryKey(key);
    UiPersistence::restoreMdiGeometry(key, listMdiSubWindow_);

    // Cleanup when closed
    connect(listMdiSubWindow_, &QObject::destroyed, this, [self = QPointer<{{domain_entity.entity_pascal}}Controller>(this), key]() {
        if (!self) return;
        self->untrack_window(key);
        self->listWindow_ = nullptr;
        self->listMdiSubWindow_ = nullptr;
    });

    BOOST_LOG_SEV(lg(), debug) << "{{domain_entity.entity_title}} list window created";
}

void {{domain_entity.entity_pascal}}Controller::closeAllWindows() {
    BOOST_LOG_SEV(lg(), debug) << "closeAllWindows called";

    // Close all managed windows
    QList<QString> keys = managed_windows_.keys();
    for (const QString& key : keys) {
        if (auto* window = managed_windows_.value(key)) {
            window->close();
        }
    }
    managed_windows_.clear();

    listWindow_ = nullptr;
    listMdiSubWindow_ = nullptr;
}

void {{domain_entity.entity_pascal}}Controller::reloadListWindow() {
    if (listWindow_) {
        listWindow_->reload();
    }
}

void {{domain_entity.entity_pascal}}Controller::onShowDetails(
    const {{domain_entity.qt.domain_class}}& {{domain_entity.qt.item_var}}) {
    BOOST_LOG_SEV(lg(), debug) << "Show details for: " << {{domain_entity.qt.item_var}}.{{#domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field_access}}{{/domain_entity.qt.key_field_access}}{{^domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field}}{{/domain_entity.qt.key_field_access}};
    showDetailWindow({{domain_entity.qt.item_var}});
}

void {{domain_entity.entity_pascal}}Controller::onAddNewRequested() {
    BOOST_LOG_SEV(lg(), info) << "Add new {{domain_entity.entity_singular_words}} requested";
    showAddWindow();
}

{{#domain_entity.qt.has_uuid_primary_key}}
void {{domain_entity.entity_pascal}}Controller::onShowHistory(
    const {{domain_entity.qt.domain_class}}& {{domain_entity.qt.item_var}}) {
    BOOST_LOG_SEV(lg(), debug) << "Show history requested for: " << {{domain_entity.qt.item_var}}.{{#domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field_access}}{{/domain_entity.qt.key_field_access}}{{^domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field}}{{/domain_entity.qt.key_field_access}};
    showHistoryWindow({{domain_entity.qt.item_var}});
}
{{/domain_entity.qt.has_uuid_primary_key}}
{{^domain_entity.qt.has_uuid_primary_key}}
void {{domain_entity.entity_pascal}}Controller::onShowHistory(
    const {{domain_entity.qt.domain_class}}& {{domain_entity.qt.item_var}}) {
    BOOST_LOG_SEV(lg(), debug) << "Show history requested for: " << {{domain_entity.qt.item_var}}.{{#domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field_access}}{{/domain_entity.qt.key_field_access}}{{^domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field}}{{/domain_entity.qt.key_field_access}};
    showHistoryWindow(QString::fromStdString({{domain_entity.qt.item_var}}.{{#domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field_access}}{{/domain_entity.qt.key_field_access}}{{^domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field}}{{/domain_entity.qt.key_field_access}}));
}
{{/domain_entity.qt.has_uuid_primary_key}}

void {{domain_entity.entity_pascal}}Controller::showAddWindow() {
    BOOST_LOG_SEV(lg(), debug) << "Creating add window for new {{domain_entity.entity_singular_words}}";

    auto* detailDialog = new {{domain_entity.entity_pascal}}DetailDialog(mainWindow_);
{{#domain_entity.qt.has_change_reason_cache}}
    if (changeReasonCache_)
        detailDialog->setChangeReasonCache(changeReasonCache_);
{{/domain_entity.qt.has_change_reason_cache}}
    detailDialog->setClientManager(clientManager_);
    detailDialog->setUsername(username_.toStdString());
    detailDialog->setCreateMode(true);

    connect(detailDialog, &{{domain_entity.entity_pascal}}DetailDialog::statusMessage,
            this, &{{domain_entity.entity_pascal}}Controller::statusMessage);
    connect(detailDialog, &{{domain_entity.entity_pascal}}DetailDialog::errorMessage,
            this, &{{domain_entity.entity_pascal}}Controller::errorMessage);
    connect(detailDialog, &{{domain_entity.entity_pascal}}DetailDialog::{{domain_entity.qt.item_var}}Saved,
            this, [self = QPointer<{{domain_entity.entity_pascal}}Controller>(this)](const QString& code) {
        if (!self) return;
        BOOST_LOG_SEV(lg(), info) << "{{domain_entity.entity_title}} saved: " << code.toStdString();
        self->handleEntitySaved();
    });

    auto* detailWindow = new DetachableMdiSubWindow(mainWindow_);
    detailWindow->setAttribute(Qt::WA_DeleteOnClose);
    detailWindow->setWidget(detailDialog);
    detailWindow->setWindowTitle("New {{domain_entity.entity_title}}");
    detailWindow->setWindowIcon(IconUtils::createRecoloredIcon(
        Icon::{{domain_entity.qt.icon}}, IconUtils::DefaultIconColor));

    register_detachable_window(detailWindow);

    connect_dialog_close(detailDialog, detailWindow);
    show_managed_window(detailWindow, listMdiSubWindow_);
}

void {{domain_entity.entity_pascal}}Controller::showDetailWindow(
    const {{domain_entity.qt.domain_class}}& {{domain_entity.qt.item_var}}) {

    const QString identifier = QString::fromStdString({{domain_entity.qt.item_var}}.{{#domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field_access}}{{/domain_entity.qt.key_field_access}}{{^domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field}}{{/domain_entity.qt.key_field_access}});
    const QString key = build_window_key("details", identifier);

    if (try_reuse_window(key)) {
        BOOST_LOG_SEV(lg(), debug) << "Reusing existing detail window";
        return;
    }

    BOOST_LOG_SEV(lg(), debug) << "Creating detail window for: " << {{domain_entity.qt.item_var}}.{{#domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field_access}}{{/domain_entity.qt.key_field_access}}{{^domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field}}{{/domain_entity.qt.key_field_access}};

    auto* detailDialog = new {{domain_entity.entity_pascal}}DetailDialog(mainWindow_);
{{#domain_entity.qt.has_change_reason_cache}}
    if (changeReasonCache_)
        detailDialog->setChangeReasonCache(changeReasonCache_);
{{/domain_entity.qt.has_change_reason_cache}}
    detailDialog->setClientManager(clientManager_);
    detailDialog->setUsername(username_.toStdString());
    detailDialog->setCreateMode(false);
    detailDialog->set{{domain_entity.entity_pascal_short}}({{domain_entity.qt.item_var}});

    connect(detailDialog, &{{domain_entity.entity_pascal}}DetailDialog::statusMessage,
            this, &{{domain_entity.entity_pascal}}Controller::statusMessage);
    connect(detailDialog, &{{domain_entity.entity_pascal}}DetailDialog::errorMessage,
            this, &{{domain_entity.entity_pascal}}Controller::errorMessage);
    connect(detailDialog, &{{domain_entity.entity_pascal}}DetailDialog::{{domain_entity.qt.item_var}}Saved,
            this, [self = QPointer<{{domain_entity.entity_pascal}}Controller>(this)](const QString& code) {
        if (!self) return;
        BOOST_LOG_SEV(lg(), info) << "{{domain_entity.entity_title}} saved: " << code.toStdString();
        self->handleEntitySaved();
    });
    connect(detailDialog, &{{domain_entity.entity_pascal}}DetailDialog::{{domain_entity.qt.item_var}}Deleted,
            this, [self = QPointer<{{domain_entity.entity_pascal}}Controller>(this), key](const QString& code) {
        if (!self) return;
        BOOST_LOG_SEV(lg(), info) << "{{domain_entity.entity_title}} deleted: " << code.toStdString();
        self->handleEntityDeleted();
    });

    auto* detailWindow = new DetachableMdiSubWindow(mainWindow_);
    detailWindow->setAttribute(Qt::WA_DeleteOnClose);
    detailWindow->setWidget(detailDialog);
    detailWindow->setWindowTitle(QString("{{domain_entity.entity_title}}: %1").arg(identifier));
    detailWindow->setWindowIcon(IconUtils::createRecoloredIcon(
        Icon::{{domain_entity.qt.icon}}, IconUtils::DefaultIconColor));

    // Track window
    track_window(key, detailWindow);
    register_detachable_window(detailWindow);
    detailWindow->setGeometryKey(key);
    UiPersistence::restoreMdiGeometry(key, detailWindow);

    QPointer<{{domain_entity.entity_pascal}}Controller> self = this;
    connect(detailWindow, &QObject::destroyed, this,
            [self, key]() {
        if (self) {
            self->untrack_window(key);
        }
    });

    connect_dialog_close(detailDialog, detailWindow);
    show_managed_window(detailWindow, listMdiSubWindow_);
}

{{#domain_entity.qt.has_uuid_primary_key}}
void {{domain_entity.entity_pascal}}Controller::showHistoryWindow(
    const {{domain_entity.qt.domain_class}}& {{domain_entity.qt.item_var}}) {
    const QString code = QString::fromStdString({{domain_entity.qt.item_var}}.{{#domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field_access}}{{/domain_entity.qt.key_field_access}}{{^domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field}}{{/domain_entity.qt.key_field_access}});
    BOOST_LOG_SEV(lg(), info) << "Opening history window for {{domain_entity.entity_singular_words}}: "
                              << {{domain_entity.qt.item_var}}.{{#domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field_access}}{{/domain_entity.qt.key_field_access}}{{^domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field}}{{/domain_entity.qt.key_field_access}};

    const QString windowKey = build_window_key("history", code);

    // Try to reuse existing window
    if (try_reuse_window(windowKey)) {
        BOOST_LOG_SEV(lg(), info) << "Reusing existing history window for: "
                                  << {{domain_entity.qt.item_var}}.{{#domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field_access}}{{/domain_entity.qt.key_field_access}}{{^domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field}}{{/domain_entity.qt.key_field_access}};
        return;
    }

    BOOST_LOG_SEV(lg(), info) << "Creating new history window for: "
                              << {{domain_entity.qt.item_var}}.{{#domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field_access}}{{/domain_entity.qt.key_field_access}}{{^domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field}}{{/domain_entity.qt.key_field_access}};

    auto* historyDialog = new {{domain_entity.entity_pascal}}HistoryDialog(
        {{domain_entity.qt.item_var}}.{{#domain_entity.qt.id_access}}{{domain_entity.qt.id_access}}{{/domain_entity.qt.id_access}}{{^domain_entity.qt.id_access}}id{{/domain_entity.qt.id_access}}, code, clientManager_, mainWindow_);
{{/domain_entity.qt.has_uuid_primary_key}}
{{^domain_entity.qt.has_uuid_primary_key}}
void {{domain_entity.entity_pascal}}Controller::showHistoryWindow(const QString& code) {
    BOOST_LOG_SEV(lg(), info) << "Opening history window for {{domain_entity.entity_singular_words}}: "
                              << code.toStdString();

    const QString windowKey = build_window_key("history", code);

    // Try to reuse existing window
    if (try_reuse_window(windowKey)) {
        BOOST_LOG_SEV(lg(), info) << "Reusing existing history window for: "
                                  << code.toStdString();
        return;
    }

    BOOST_LOG_SEV(lg(), info) << "Creating new history window for: "
                              << code.toStdString();

    auto* historyDialog = new {{domain_entity.entity_pascal}}HistoryDialog(code, clientManager_, mainWindow_);
{{/domain_entity.qt.has_uuid_primary_key}}

    connect(historyDialog, &{{domain_entity.entity_pascal}}HistoryDialog::statusChanged,
            this, [self = QPointer<{{domain_entity.entity_pascal}}Controller>(this)](const QString& message) {
        if (!self) return;
        emit self->statusMessage(message);
    });
    connect(historyDialog, &{{domain_entity.entity_pascal}}HistoryDialog::errorOccurred,
            this, [self = QPointer<{{domain_entity.entity_pascal}}Controller>(this)](const QString& message) {
        if (!self) return;
        emit self->errorMessage(message);
    });
    connect(historyDialog, &{{domain_entity.entity_pascal}}HistoryDialog::revertVersionRequested,
            this, &{{domain_entity.entity_pascal}}Controller::onRevertVersion);
    connect(historyDialog, &{{domain_entity.entity_pascal}}HistoryDialog::openVersionRequested,
            this, &{{domain_entity.entity_pascal}}Controller::onOpenVersion);

    // Load history data
    historyDialog->loadHistory();

    auto* historyWindow = new DetachableMdiSubWindow(mainWindow_);
    historyWindow->setAttribute(Qt::WA_DeleteOnClose);
    historyWindow->setWidget(historyDialog);
    historyWindow->setWindowTitle(QString("{{domain_entity.entity_title}} History: %1").arg(code));
    historyWindow->setWindowIcon(IconUtils::createRecoloredIcon(
        Icon::History, IconUtils::DefaultIconColor));

    // Track this history window
    track_window(windowKey, historyWindow);
    register_detachable_window(historyWindow);
    historyWindow->setGeometryKey(windowKey);
    UiPersistence::restoreMdiGeometry(windowKey, historyWindow);

    QPointer<{{domain_entity.entity_pascal}}Controller> self = this;
    connect(historyWindow, &QObject::destroyed, this,
            [self, windowKey]() {
        if (self) {
            self->untrack_window(windowKey);
        }
    });

    show_managed_window(historyWindow, listMdiSubWindow_);
}

void {{domain_entity.entity_pascal}}Controller::onOpenVersion(
    const {{domain_entity.qt.domain_class}}& {{domain_entity.qt.item_var}}, int versionNumber) {
    BOOST_LOG_SEV(lg(), info) << "Opening historical version " << versionNumber
                              << " for {{domain_entity.entity_singular_words}}: " << {{domain_entity.qt.item_var}}.{{#domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field_access}}{{/domain_entity.qt.key_field_access}}{{^domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field}}{{/domain_entity.qt.key_field_access}};

    const QString code = QString::fromStdString({{domain_entity.qt.item_var}}.{{#domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field_access}}{{/domain_entity.qt.key_field_access}}{{^domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field}}{{/domain_entity.qt.key_field_access}});
    const QString windowKey = build_window_key("version", QString("%1_v%2")
        .arg(code).arg(versionNumber));

    // Try to reuse existing window
    if (try_reuse_window(windowKey)) {
        BOOST_LOG_SEV(lg(), info) << "Reusing existing version window";
        return;
    }

    auto* detailDialog = new {{domain_entity.entity_pascal}}DetailDialog(mainWindow_);
{{#domain_entity.qt.has_change_reason_cache}}
    if (changeReasonCache_)
        detailDialog->setChangeReasonCache(changeReasonCache_);
{{/domain_entity.qt.has_change_reason_cache}}
    detailDialog->setClientManager(clientManager_);
    detailDialog->setUsername(username_.toStdString());
    detailDialog->set{{domain_entity.entity_pascal_short}}({{domain_entity.qt.item_var}});
    detailDialog->setReadOnly(true);

    connect(detailDialog, &{{domain_entity.entity_pascal}}DetailDialog::statusMessage,
            this, [self = QPointer<{{domain_entity.entity_pascal}}Controller>(this)](const QString& message) {
        if (!self) return;
        emit self->statusMessage(message);
    });
    connect(detailDialog, &{{domain_entity.entity_pascal}}DetailDialog::errorMessage,
            this, [self = QPointer<{{domain_entity.entity_pascal}}Controller>(this)](const QString& message) {
        if (!self) return;
        emit self->errorMessage(message);
    });

    auto* detailWindow = new DetachableMdiSubWindow(mainWindow_);
    detailWindow->setAttribute(Qt::WA_DeleteOnClose);
    detailWindow->setWidget(detailDialog);
    detailWindow->setWindowTitle(QString("{{domain_entity.entity_title}}: %1 (Version %2)")
        .arg(code).arg(versionNumber));
    detailWindow->setWindowIcon(IconUtils::createRecoloredIcon(
        Icon::History, IconUtils::DefaultIconColor));

    track_window(windowKey, detailWindow);
    register_detachable_window(detailWindow);

    QPointer<{{domain_entity.entity_pascal}}Controller> self = this;
    connect(detailWindow, &QObject::destroyed, this,
            [self, windowKey]() {
        if (self) {
            self->untrack_window(windowKey);
        }
    });

    connect_dialog_close(detailDialog, detailWindow);
    show_managed_window(detailWindow, listMdiSubWindow_, QPoint(60, 60));
}

void {{domain_entity.entity_pascal}}Controller::onRevertVersion(
    const {{domain_entity.qt.domain_class}}& {{domain_entity.qt.item_var}}) {
    BOOST_LOG_SEV(lg(), info) << "Reverting {{domain_entity.entity_singular_words}} to version: "
                              << {{domain_entity.qt.item_var}}.{{#domain_entity.qt.version_access}}{{domain_entity.qt.version_access}}{{/domain_entity.qt.version_access}}{{^domain_entity.qt.version_access}}version{{/domain_entity.qt.version_access}};

    // Open detail dialog with the old version data for editing
    auto* detailDialog = new {{domain_entity.entity_pascal}}DetailDialog(mainWindow_);
{{#domain_entity.qt.has_change_reason_cache}}
    if (changeReasonCache_)
        detailDialog->setChangeReasonCache(changeReasonCache_);
{{/domain_entity.qt.has_change_reason_cache}}
    detailDialog->setClientManager(clientManager_);
    detailDialog->setUsername(username_.toStdString());
    detailDialog->set{{domain_entity.entity_pascal_short}}({{domain_entity.qt.item_var}});
    detailDialog->setCreateMode(false);

    connect(detailDialog, &{{domain_entity.entity_pascal}}DetailDialog::statusMessage,
            this, &{{domain_entity.entity_pascal}}Controller::statusMessage);
    connect(detailDialog, &{{domain_entity.entity_pascal}}DetailDialog::errorMessage,
            this, &{{domain_entity.entity_pascal}}Controller::errorMessage);
    connect(detailDialog, &{{domain_entity.entity_pascal}}DetailDialog::{{domain_entity.qt.item_var}}Saved,
            this, [self = QPointer<{{domain_entity.entity_pascal}}Controller>(this)](const QString& code) {
        if (!self) return;
        BOOST_LOG_SEV(lg(), info) << "{{domain_entity.entity_title}} reverted: " << code.toStdString();
        emit self->statusMessage(QString("{{domain_entity.entity_title}} '%1' reverted successfully").arg(code));
        self->handleEntitySaved();
    });

    auto* detailWindow = new DetachableMdiSubWindow(mainWindow_);
    detailWindow->setAttribute(Qt::WA_DeleteOnClose);
    detailWindow->setWidget(detailDialog);
    detailWindow->setWindowTitle(QString("Revert {{domain_entity.entity_title}}: %1")
        .arg(QString::fromStdString({{domain_entity.qt.item_var}}.{{#domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field_access}}{{/domain_entity.qt.key_field_access}}{{^domain_entity.qt.key_field_access}}{{domain_entity.qt.key_field}}{{/domain_entity.qt.key_field_access}})));
    detailWindow->setWindowIcon(IconUtils::createRecoloredIcon(
        Icon::ArrowRotateCounterclockwise, IconUtils::DefaultIconColor));

    register_detachable_window(detailWindow);

    connect_dialog_close(detailDialog, detailWindow);
    show_managed_window(detailWindow, listMdiSubWindow_);
}

EntityListMdiWindow* {{domain_entity.entity_pascal}}Controller::listWindow() const {
    return listWindow_;
}

}

See also

Emacs 29.1 (Org mode 9.6.6)