From 560cadb2c0ea280804edf5e04be2cb9059f21157 Mon Sep 17 00:00:00 2001 From: Bent Witthold Date: Mon, 2 Mar 2026 17:11:31 +0100 Subject: [PATCH] All mapped control widgets (plus labels) are dynamically generated from meta data. --- views/itemdetailmapper.cpp | 142 ++++++++++++++++++++++--------------- views/itemdetailmapper.h | 25 +++---- 2 files changed, 93 insertions(+), 74 deletions(-) diff --git a/views/itemdetailmapper.cpp b/views/itemdetailmapper.cpp index e00cd27..4f814c6 100644 --- a/views/itemdetailmapper.cpp +++ b/views/itemdetailmapper.cpp @@ -58,7 +58,7 @@ void ItemDetailMapper::rowsInserted(const QModelIndex& parent, int start, int en void ItemDetailMapper::rowsRemoved(const QModelIndex& parent, int start, int end) { if (m_model->rowCount() == 0) { - clearEditWidgets(); + clearControlWidgets(); } updateButtons(m_mapper->currentIndex()); @@ -116,34 +116,9 @@ void ItemDetailMapper::setupNavigationButtons() { void ItemDetailMapper::setupWidgets() { m_layout = new QGridLayout(); - addWidgetsWithMapping(0); - addWidgetsWithMapping(1); - addWidgetsWithMapping(2); - - m_typeLabel = new QLabel(GET_HEADER_FOR_COLUMN(3)); - m_typeBox = new QComboBox(); - m_typeLabel->setBuddy(m_typeBox); - m_typeModel = new QStringListModel(TYPES, this); - m_typeBox->setModel(m_typeModel); - m_layout->addWidget(m_typeLabel, 3, 0); - m_layout->addWidget(m_typeBox, 3, 1); - m_mapper->addMapping(m_typeBox, 3, "currentText"); - - m_amountLabel = new QLabel("&Amount"); - m_amountBox = new QSpinBox(); - m_amountBox->setMaximum(1000); - m_amountLabel->setBuddy(m_amountBox); - m_layout->addWidget(m_amountLabel, 4, 0); - m_layout->addWidget(m_amountBox, 4, 1); - m_mapper->addMapping(m_amountBox, 4); - - m_factorLabel = new QLabel("&Factor"); - m_factorBox = new QDoubleSpinBox(); - m_factorBox->setMaximum(1000); - m_factorLabel->setBuddy(m_factorBox); - m_layout->addWidget(m_factorLabel, 5, 0); - m_layout->addWidget(m_factorBox, 5, 1); - m_mapper->addMapping(m_factorBox, 5); + for (int i = 0; i < USER_FACING_ROLES.size(); ++i) { + setupWidgetPairForColumn(i); + } const int nRows = m_layout->rowCount(); m_layout->addWidget(m_previousButton, nRows, 0); @@ -152,49 +127,98 @@ void ItemDetailMapper::setupWidgets() { setLayout(m_layout); } -void ItemDetailMapper::addWidgetsWithMapping(const int column) { - QPair widgetPair0 = createWidgetPairForColumn(column); - QWidget* control = widgetPair0.second; - m_layout->addWidget(widgetPair0.first, column, 0); - m_layout->addWidget(control, column, 1); - m_mapper->addMapping(control, column); - editControls.append(control); -} - -QPair ItemDetailMapper::createWidgetPairForColumn(const int column) { +void ItemDetailMapper::setupWidgetPairForColumn(const int column) { const UserRoles role = GET_ROLE_FOR_COLUMN(column); - QWidget* edit; - if (STRING_ROLES.contains(role)) { - edit = new QLineEdit(); - } else { - qCritical() - << QString("Only string roles are supported yet. But tried with role %1!!!").arg(role); - qDebug() << "Using line edit as well and pretend it's a string role..."; - edit = new QLineEdit(); - } + QWidget* control = createControlWidget(role); const QString string = QString("&%1").arg(GET_HEADER_FOR_COLUMN(column)); QLabel* label = new QLabel(string); - label->setBuddy(edit); - return QPair(label, edit); + label->setBuddy(control); + + m_layout->addWidget(label, column, 0); + m_layout->addWidget(control, column, 1); + m_controlWidgets.append(control); + + if (TYPE_ROLES.contains(role)) { + m_mapper->addMapping(control, column, "currentText"); + } else { + m_mapper->addMapping(control, column); + } } -void ItemDetailMapper::clearEditWidgets() { +QWidget* ItemDetailMapper::createControlWidget(const int role) { + QWidget* control; + if (STRING_ROLES.contains(role)) { + control = new QLineEdit(); + } else if (TYPE_ROLES.contains(role)) { + control = createComboBox(role); + } else if (INT_ROLES.contains(role)) { + QSpinBox* spinBox = new QSpinBox(); + spinBox->setMaximum(1000); + control = spinBox; + } else if (DOUBLE_ROLES.contains(role)) { + QDoubleSpinBox* spinBox = new QDoubleSpinBox(); + spinBox->setMaximum(1000); + control = spinBox; + } else { + qCritical() << QString("Unsupported role %1!!!").arg(role); + qDebug() << "Using line edit as well and pretend it's a string role..."; + control = new QLineEdit(); + } + return control; +} + +QWidget* ItemDetailMapper::createComboBox(const int role) { + QStringListModel* typeModel; + if (role == TypeRole) { + typeModel = new QStringListModel(TYPES, this); + } else { + qCritical() << "Unsupported type with role:" << role + << "- Using string list model with only one empty string!"; + typeModel = new QStringListModel({""}, this); + } + QComboBox* comboBox = new QComboBox(); + comboBox->setModel(typeModel); + return comboBox; +} + +void ItemDetailMapper::clearControlWidgets() { setEnabled(false); - clearLineEdit(0); - clearLineEdit(1); - clearLineEdit(2); - - m_typeBox->setCurrentIndex(m_typeBox->count() - 1); - m_amountBox->clear(); - m_factorBox->clear(); + for (int i = 0; i < m_controlWidgets.size(); ++i) { + const UserRoles role = GET_ROLE_FOR_COLUMN(i); + if (STRING_ROLES.contains(role)) { + clearLineEdit(i); + } else if (TYPE_ROLES.contains(role)) { + clearComboBox(i); + } else if (INT_ROLES.contains(role)) { + clearSpinBox(i); + } else if (DOUBLE_ROLES.contains(role)) { + clearSpinBox(i); + } else { + qCritical() << "Could not reset content for control widget in column:" << i << "!"; + } + } } void ItemDetailMapper::clearLineEdit(const int column) { - QLineEdit* lineEdit = dynamic_cast(editControls[column]); + QLineEdit* lineEdit = dynamic_cast(m_controlWidgets[column]); if (lineEdit) { lineEdit->clear(); } } + +void ItemDetailMapper::clearComboBox(const int column) { + QComboBox* comboBox = dynamic_cast(m_controlWidgets[column]); + if (comboBox) { + comboBox->setCurrentText(""); + } +} + +void ItemDetailMapper::clearSpinBox(const int column) { + QAbstractSpinBox* spinBox = dynamic_cast(m_controlWidgets[column]); + if (spinBox) { + spinBox->clear(); + } +} diff --git a/views/itemdetailmapper.h b/views/itemdetailmapper.h index a89ccfe..bb34f54 100644 --- a/views/itemdetailmapper.h +++ b/views/itemdetailmapper.h @@ -47,28 +47,23 @@ class ItemDetailMapper : public QWidget { /// GUI elements QGridLayout* m_layout; - QList editControls; - - QLabel* m_typeLabel; - QComboBox* m_typeBox; - QStringListModel* m_typeModel = nullptr; - - QLabel* m_amountLabel = nullptr; - QSpinBox* m_amountBox = nullptr; - - QLabel* m_factorLabel = nullptr; - QDoubleSpinBox* m_factorBox = nullptr; + QList m_controlWidgets; QPushButton* m_nextButton; QPushButton* m_previousButton; void setupConnections(); - void setupLayout(); + void setupNavigationButtons(); void setupWidgets(); - void addWidgetsWithMapping(const int row); - QPair createWidgetPairForColumn(const int column); - void clearEditWidgets(); + void setupWidgetPairForColumn(const int column); + QWidget* createControlWidget(const int column); + QWidget* createComboBox(const int role); + + void clearControlWidgets(); + void clearLineEdit(const int column); + void clearComboBox(const int column); + void clearSpinBox(const int column); }; #endif // ITEMDETAILMAPPER_H