Merge branch 'feature/UndoRedoWithModelData' into develop
This commit is contained in:
@ -29,8 +29,10 @@ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
|||||||
${PROJECT_SOURCES}
|
${PROJECT_SOURCES}
|
||||||
utils/messagehandler.h
|
utils/messagehandler.h
|
||||||
assets/icons.qrc
|
assets/icons.qrc
|
||||||
Dialogs/abstractdialog.h Dialogs/abstractdialog.cpp
|
dialogs/abstractdialog.h dialogs/abstractdialog.cpp
|
||||||
Dialogs/newitemdialog.h Dialogs/newitemdialog.cpp
|
dialogs/newitemdialog.h dialogs/newitemdialog.cpp
|
||||||
|
dialogs/edititemdialog.h dialogs/edititemdialog.cpp
|
||||||
|
views/itemdetailmapper.h views/itemdetailmapper.cpp
|
||||||
)
|
)
|
||||||
# Define target properties for Android with Qt 6 as:
|
# Define target properties for Android with Qt 6 as:
|
||||||
# set_property(TARGET ${TARGET_APP} APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
|
# set_property(TARGET ${TARGET_APP} APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
|
||||||
|
|||||||
32
dialogs/edititemdialog.cpp
Normal file
32
dialogs/edititemdialog.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include "edititemdialog.h"
|
||||||
|
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include "../views/itemdetailmapper.h"
|
||||||
|
|
||||||
|
EditItemDialog::EditItemDialog(QTableView* tableView, QWidget* parent)
|
||||||
|
: AbstractDialog(parent)
|
||||||
|
, m_tableView(tableView) {}
|
||||||
|
|
||||||
|
void EditItemDialog::createContent() {
|
||||||
|
if (m_contentContainer) {
|
||||||
|
delete m_contentContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
setWindowTitle(tr("Edit item..."));
|
||||||
|
|
||||||
|
m_detailMapper = new ItemDetailMapper(this);
|
||||||
|
m_detailMapper->setModelMappings(m_tableView);
|
||||||
|
m_contentContainer = m_detailMapper;
|
||||||
|
|
||||||
|
m_outerLayout->insertWidget(0, m_contentContainer);
|
||||||
|
|
||||||
|
void EditItemDialog::accept() {
|
||||||
|
m_detailMapper->submit();
|
||||||
|
QDialog::accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditItemDialog::reject() {
|
||||||
|
m_detailMapper->revert();
|
||||||
|
QDialog::reject();
|
||||||
|
}
|
||||||
46
dialogs/edititemdialog.h
Normal file
46
dialogs/edititemdialog.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef EDITITEMDIALOG_H
|
||||||
|
#define EDITITEMDIALOG_H
|
||||||
|
|
||||||
|
#include "abstractdialog.h"
|
||||||
|
|
||||||
|
class QDoubleSpinBox;
|
||||||
|
class QLineEdit;
|
||||||
|
class QSpinBox;
|
||||||
|
class QLabel;
|
||||||
|
class QTableView;
|
||||||
|
|
||||||
|
class ItemDetailMapper;
|
||||||
|
|
||||||
|
class EditItemDialog : public AbstractDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
EditItemDialog(QTableView* tableView, QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
/// AbstractDialog interface
|
||||||
|
void createContent() override;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void accept() override;
|
||||||
|
void reject() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTableView* m_tableView = nullptr;
|
||||||
|
ItemDetailMapper* m_detailMapper;
|
||||||
|
|
||||||
|
QLabel* m_nameLabel = nullptr;
|
||||||
|
QLineEdit* m_nameEdit = nullptr;
|
||||||
|
|
||||||
|
QLabel* m_descriptionLabel = nullptr;
|
||||||
|
QLineEdit* m_descriptionEdit = nullptr;
|
||||||
|
|
||||||
|
QLabel* m_infoLabel = nullptr;
|
||||||
|
QLineEdit* m_infoEdit = nullptr;
|
||||||
|
|
||||||
|
QLabel* m_amountLabel = nullptr;
|
||||||
|
QSpinBox* m_amountBox = nullptr;
|
||||||
|
|
||||||
|
QLabel* m_factorLabel = nullptr;
|
||||||
|
QDoubleSpinBox* m_factorBox = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EDITITEMDIALOG_H
|
||||||
@ -7,6 +7,7 @@ class QDoubleSpinBox;
|
|||||||
class QLineEdit;
|
class QLineEdit;
|
||||||
class QSpinBox;
|
class QSpinBox;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
|
|
||||||
class NewItemDialog : public AbstractDialog {
|
class NewItemDialog : public AbstractDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
116
mainwindow.cpp
116
mainwindow.cpp
@ -3,10 +3,13 @@
|
|||||||
|
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QUndoStack>
|
||||||
|
#include <QUndoView>
|
||||||
|
|
||||||
#include "../../ApplicationConfig.h"
|
#include "../../ApplicationConfig.h"
|
||||||
#include "Dialogs/newitemdialog.h"
|
|
||||||
#include "data/settingshandler.h"
|
#include "data/settingshandler.h"
|
||||||
|
#include "dialogs/edititemdialog.h"
|
||||||
|
#include "dialogs/newitemdialog.h"
|
||||||
#include "genericcore.h"
|
#include "genericcore.h"
|
||||||
#include "model/tablemodel.h"
|
#include "model/tablemodel.h"
|
||||||
|
|
||||||
@ -19,6 +22,7 @@ MainWindow::MainWindow(QWidget* parent)
|
|||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
m_core = std::make_unique<GenericCore>();
|
m_core = std::make_unique<GenericCore>();
|
||||||
|
setWindowTitle(windowTitle() + " [*]");
|
||||||
|
|
||||||
/// application icon
|
/// application icon
|
||||||
const QString iconString = "://feature.png";
|
const QString iconString = "://feature.png";
|
||||||
@ -49,10 +53,13 @@ MainWindow::MainWindow(QWidget* parent)
|
|||||||
connect(this, &MainWindow::checkForUpdates, this,
|
connect(this, &MainWindow::checkForUpdates, this,
|
||||||
&MainWindow::on_actionCheck_for_update_triggered, Qt::QueuedConnection);
|
&MainWindow::on_actionCheck_for_update_triggered, Qt::QueuedConnection);
|
||||||
|
|
||||||
connect(ui->tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
|
// connect(ui->tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
|
||||||
&MainWindow::onSelectionChanged);
|
// &MainWindow::onSelectionChanged);
|
||||||
|
connect(ui->tableView->selectionModel(), &QItemSelectionModel::currentChanged, this,
|
||||||
|
&MainWindow::onCurrentChanged);
|
||||||
|
|
||||||
onSelectionChanged(QItemSelection(), QItemSelection());
|
onSelectionChanged(QItemSelection(), QItemSelection());
|
||||||
|
onCurrentChanged(QModelIndex(), QModelIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow() { delete ui; }
|
MainWindow::~MainWindow() { delete ui; }
|
||||||
@ -100,6 +107,20 @@ void MainWindow::showStatusMessage(const QString text) {
|
|||||||
ui->statusbar->showMessage(text);
|
ui->statusbar->showMessage(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onCurrentChanged(const QModelIndex& current, const QModelIndex& previous) {
|
||||||
|
// Q_UNUSED(current);
|
||||||
|
Q_UNUSED(previous);
|
||||||
|
|
||||||
|
// QItemSelection localSelection = ui->tableView->selectionModel()->selection();
|
||||||
|
if (current == QModelIndex()) {
|
||||||
|
// qDebug() << "Nothing selected. Disabling delete action";
|
||||||
|
m_deleteItemAct->setEnabled(false);
|
||||||
|
} else {
|
||||||
|
// qDebug() << "Something selected. Enabling delete action";
|
||||||
|
m_deleteItemAct->setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::onSelectionChanged(const QItemSelection& selected,
|
void MainWindow::onSelectionChanged(const QItemSelection& selected,
|
||||||
const QItemSelection& deselected) {
|
const QItemSelection& deselected) {
|
||||||
Q_UNUSED(selected);
|
Q_UNUSED(selected);
|
||||||
@ -153,6 +174,22 @@ void MainWindow::openNewItemDialog() {
|
|||||||
m_newItemDialog->show();
|
m_newItemDialog->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::openEditItemDialog() {
|
||||||
|
showStatusMessage(tr("Invoked 'Edit|Edit Item'"));
|
||||||
|
m_editItemDialog->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::deleteCurrentItem() {
|
||||||
|
showStatusMessage(tr("Invoked 'Edit|Delete Item'"));
|
||||||
|
// QItemSelection localSelection = ui->tableView->selectionModel()->selection();
|
||||||
|
const QModelIndex currentIndex = ui->tableView->selectionModel()->currentIndex();
|
||||||
|
if (currentIndex == QModelIndex()) {
|
||||||
|
qDebug() << "No current item. Nothing to remove.";
|
||||||
|
} else {
|
||||||
|
m_tableModel->removeRows(currentIndex.row(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::deleteSelectedtItems() {
|
void MainWindow::deleteSelectedtItems() {
|
||||||
showStatusMessage(tr("Invoked 'Edit|Delete Item'"));
|
showStatusMessage(tr("Invoked 'Edit|Delete Item'"));
|
||||||
QItemSelection localSelection = ui->tableView->selectionModel()->selection();
|
QItemSelection localSelection = ui->tableView->selectionModel()->selection();
|
||||||
@ -172,9 +209,33 @@ void MainWindow::deleteSelectedtItems() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onCleanStateChanged(bool clean) {
|
||||||
|
qInfo() << "Slot onCleanStateChanged triggered: clean:" << clean;
|
||||||
|
setWindowModified(!clean);
|
||||||
|
if (!clean) {
|
||||||
|
ui->statusbar->clearMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::onShowUndoViewToggled(bool checked) {
|
||||||
|
// qInfo() << "Slot onShowUndoViewToggled toggled: checked:" << checked;
|
||||||
|
// m_undoView->setVisible(checked);
|
||||||
|
|
||||||
|
/// workaround until m_showUndoViewAction is checkable
|
||||||
|
qInfo() << "Slot onShowUndoViewToggled triggered, toggleing undo view...";
|
||||||
|
Q_UNUSED(checked);
|
||||||
|
if (m_modelUndoView->isVisible()) {
|
||||||
|
m_modelUndoView->setVisible(false);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
m_modelUndoView->setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::createActions() {
|
void MainWindow::createActions() {
|
||||||
// TODO add generic menu actions (file/new, edit/cut, ...)
|
// TODO add generic menu actions (file/new, edit/cut, ...)
|
||||||
createFileActions();
|
createFileActions();
|
||||||
|
createUndoActions();
|
||||||
createEditActions();
|
createEditActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,6 +293,44 @@ void MainWindow::createFileActions() {
|
|||||||
ui->menu_File->addAction(m_exitAct.get());
|
ui->menu_File->addAction(m_exitAct.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::createUndoActions() {
|
||||||
|
if (!m_core) {
|
||||||
|
qCritical() << "No core instance set, aborting...";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_modelUndoStack = m_core->getModelUndoStack();
|
||||||
|
|
||||||
|
connect(m_modelUndoStack, &QUndoStack::cleanChanged, this, &MainWindow::onCleanStateChanged);
|
||||||
|
|
||||||
|
m_undoAct.reset(m_modelUndoStack->createUndoAction(this, tr("&Undo")));
|
||||||
|
m_undoAct->setShortcuts(QKeySequence::Undo);
|
||||||
|
m_undoAct->setStatusTip(tr("Undo the last operation"));
|
||||||
|
ui->menu_Edit->addAction(m_undoAct.get());
|
||||||
|
|
||||||
|
m_redoAct.reset(m_modelUndoStack->createRedoAction(this, tr("&Redo")));
|
||||||
|
m_redoAct->setShortcuts(QKeySequence::Redo);
|
||||||
|
m_redoAct->setStatusTip(tr("Redo the last operation"));
|
||||||
|
ui->menu_Edit->addAction(m_redoAct.get());
|
||||||
|
|
||||||
|
m_modelUndoView = make_unique<QUndoView>(m_modelUndoStack);
|
||||||
|
m_modelUndoView->setWindowTitle(tr("Undo list"));
|
||||||
|
m_modelUndoView->setAttribute(Qt::WA_QuitOnClose, false);
|
||||||
|
m_modelUndoView->setMinimumSize(450, 600);
|
||||||
|
m_showModelUndoViewAct = make_unique<QAction>(tr("Show undo/redo window"), this);
|
||||||
|
m_showModelUndoViewAct->setStatusTip(tr("Opens a window displaying the items on the undo stack"));
|
||||||
|
|
||||||
|
// TODO showUndoViewAction should be checkable
|
||||||
|
// m_showUndoViewAction->setCheckable(true);
|
||||||
|
// connect(m_showUndoViewAction, &QAction::toggled, this, &MainWindow::onShowUndoViewToggled);
|
||||||
|
connect(m_showModelUndoViewAct.get(), &QAction::triggered, this,
|
||||||
|
&MainWindow::onShowUndoViewToggled);
|
||||||
|
|
||||||
|
// TODO ? add a keyboard short cut?
|
||||||
|
// m_showUndoViewAction->setShortcuts(QKeySequence::Copy);
|
||||||
|
|
||||||
|
ui->menu_View->addAction(m_showModelUndoViewAct.get());
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::createEditActions() {
|
void MainWindow::createEditActions() {
|
||||||
m_cutAct = make_unique<QAction>(tr("Cu&t"), this);
|
m_cutAct = make_unique<QAction>(tr("Cu&t"), this);
|
||||||
m_cutAct->setShortcuts(QKeySequence::Cut);
|
m_cutAct->setShortcuts(QKeySequence::Cut);
|
||||||
@ -271,14 +370,15 @@ void MainWindow::createEditActions() {
|
|||||||
m_openEditItemDialogAct = make_unique<QAction>(tr("&Edit item"), this);
|
m_openEditItemDialogAct = make_unique<QAction>(tr("&Edit item"), this);
|
||||||
m_openEditItemDialogAct->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_E));
|
m_openEditItemDialogAct->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_E));
|
||||||
m_openEditItemDialogAct->setStatusTip(tr("Opens a edit dialog for the current item"));
|
m_openEditItemDialogAct->setStatusTip(tr("Opens a edit dialog for the current item"));
|
||||||
// connect(m_openEditItemDialogAct, &QAction::triggered, this, &MainWindow::openEditDialog);
|
connect(m_openEditItemDialogAct.get(), &QAction::triggered, this,
|
||||||
m_openEditItemDialogAct->setEnabled(false);
|
&MainWindow::openEditItemDialog);
|
||||||
ui->menu_Edit->addAction(m_openEditItemDialogAct.get());
|
ui->menu_Edit->addAction(m_openEditItemDialogAct.get());
|
||||||
|
|
||||||
m_deleteItemAct = make_unique<QAction>(tr("&Delete item(s)"), this);
|
m_deleteItemAct = make_unique<QAction>(tr("&Delete item(s)"), this);
|
||||||
m_deleteItemAct->setShortcuts(QKeySequence::Delete);
|
m_deleteItemAct->setShortcuts(QKeySequence::Delete);
|
||||||
m_deleteItemAct->setStatusTip(tr("Delete currently selected item(s)"));
|
m_deleteItemAct->setStatusTip(tr("Delete currently selected item(s)"));
|
||||||
connect(m_deleteItemAct.get(), &QAction::triggered, this, &MainWindow::deleteSelectedtItems);
|
// connect(m_deleteItemAct.get(), &QAction::triggered, this, &MainWindow::deleteSelectedtItems);
|
||||||
|
connect(m_deleteItemAct.get(), &QAction::triggered, this, &MainWindow::deleteCurrentItem);
|
||||||
ui->menu_Edit->addAction(m_deleteItemAct.get());
|
ui->menu_Edit->addAction(m_deleteItemAct.get());
|
||||||
|
|
||||||
ui->menu_Edit->addSeparator();
|
ui->menu_Edit->addSeparator();
|
||||||
@ -302,8 +402,12 @@ void MainWindow::createHelpMenu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::createGuiDialogs() {
|
void MainWindow::createGuiDialogs() {
|
||||||
|
/// new item dialog
|
||||||
m_newItemDialog = make_unique<NewItemDialog>(this);
|
m_newItemDialog = make_unique<NewItemDialog>(this);
|
||||||
m_newItemDialog->createContent();
|
m_newItemDialog->createContent();
|
||||||
connect(m_newItemDialog.get(), &NewItemDialog::addItems, m_tableModel.get(),
|
connect(m_newItemDialog.get(), &NewItemDialog::addItems, m_tableModel.get(),
|
||||||
&TableModel::appendItems);
|
&TableModel::appendItems);
|
||||||
|
/// edit item dialog
|
||||||
|
m_editItemDialog = make_unique<EditItemDialog>(ui->tableView, this);
|
||||||
|
m_editItemDialog->createContent();
|
||||||
}
|
}
|
||||||
|
|||||||
21
mainwindow.h
21
mainwindow.h
@ -4,17 +4,20 @@
|
|||||||
#include <QItemSelection>
|
#include <QItemSelection>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
|
||||||
class NewItemDialog;
|
|
||||||
class TableModel;
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class QUndoStack;
|
||||||
|
|
||||||
|
class QUndoView;
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
}
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class GenericCore;
|
class GenericCore;
|
||||||
|
class TableModel;
|
||||||
|
class NewItemDialog;
|
||||||
|
class EditItemDialog;
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -34,6 +37,7 @@ class MainWindow : public QMainWindow {
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void showStatusMessage(const QString text);
|
void showStatusMessage(const QString text);
|
||||||
|
void onCurrentChanged(const QModelIndex& current, const QModelIndex& previous);
|
||||||
void onSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
|
void onSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
|
||||||
|
|
||||||
void onAboutClicked();
|
void onAboutClicked();
|
||||||
@ -43,14 +47,21 @@ class MainWindow : public QMainWindow {
|
|||||||
|
|
||||||
/// slots for menu actions
|
/// slots for menu actions
|
||||||
void openNewItemDialog();
|
void openNewItemDialog();
|
||||||
|
void openEditItemDialog();
|
||||||
|
void deleteCurrentItem();
|
||||||
void deleteSelectedtItems();
|
void deleteSelectedtItems();
|
||||||
|
|
||||||
|
void onCleanStateChanged(bool clean);
|
||||||
|
void onShowUndoViewToggled(bool checked);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainWindow* ui;
|
Ui::MainWindow* ui;
|
||||||
|
|
||||||
// GenericCore* m_core;
|
// GenericCore* m_core;
|
||||||
unique_ptr<GenericCore> m_core;
|
unique_ptr<GenericCore> m_core;
|
||||||
shared_ptr<TableModel> m_tableModel;
|
shared_ptr<TableModel> m_tableModel;
|
||||||
|
QUndoStack* m_modelUndoStack;
|
||||||
|
unique_ptr<QUndoView> m_modelUndoView;
|
||||||
|
|
||||||
/// File actions
|
/// File actions
|
||||||
unique_ptr<QAction> m_newFileAct;
|
unique_ptr<QAction> m_newFileAct;
|
||||||
@ -70,13 +81,17 @@ class MainWindow : public QMainWindow {
|
|||||||
unique_ptr<QAction> m_openEditItemDialogAct;
|
unique_ptr<QAction> m_openEditItemDialogAct;
|
||||||
unique_ptr<QAction> m_deleteItemAct;
|
unique_ptr<QAction> m_deleteItemAct;
|
||||||
unique_ptr<QAction> m_findItemAct;
|
unique_ptr<QAction> m_findItemAct;
|
||||||
|
/// View actions
|
||||||
|
unique_ptr<QAction> m_showModelUndoViewAct;
|
||||||
|
|
||||||
/// Dialogs
|
/// Dialogs
|
||||||
unique_ptr<NewItemDialog> m_newItemDialog;
|
unique_ptr<NewItemDialog> m_newItemDialog;
|
||||||
|
unique_ptr<EditItemDialog> m_editItemDialog;
|
||||||
|
|
||||||
/// Setup functions
|
/// Setup functions
|
||||||
void createActions();
|
void createActions();
|
||||||
void createFileActions();
|
void createFileActions();
|
||||||
|
void createUndoActions();
|
||||||
void createEditActions();
|
void createEditActions();
|
||||||
void createHelpMenu();
|
void createHelpMenu();
|
||||||
void createGuiDialogs();
|
void createGuiDialogs();
|
||||||
|
|||||||
142
views/itemdetailmapper.cpp
Normal file
142
views/itemdetailmapper.cpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#include "itemdetailmapper.h"
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
#include <QDataWidgetMapper>
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QTableView>
|
||||||
|
|
||||||
|
ItemDetailMapper::ItemDetailMapper(QWidget* parent)
|
||||||
|
: QWidget{parent} {
|
||||||
|
/// model mapping
|
||||||
|
m_mapper = std::make_unique<QDataWidgetMapper>(this);
|
||||||
|
m_mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
|
||||||
|
|
||||||
|
/// 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_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_amountLabel, 3, 0, 1, 1);
|
||||||
|
layout->addWidget(m_amountBox, 3, 1, 1, 1);
|
||||||
|
layout->addWidget(m_factorLabel, 4, 0, 1, 1);
|
||||||
|
layout->addWidget(m_factorBox, 4, 1, 1, 1);
|
||||||
|
|
||||||
|
layout->addWidget(m_previousButton, 5, 0, 1, 1);
|
||||||
|
layout->addWidget(m_nextButton, 5, 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_amountBox, 3);
|
||||||
|
m_mapper->addMapping(m_factorBox, 4);
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
setEnabled(false);
|
||||||
|
|
||||||
|
m_nameEdit->clear();
|
||||||
|
m_descriptionEdit->clear();
|
||||||
|
m_infoEdit->clear();
|
||||||
|
m_amountBox->clear();
|
||||||
|
m_factorBox->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
65
views/itemdetailmapper.h
Normal file
65
views/itemdetailmapper.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#ifndef ITEMDETAILMAPPER_H
|
||||||
|
#define ITEMDETAILMAPPER_H
|
||||||
|
|
||||||
|
#include <QDataWidgetMapper>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class QLabel;
|
||||||
|
class QLineEdit;
|
||||||
|
class QDoubleSpinBox;
|
||||||
|
class QSpinBox;
|
||||||
|
class QPushButton;
|
||||||
|
class QAbstractItemModel;
|
||||||
|
class QItemSelectionModel;
|
||||||
|
class QTableView;
|
||||||
|
|
||||||
|
class ItemDetailMapper : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ItemDetailMapper(QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
void setModelMappings(QTableView* tableView);
|
||||||
|
|
||||||
|
bool submit();
|
||||||
|
void revert();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onCurrentIndexChanged(const QModelIndex& current, const QModelIndex& previous);
|
||||||
|
void rowsInserted(const QModelIndex& parent, int start, int end);
|
||||||
|
void rowsRemoved(const QModelIndex& parent, int start, int end);
|
||||||
|
void toPrevious();
|
||||||
|
void toNext();
|
||||||
|
void updateButtons(int row);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// *** members ***
|
||||||
|
/// Model stuff
|
||||||
|
QTableView* m_tableView = nullptr;
|
||||||
|
QAbstractItemModel* m_model = nullptr;
|
||||||
|
QItemSelectionModel* m_selectionModel = nullptr;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
QLabel* m_amountLabel = nullptr;
|
||||||
|
QSpinBox* m_amountBox = nullptr;
|
||||||
|
|
||||||
|
QLabel* m_factorLabel = nullptr;
|
||||||
|
QDoubleSpinBox* m_factorBox = nullptr;
|
||||||
|
|
||||||
|
QPushButton* m_nextButton;
|
||||||
|
QPushButton* m_previousButton;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ITEMDETAILMAPPER_H
|
||||||
Reference in New Issue
Block a user