#include "itemdetailmapper.h" #include #include #include #include #include #include #include #include #include #include #include "model/metadata.h" ItemDetailMapper::ItemDetailMapper(QTableView* tableView, QWidget* parent) : QWidget{parent} { /// model mapping m_mapper = std::make_unique(this); /// BUG: If multiple columns are changed not all changes are applied. /// Multiple changes are set individually by calling setData(). /// Probably due to a conflicting dataChanged signal for too many roles&columns the data of /// the remaining columns is reset before setData is called. /// And a manual submit would also create multiple undo steps anyway. /// Workaround: ManualSubmit -> AutoSubmit // m_mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit); m_mapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit); qDebug() << "Setting model..."; m_tableView = tableView; m_model = tableView->model(); m_selectionModel = tableView->selectionModel(); m_mapper->setModel(m_model); setupNavigationButtons(); setupWidgets(); setupConnections(); } bool ItemDetailMapper::submit() { return m_mapper->submit(); } void ItemDetailMapper::revert() { m_mapper->revert(); } void ItemDetailMapper::onCurrentIndexChanged(const QModelIndex& current, const QModelIndex& /*previous*/) { if (!isEnabled()) { setEnabled(true); } m_mapper->setCurrentModelIndex(current); updateButtons(current.row()); emitContentChanged(current); } void ItemDetailMapper::rowsInserted(const QModelIndex& parent, int start, int end) { updateButtons(m_mapper->currentIndex()); } void ItemDetailMapper::rowsRemoved(const QModelIndex& parent, int start, int end) { if (m_model->rowCount() == 0) { clearEditWidgets(); } updateButtons(m_mapper->currentIndex()); } void ItemDetailMapper::toPrevious() { int currentRow = m_selectionModel->currentIndex().row(); QModelIndex previousIndex = m_selectionModel->currentIndex().siblingAtRow(currentRow - 1); if (previousIndex.isValid()) { m_selectionModel->setCurrentIndex(previousIndex, QItemSelectionModel::ClearAndSelect); } } void ItemDetailMapper::toNext() { int currentRow = m_selectionModel->currentIndex().row(); QModelIndex nextIndex = m_selectionModel->currentIndex().siblingAtRow(currentRow + 1); if (nextIndex.isValid()) { m_selectionModel->setCurrentIndex(nextIndex, QItemSelectionModel::ClearAndSelect); } } void ItemDetailMapper::updateButtons(int row) { m_previousButton->setEnabled(row > 0); m_nextButton->setEnabled(row < m_model->rowCount() - 1); } void ItemDetailMapper::emitContentChanged(const QModelIndex& currentIndex) { // BUG QR-Code isn't updated after changes through the ItemDetailMapper #18 QString toStringText = ""; if (currentIndex.isValid()) { toStringText = currentIndex.data(ToStringRole).toString(); } 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 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) { 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(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(editControls[column]); if (lineEdit) { lineEdit->clear(); } }