ores.cpp.qt.detail_dialog_header

Table of Contents

Detail dialog declarations. 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.

Extension points

<<paste:UUID>> markers in this template are paste-block injection points — see paste blocks: injecting custom code into generated files for the full mechanism. This header defines one:

  • F55CB64E-165A-4E15-A50A-5723C0320E97 — in private:, after the generated method declarations. Pairs with the implementation seam of the same purpose in ores.cpp.qt.detail_dialog_impl (EC97923E-BC8D-4A50-9970-CBC5CBD4B732) — an entity declares any extra private methods here that block implements.
  • 9C3E6A1D-4B8F-4D2C-8A5E-3F1B7C9D2E6A — after the generated includes, before the Ui forward declaration. Use for any type used by a F55CB64E member/method declaration that isn't already visible (e.g. a hand-written helper class's header) — a forward declaration alone is not enough for by-value or unique_ptr<T> members, so most entities will need a real #include here.
  • EC19A4EE-363D-4D41-A33A-D5F85A139C80 — in the dialog's own signals:, after the generated Saved=/=Deleted=/(optional) =revertRequested signals. Declares a custom dialog signal, e.g. for a toolbar action the dialog can't act on itself. Pair with the controller-side seam that relays it upward (DF72DFCF-FD65-4FE5-98BA-CB8168CE0FDF in ores.cpp.qt.controller_impl, via the controller header's own signals: seam 66E078FB-D6A6-4DF6-814B-65995D948090 in ores.cpp.qt.controller_header).

Template

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

{{! GENERATED FILE — tangled from projects/ores.codegen/library/templates/cpp_qt.org. Edit the org source. }}
{{! Template to generate Qt detail dialog header for domain entities }}
{{{cpp_license}}}
#ifndef ORES_QT_{{domain_entity.entity_upper}}_DETAIL_DIALOG_HPP
#define ORES_QT_{{domain_entity.entity_upper}}_DETAIL_DIALOG_HPP

#include <vector>
#include "ores.qt/ClientManager.hpp"
#include "ores.qt/DetailDialogBase.hpp"
#include "ores.logging/make_logger.hpp"
#include "{{domain_entity.qt.domain_include}}"
{{#domain_entity.qt.has_setting_gated_actions}}
#include "ores.qt/SettingGatedActionController.hpp"
#include <QAction>
{{/domain_entity.qt.has_setting_gated_actions}}
{{#domain_entity.qt.has_version_navigation}}
#include <vector>
{{/domain_entity.qt.has_version_navigation}}
{{#domain_entity.qt.has_generate_action}}
#include "ores.{{domain_entity.component_include}}/{{domain_entity.generator_facet_name}}/{{domain_entity.entity_singular}}_generator.hpp"
#include "ores.utility/generation/generation_context.hpp"
{{/domain_entity.qt.has_generate_action}}
{{#domain_entity.qt.has_toolbar}}
#include "ores.qt/IconUtils.hpp"
#include <QAction>
#include <QToolBar>
{{/domain_entity.qt.has_toolbar}}
{{#domain_entity.qt.detail_fields}}{{#is_dynamic_combo}}
{{^combo_fetch_fn}}
#include "{{combo_include}}"
{{/combo_fetch_fn}}
{{#combo_fetch_fn}}
#include "{{combo_fetch_include}}"
{{/combo_fetch_fn}}
{{/is_dynamic_combo}}{{/domain_entity.qt.detail_fields}}
{{#domain_entity.qt.has_flagged_combo_fields}}
#include "ores.qt/FlagIconHelper.hpp"
#include "ores.qt/LookupFetcher.hpp"
{{/domain_entity.qt.has_flagged_combo_fields}}
{{#domain_entity.qt.has_colour_fields}}
#include "ores.qt/ColourSwatchHelper.hpp"
#include <QPushButton>
{{/domain_entity.qt.has_colour_fields}}
<<paste:9C3E6A1D-4B8F-4D2C-8A5E-3F1B7C9D2E6A>>

namespace Ui {
class {{domain_entity.entity_pascal}}DetailDialog;
}

namespace ores::qt {

/**
 * @brief Detail dialog for viewing and editing {{domain_entity.entity_singular_words}} records.
 *
 * This dialog allows viewing, creating, and editing {{domain_entity.entity_plural_words}}.
 * It supports both create mode (for new records) and edit mode (for
 * existing records).
 */
class {{domain_entity.entity_pascal}}DetailDialog final : public DetailDialogBase {
    Q_OBJECT

private:
    inline static std::string_view logger_name =
        "ores.qt.{{domain_entity.entity_snake}}_detail_dialog";

    [[nodiscard]] static auto& lg() {
        using namespace ores::logging;
        static auto instance = make_logger(logger_name);
        return instance;
    }

public:
    explicit {{domain_entity.entity_pascal}}DetailDialog(QWidget* parent = nullptr);
    ~{{domain_entity.entity_pascal}}DetailDialog() override;

    void setClientManager(ClientManager* clientManager);
    void setUsername(const std::string& username);
    void set{{domain_entity.entity_pascal_short}}(const {{domain_entity.qt.domain_class}}& {{domain_entity.qt.item_var}});
    void setCreateMode(bool createMode);
{{^domain_entity.qt.has_version_navigation}}
    void setReadOnly(bool readOnly);
{{/domain_entity.qt.has_version_navigation}}
{{#domain_entity.qt.has_version_navigation}}
    void setReadOnly(bool readOnly, int versionNumber = 0);

    /**
     * @brief Sets the history for version navigation.
     *
     * Shows a navigation toolbar allowing the user to navigate between
     * versions (first/prev/next/last); the flag is grayed out for
     * non-latest versions.
     *
     * @param history All versions ordered newest-first (index 0 is latest)
     * @param versionNumber The version number to initially display
     */
    void setHistory(const std::vector<{{domain_entity.qt.domain_class}}>& history, int versionNumber);
{{/domain_entity.qt.has_version_navigation}}

    /**
     * @brief Force the dialog into the unsaved-changes state.
     *
     * Used when values are loaded programmatically and must be savable
     * immediately even though the user typed nothing — e.g. a revert, where
     * the act of loading a past version's values is itself the change.
     */
    void markDirty();
{{#domain_entity.qt.detail_fields}}{{#is_dynamic_combo}}{{^combo_fetch_fn}}
    void {{combo_setter}}(const std::vector<{{combo_type}}>& items);
{{/combo_fetch_fn}}{{/is_dynamic_combo}}{{/domain_entity.qt.detail_fields}}

signals:
    void {{domain_entity.qt.item_var}}Saved(const QString& code);
    void {{domain_entity.qt.item_var}}Deleted(const QString& code);
{{#domain_entity.qt.has_version_navigation}}

    /**
     * @brief Emitted when user requests to revert to the displayed historical version.
     * @param {{domain_entity.qt.item_var}} The {{domain_entity.entity_singular_words}} data to revert to.
     */
    void revertRequested(const {{domain_entity.qt.domain_class}}& {{domain_entity.qt.item_var}});
{{/domain_entity.qt.has_version_navigation}}
<<paste:EC19A4EE-363D-4D41-A33A-D5F85A139C80>>

private slots:
    void onSaveClicked();
    void onDeleteClicked();
{{#domain_entity.qt.has_line_edit_key}}
    void onCodeChanged(const QString& text);
{{/domain_entity.qt.has_line_edit_key}}
    void onFieldChanged();
{{#domain_entity.qt.has_version_navigation}}
    void onRevertClicked();
    void onFirstVersionClicked();
    void onPrevVersionClicked();
    void onNextVersionClicked();
    void onLastVersionClicked();
{{/domain_entity.qt.has_version_navigation}}
{{#domain_entity.qt.has_generate_action}}
    void onGenerateClicked();
{{/domain_entity.qt.has_generate_action}}

protected:
    QTabWidget* tabWidget() const override;
    QWidget* provenanceTab() const override;
    ProvenanceWidget* provenanceWidget() const override;
    bool hasUnsavedChanges() const override { return hasChanges_; }
    QString code() const override;
{{#domain_entity.qt.has_flag_icon}}
    std::optional<boost::uuids::uuid> entityImageId() const override;
{{/domain_entity.qt.has_flag_icon}}
{{#domain_entity.qt.has_key_flag_icon}}
    QLineEdit* keyFlagField() const override;
    QIcon keyFlagIcon(const std::string& key) const override;
{{#domain_entity.qt.key_flag_is_pair}}
    QSize keyFlagIconSize() const override;
{{/domain_entity.qt.key_flag_is_pair}}
{{/domain_entity.qt.has_key_flag_icon}}

private:
    void setupUi();
    void setupConnections();
{{#domain_entity.qt.has_combo_fields}}
    void setupCombos();
{{/domain_entity.qt.has_combo_fields}}
    void updateUiFrom{{domain_entity.entity_pascal_short}}();
    void update{{domain_entity.entity_pascal_short}}FromUi();
    void updateSaveButtonState();
    bool validateInput();
{{#domain_entity.qt.detail_fields}}{{#is_dynamic_combo}}
    void populate{{combo_setter_pascal}}();
{{/is_dynamic_combo}}{{/domain_entity.qt.detail_fields}}
{{#domain_entity.qt.detail_fields}}{{#is_flagged_combo}}
    void populate{{field_pascal}}Combo();
{{/is_flagged_combo}}{{/domain_entity.qt.detail_fields}}
{{#domain_entity.qt.has_version_navigation}}
    void displayCurrentVersion();
    void updateVersionNavButtonStates();
    void showVersionNavActions(bool visible);
{{/domain_entity.qt.has_version_navigation}}
{{#domain_entity.qt.has_generate_action}}
    void setupGenerateAction();
{{/domain_entity.qt.has_generate_action}}
{{! see * Extension points above }}
<<paste:F55CB64E-165A-4E15-A50A-5723C0320E97>>

    Ui::{{domain_entity.entity_pascal}}DetailDialog* ui_;
    ClientManager* clientManager_;
    std::string username_;
    {{domain_entity.qt.domain_class}} {{domain_entity.qt.item_var}}_;
    bool createMode_{true};
    bool readOnly_{false};
    bool hasChanges_{false};
{{#domain_entity.qt.detail_fields}}{{#is_dynamic_combo}}{{^combo_fetch_fn}}
    std::vector<{{combo_type}}> {{combo_items_member}}_;
{{/combo_fetch_fn}}{{/is_dynamic_combo}}{{/domain_entity.qt.detail_fields}}
{{#domain_entity.qt.has_setting_gated_actions}}
{{#domain_entity.qt.setting_gated_actions}}
    QAction* {{action}}_;
{{/domain_entity.qt.setting_gated_actions}}
    SettingGatedActionController* settingGatedActions_{nullptr};
{{/domain_entity.qt.has_setting_gated_actions}}
{{#domain_entity.qt.has_toolbar}}
    QToolBar* toolBar_{nullptr};
{{/domain_entity.qt.has_toolbar}}
{{#domain_entity.qt.has_version_navigation}}
    QAction* revertAction_{nullptr};
    QAction* firstVersionAction_{nullptr};
    QAction* prevVersionAction_{nullptr};
    QAction* nextVersionAction_{nullptr};
    QAction* lastVersionAction_{nullptr};
    std::vector<{{domain_entity.qt.domain_class}}> history_;
    int currentHistoryIndex_{0};
    int historicalVersion_{0};
{{/domain_entity.qt.has_version_navigation}}
};

}

#endif

See also

Emacs 29.3 (Org mode 9.6.15)