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

@ -22,8 +22,7 @@ void EditItemDialog::createContent() {
QHBoxLayout* innerLayout = new QHBoxLayout(); QHBoxLayout* innerLayout = new QHBoxLayout();
m_contentContainer->setLayout(innerLayout); m_contentContainer->setLayout(innerLayout);
m_detailMapper = new ItemDetailMapper(this); m_detailMapper = new ItemDetailMapper(m_tableView, this);
m_detailMapper->setModelMappings(m_tableView);
innerLayout->addWidget(m_detailMapper); innerLayout->addWidget(m_detailMapper);
updateQRCode(); updateQRCode();

View File

@ -12,7 +12,7 @@
#include <QTableView> #include <QTableView>
#include "model/metadata.h" #include "model/metadata.h"
ItemDetailMapper::ItemDetailMapper(QWidget* parent) ItemDetailMapper::ItemDetailMapper(QTableView* tableView, QWidget* parent)
: QWidget{parent} { : QWidget{parent} {
/// model mapping /// model mapping
m_mapper = std::make_unique<QDataWidgetMapper>(this); m_mapper = std::make_unique<QDataWidgetMapper>(this);
@ -25,85 +25,17 @@ ItemDetailMapper::ItemDetailMapper(QWidget* parent)
// m_mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit); // m_mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
m_mapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit); 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..."; qDebug() << "Setting model...";
m_tableView = tableView; m_tableView = tableView;
m_model = tableView->model(); m_model = tableView->model();
m_selectionModel = tableView->selectionModel(); m_selectionModel = tableView->selectionModel();
m_mapper->setModel(m_model); 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); setupConnections();
connect(m_model, &QAbstractItemModel::rowsRemoved, this, &ItemDetailMapper::rowsRemoved);
connect(m_selectionModel, &QItemSelectionModel::currentChanged, this,
&ItemDetailMapper::onCurrentIndexChanged);
updateButtons(m_selectionModel->currentIndex().row());
} }
bool ItemDetailMapper::submit() { return m_mapper->submit(); } 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) { void ItemDetailMapper::rowsRemoved(const QModelIndex& parent, int start, int end) {
if (m_model->rowCount() == 0) { if (m_model->rowCount() == 0) {
setEnabled(false); clearEditWidgets();
m_nameEdit->clear();
m_descriptionEdit->clear();
m_infoEdit->clear();
m_amountBox->clear();
m_factorBox->clear();
} }
updateButtons(m_mapper->currentIndex()); updateButtons(m_mapper->currentIndex());
@ -167,3 +93,108 @@ void ItemDetailMapper::emitContentChanged(const QModelIndex& currentIndex) {
} }
emit contentChanged(toStringText); 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 <QStringListModel>
#include <QWidget> #include <QWidget>
class QGridLayout;
class QLabel; class QLabel;
class QLineEdit; class QLineEdit;
class QDoubleSpinBox; class QDoubleSpinBox;
@ -18,9 +19,7 @@ class QTableView;
class ItemDetailMapper : public QWidget { class ItemDetailMapper : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit ItemDetailMapper(QWidget* parent = nullptr); explicit ItemDetailMapper(QTableView* tableView, QWidget* parent = nullptr);
void setModelMappings(QTableView* tableView);
bool submit(); bool submit();
void revert(); void revert();
@ -47,14 +46,8 @@ class ItemDetailMapper : public QWidget {
std::unique_ptr<QDataWidgetMapper> m_mapper; std::unique_ptr<QDataWidgetMapper> m_mapper;
/// GUI elements /// GUI elements
QLabel* m_nameLabel = nullptr; QGridLayout* m_layout;
QLineEdit* m_nameEdit = nullptr; QList<QWidget*> editControls;
QLabel* m_descriptionLabel = nullptr;
QLineEdit* m_descriptionEdit = nullptr;
QLabel* m_infoLabel = nullptr;
QLineEdit* m_infoEdit = nullptr;
QLabel* m_typeLabel; QLabel* m_typeLabel;
QComboBox* m_typeBox; QComboBox* m_typeBox;
@ -68,6 +61,14 @@ class ItemDetailMapper : public QWidget {
QPushButton* m_nextButton; QPushButton* m_nextButton;
QPushButton* m_previousButton; 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 #endif // ITEMDETAILMAPPER_H