Qt facet
Table of Contents
Qt entity UI components live in ores.qt and follow a four-part
structure: a Client<Entity>Model (async data fetching, pagination,
QAbstractTableModel), a list window (toolbar + proxy model + table
view), a detail dialog (form editors, save/cancel), and a history
dialog (read-only versioned view). Codegen (--profile qt) is the
primary path; all four components should be generated from the JSON
model before resorting to manual creation. Return to
Knowledge.
ClientModel layout
The model inherits QAbstractTableModel and is final. It owns
async loading via QFutureWatcher (refresh() launches
QtConcurrent::run that calls the service; onDataLoaded() is
connected via watcher_.setFuture). Pagination is exposed through
load_page(offset, limit). Failure emits loadError (never throws)
so the UI can display a message without crashing.
Recency highlighting: data() returns Qt::BackgroundRole with a
configurable highlight colour for rows whose valid_from is within a
recency window (e.g., last 24 h). This is implemented in the model,
not the view.
List window layout
The list window inherits QWidget and is final. It owns the
Client{Entity}Model and a QSortFilterProxyModel proxy. The
toolbar provides Reload, Add, Edit, Delete (and optionally History)
buttons. Double-click or Edit opens the detail dialog on demand;
the window does not own the dialog — it connects accepted() to
trigger a refresh.
Detail dialog
The detail dialog inherits QDialog and is final. It exposes
set{Entity}(...) to populate for edit and get{Entity}() const to
read back the edited domain object. One QLineEdit or QComboBox
per editable field. On save: call promptChangeReason() (inherited
from DetailDialogBase) to collect audit fields before sending to the
server, then read fields into a domain object, set
change_reason_code and change_commentary on the entity, and call
the service asynchronously (same QtConcurrent + QFutureWatcher
pattern as the model), emit accepted() on success or rejected()
with an error message on failure. On delete: show a confirmation
dialog first, then call promptChangeReason() before the async
delete.
History dialog
Read-only dialog using its own Client{Entity}HistoryModel
(inherits QAbstractTableModel, loads all versions of one entity by
UUID). Opened from the list window via a History toolbar button.
Icon selection
Choose an icon from the icon-guidelines skill. Icons are set on
QAction / QPushButton using QIcon::fromTheme() or embedded resource
paths.
File locations
| Component | Header | Implementation |
|---|---|---|
| ClientModel | include/ores.qt/Client{Entity}Model.hpp |
src/Client{Entity}Model.cpp |
| List window | include/ores.qt/{Entity}ListWindow.hpp |
src/{Entity}ListWindow.cpp |
| Detail dialog | include/ores.qt/{Entity}Dialog.hpp |
src/{Entity}Dialog.cpp |
| History dialog | include/ores.qt/{Entity}HistoryDialog.hpp |
src/{Entity}HistoryDialog.cpp |
| Controller wiring | src/MainWindow.cpp (register in menu + plugin) |
— |
Templates
Generated by --profile qt. Read the template for the authoritative
implementation — do not reproduce it here.
| Template | Output path |
|---|---|
cpp_qt_client_model.hpp.mustache |
include/ores.qt/Client{EntityPascal}Model.hpp |
cpp_qt_client_model.cpp.mustache |
src/Client{EntityPascal}Model.cpp |
cpp_qt_mdi_window.hpp.mustache |
include/ores.qt/{EntityPascal}MdiWindow.hpp |
cpp_qt_mdi_window.cpp.mustache |
src/{EntityPascal}MdiWindow.cpp |
cpp_qt_detail_dialog.hpp.mustache |
include/ores.qt/{EntityPascal}DetailDialog.hpp |
cpp_qt_detail_dialog.cpp.mustache |
src/{EntityPascal}DetailDialog.cpp |
cpp_qt_history_dialog.hpp.mustache |
include/ores.qt/{EntityPascal}HistoryDialog.hpp |
cpp_qt_history_dialog.cpp.mustache |
src/{EntityPascal}HistoryDialog.cpp |
cpp_qt_controller.hpp.mustache |
include/ores.qt/{EntityPascal}Controller.hpp |
cpp_qt_controller.cpp.mustache |
src/{EntityPascal}Controller.cpp |
qt_detail_dialog_ui.mustache |
ui/{EntityPascal}DetailDialog.ui |
qt_history_dialog_ui.mustache |
ui/{EntityPascal}HistoryDialog.ui |
See also
- qt-entity-creator — skill that drives this workflow.
- How do I create Qt UI for a new entity? — recipe walkthrough.
- Qt plugin architecture —
ores.qt.apicontract, plugin lifecycle. - icon-guidelines — icon selection for toolbar actions.
- Entity lifecycle — layer ordering overview.
- cpp_qt — the literate templates that generate this facet.