Refactored ItemDetailMapper to encapsulate widget creation and their mappings into functions to be able to iterate over meta data to auto generate them. (Only working for string roles for now)

This commit is contained in:
2026-03-02 14:09:55 +01:00
parent d56af7231c
commit 0e7f803d42
3 changed files with 123 additions and 92 deletions

View File

@ -12,7 +12,7 @@
#include <QTableView>
#include "model/metadata.h"
ItemDetailMapper::ItemDetailMapper(QWidget* parent)
ItemDetailMapper::ItemDetailMapper(QTableView* tableView, QWidget* parent)
: QWidget{parent} {
/// model mapping
m_mapper = std::make_unique<QDataWidgetMapper>(this);
@ -25,85 +25,17 @@ ItemDetailMapper::ItemDetailMapper(QWidget* parent)
// m_mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
m_mapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);
/// model mapping buttons
m_nextButton = new QPushButton(tr("Ne&xt"));
m_previousButton = new QPushButton(tr("&Previous"));
connect(m_previousButton, &QAbstractButton::clicked, this, &ItemDetailMapper::toPrevious);
connect(m_nextButton, &QAbstractButton::clicked, this, &ItemDetailMapper::toNext);
/// the individual widgets
// REFACTOR deduce label names and types from meta data & use a factory
m_nameLabel = new QLabel("&Name");
m_nameEdit = new QLineEdit();
m_nameLabel->setBuddy(m_nameEdit);
m_descriptionLabel = new QLabel("&Description");
m_descriptionEdit = new QLineEdit();
m_descriptionLabel->setBuddy(m_descriptionEdit);
m_infoLabel = new QLabel("&Info");
m_infoEdit = new QLineEdit();
m_infoLabel->setBuddy(m_infoEdit);
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_amountLabel = new QLabel("&Amount");
m_amountBox = new QSpinBox();
m_amountBox->setMaximum(1000);
m_amountLabel->setBuddy(m_amountBox);
m_factorLabel = new QLabel("&Factor");
m_factorBox = new QDoubleSpinBox();
m_factorBox->setMaximum(1000);
m_factorLabel->setBuddy(m_factorBox);
QGridLayout* layout = new QGridLayout();
layout->addWidget(m_nameLabel, 0, 0, 1, 1);
layout->addWidget(m_nameEdit, 0, 1, 1, 1);
layout->addWidget(m_descriptionLabel, 1, 0, 1, 1);
layout->addWidget(m_descriptionEdit, 1, 1, 1, 1);
layout->addWidget(m_infoLabel, 2, 0, 1, 1);
layout->addWidget(m_infoEdit, 2, 1, 1, 1);
layout->addWidget(m_typeLabel, 3, 0, 1, 1);
layout->addWidget(m_typeBox, 3, 1, 1, 1);
layout->addWidget(m_amountLabel, 4, 0, 1, 1);
layout->addWidget(m_amountBox, 4, 1, 1, 1);
layout->addWidget(m_factorLabel, 5, 0, 1, 1);
layout->addWidget(m_factorBox, 5, 1, 1, 1);
layout->addWidget(m_previousButton, 6, 0, 1, 1);
layout->addWidget(m_nextButton, 6, 1, 1, 1);
setLayout(layout);
}
void ItemDetailMapper::setModelMappings(QTableView* tableView) {
qDebug() << "Setting model...";
m_tableView = tableView;
m_model = tableView->model();
m_selectionModel = tableView->selectionModel();
m_mapper->setModel(m_model);
m_mapper->addMapping(m_nameEdit, 0);
m_mapper->addMapping(m_descriptionEdit, 1);
m_mapper->addMapping(m_infoEdit, 2);
m_mapper->addMapping(m_typeBox, 3, "currentText");
m_mapper->addMapping(m_amountBox, 4);
m_mapper->addMapping(m_factorBox, 5);
m_mapper->setCurrentIndex(m_selectionModel->currentIndex().row());
setupNavigationButtons();
setupWidgets();
connect(m_model, &QAbstractItemModel::rowsInserted, this, &ItemDetailMapper::rowsInserted);
connect(m_model, &QAbstractItemModel::rowsRemoved, this, &ItemDetailMapper::rowsRemoved);
connect(m_selectionModel, &QItemSelectionModel::currentChanged, this,
&ItemDetailMapper::onCurrentIndexChanged);
updateButtons(m_selectionModel->currentIndex().row());
setupConnections();
}
bool ItemDetailMapper::submit() { return m_mapper->submit(); }
@ -126,13 +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) {
setEnabled(false);
m_nameEdit->clear();
m_descriptionEdit->clear();
m_infoEdit->clear();
m_amountBox->clear();
m_factorBox->clear();
clearEditWidgets();
}
updateButtons(m_mapper->currentIndex());
@ -167,3 +93,108 @@ void ItemDetailMapper::emitContentChanged(const QModelIndex& currentIndex) {
}
emit contentChanged(toStringText);
}
void ItemDetailMapper::setupConnections() {
m_mapper->setCurrentIndex(m_selectionModel->currentIndex().row());
connect(m_model, &QAbstractItemModel::rowsInserted, this, &ItemDetailMapper::rowsInserted);
connect(m_model, &QAbstractItemModel::rowsRemoved, this, &ItemDetailMapper::rowsRemoved);
connect(m_selectionModel, &QItemSelectionModel::currentChanged, this,
&ItemDetailMapper::onCurrentIndexChanged);
updateButtons(m_selectionModel->currentIndex().row());
}
void ItemDetailMapper::setupNavigationButtons() {
m_nextButton = new QPushButton(tr("Ne&xt"));
m_previousButton = new QPushButton(tr("&Previous"));
connect(m_previousButton, &QAbstractButton::clicked, this, &ItemDetailMapper::toPrevious);
connect(m_nextButton, &QAbstractButton::clicked, this, &ItemDetailMapper::toNext);
}
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);
const int nRows = m_layout->rowCount();
m_layout->addWidget(m_previousButton, nRows, 0);
m_layout->addWidget(m_nextButton, nRows, 1);
setLayout(m_layout);
}
void ItemDetailMapper::addWidgetsWithMapping(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);
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();
}
const QString string = QString("&%1").arg(GET_HEADER_FOR_COLUMN(column));
QLabel* label = new QLabel(string);
label->setBuddy(edit);
return QPair<QWidget*, QWidget*>(label, edit);
}
void ItemDetailMapper::clearEditWidgets() {
setEnabled(false);
clearLineEdit(0);
clearLineEdit(1);
clearLineEdit(2);
m_typeBox->setCurrentIndex(m_typeBox->count() - 1);
m_amountBox->clear();
m_factorBox->clear();
}
void ItemDetailMapper::clearLineEdit(const int column) {
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editControls[column]);
if (lineEdit) {
lineEdit->clear();
}
}

