All mapped control widgets (plus labels) are dynamically generated from meta data.

This commit is contained in:
2026-03-02 17:11:31 +01:00
parent 0e7f803d42
commit 560cadb2c0
2 changed files with 93 additions and 74 deletions

View File

@ -58,7 +58,7 @@ void ItemDetailMapper::rowsInserted(const QModelIndex& parent, int start, int en
void ItemDetailMapper::rowsRemoved(const QModelIndex& parent, int start, int end) { void ItemDetailMapper::rowsRemoved(const QModelIndex& parent, int start, int end) {
if (m_model->rowCount() == 0) { if (m_model->rowCount() == 0) {
clearEditWidgets(); clearControlWidgets();
} }
updateButtons(m_mapper->currentIndex()); updateButtons(m_mapper->currentIndex());
@ -116,34 +116,9 @@ void ItemDetailMapper::setupNavigationButtons() {
void ItemDetailMapper::setupWidgets() { void ItemDetailMapper::setupWidgets() {
m_layout = new QGridLayout(); m_layout = new QGridLayout();
addWidgetsWithMapping(0); for (int i = 0; i < USER_FACING_ROLES.size(); ++i) {
addWidgetsWithMapping(1); setupWidgetPairForColumn(i);
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);
const int nRows = m_layout->rowCount(); const int nRows = m_layout->rowCount();
m_layout->addWidget(m_previousButton, nRows, 0); m_layout->addWidget(m_previousButton, nRows, 0);
@ -152,49 +127,98 @@ void ItemDetailMapper::setupWidgets() {
setLayout(m_layout); setLayout(m_layout);
} }
void ItemDetailMapper::addWidgetsWithMapping(const int column) { void ItemDetailMapper::setupWidgetPairForColumn(const int column) {
QPair<QWidget*, QWidget*> 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<QWidget*, QWidget*> ItemDetailMapper::createWidgetPairForColumn(const int column) {
const UserRoles role = GET_ROLE_FOR_COLUMN(column); const UserRoles role = GET_ROLE_FOR_COLUMN(column);
QWidget* edit; QWidget* control = createControlWidget(role);
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();
}
const QString string = QString("&%1").arg(GET_HEADER_FOR_COLUMN(column)); const QString string = QString("&%1").arg(GET_HEADER_FOR_COLUMN(column));
QLabel* label = new QLabel(string); QLabel* label = new QLabel(string);
label->setBuddy(edit); label->setBuddy(control);
return QPair<QWidget*, QWidget*>(label, edit);
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); setEnabled(false);
clearLineEdit(0); for (int i = 0; i < m_controlWidgets.size(); ++i) {
clearLineEdit(1); const UserRoles role = GET_ROLE_FOR_COLUMN(i);
clearLineEdit(2); if (STRING_ROLES.contains(role)) {
clearLineEdit(i);
m_typeBox->setCurrentIndex(m_typeBox->count() - 1); } else if (TYPE_ROLES.contains(role)) {
m_amountBox->clear(); clearComboBox(i);
m_factorBox->clear(); } 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) { void ItemDetailMapper::clearLineEdit(const int column) {
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editControls[column]); QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(m_controlWidgets[column]);
if (lineEdit) { if (lineEdit) {
lineEdit->clear(); lineEdit->clear();
} }
} }
void ItemDetailMapper::clearComboBox(const int column) {
QComboBox* comboBox = dynamic_cast<QComboBox*>(m_controlWidgets[column]);
if (comboBox) {
comboBox->setCurrentText("");
}
}
void ItemDetailMapper::clearSpinBox(const int column) {
QAbstractSpinBox* spinBox = dynamic_cast<QAbstractSpinBox*>(m_controlWidgets[column]);
if (spinBox) {
spinBox->clear();
}
}

View File

@ -47,28 +47,23 @@ class ItemDetailMapper : public QWidget {
/// GUI elements /// GUI elements
QGridLayout* m_layout; QGridLayout* m_layout;
QList<QWidget*> editControls; QList<QWidget*> m_controlWidgets;
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;
QPushButton* m_nextButton; QPushButton* m_nextButton;
QPushButton* m_previousButton; QPushButton* m_previousButton;
void setupConnections(); void setupConnections();
void setupLayout(); void setupNavigationButtons();
void setupWidgets(); void setupWidgets();
void addWidgetsWithMapping(const int row); void setupWidgetPairForColumn(const int column);
QPair<QWidget*, QWidget*> createWidgetPairForColumn(const int column); QWidget* createControlWidget(const int column);
void clearEditWidgets(); 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 #endif // ITEMDETAILMAPPER_H