View File

@ -6,6 +6,7 @@
#include <QStringListModel>
#include <QWidget>
class QGridLayout;
class QLabel;
class QLineEdit;
class QDoubleSpinBox;
@ -18,9 +19,7 @@ class QTableView;
class ItemDetailMapper : public QWidget {
Q_OBJECT
public:
explicit ItemDetailMapper(QWidget* parent = nullptr);
void setModelMappings(QTableView* tableView);
explicit ItemDetailMapper(QTableView* tableView, QWidget* parent = nullptr);
bool submit();
void revert();
@ -47,14 +46,8 @@ class ItemDetailMapper : public QWidget {
std::unique_ptr<QDataWidgetMapper> m_mapper;
/// GUI elements
QLabel* m_nameLabel = nullptr;
QLineEdit* m_nameEdit = nullptr;
QLabel* m_descriptionLabel = nullptr;
QLineEdit* m_descriptionEdit = nullptr;
QLabel* m_infoLabel = nullptr;
QLineEdit* m_infoEdit = nullptr;
QGridLayout* m_layout;
QList<QWidget*> editControls;
QLabel* m_typeLabel;
QComboBox* m_typeBox;
@ -68,6 +61,14 @@ class ItemDetailMapper : public QWidget {
QPushButton* m_nextButton;
QPushButton* m_previousButton;
void setupConnections();
void setupLayout();
void setupWidgets();
void addWidgetsWithMapping(const int row);
QPair<QWidget*, QWidget*> createWidgetPairForColumn(const int column);
void clearEditWidgets();
};
#endif // ITEMDETAILMAPPER_H