Compare commits
10 Commits
3146eceec2
...
f148ef9cba
| Author | SHA1 | Date | |
|---|---|---|---|
| f148ef9cba | |||
| bdc8075324 | |||
| e157d4399d | |||
| 572f0f266e | |||
| 40a0815501 | |||
| c6d6b18ab3 | |||
| 2fcd69df5f | |||
| 455c6ef3bd | |||
| 22adf36aa9 | |||
| 7edd6b9aa0 |
31
CHANGELOG.md
31
CHANGELOG.md
@ -1,32 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## 0.3.0 - 2026-02-04
|
||||
## 0.1.0 - 2026-02-05
|
||||
|
||||
### Added
|
||||
|
||||
- Basic JSON RESTful client (compatible with the GenericRestServer)
|
||||
- No editing of existing items on the server yet
|
||||
|
||||
### Fixed
|
||||
|
||||
- Save changes when closing the EditItemDialog
|
||||
|
||||
## 0.2.1 - 2026-01-15
|
||||
|
||||
### Added
|
||||
|
||||
- Displaying QR code of current item in edit item dialog
|
||||
|
||||
## 0.2 - 2026-01-14
|
||||
|
||||
### Added
|
||||
|
||||
- Displaying editable table model (sortable by column)
|
||||
- Modifying model data can be un-/redone
|
||||
- Data is stored in JSON file and automatically loaded on application start
|
||||
- Data can be imported/exported from/into CSV file
|
||||
- Model rows containing specific data can be selected via "Find item(s)" dialog
|
||||
|
||||
## 0.1 - 2025-11-01
|
||||
|
||||
A simple Qt application separated into an UI frontend and backend core. With installer (for Linux for now) and option to trigger updater from within the application.
|
||||
Initial release of BeetRound. Based on GenericQtClient v0.3.0 and adjusted the project name to the use case.
|
||||
|
||||
@ -8,8 +8,8 @@ enable_testing()
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_subdirectory(libs/GenericCore)
|
||||
set (CORE_LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libs/GenericCore)
|
||||
add_subdirectory(libs/BeetRoundCore)
|
||||
set (CORE_LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libs/BeetRoundCore)
|
||||
|
||||
### 3rd party libraries
|
||||
add_subdirectory(libs/3rdParty/Qt-QrCodeGenerator)
|
||||
@ -18,7 +18,7 @@ set (QR_LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libs/3rdParty/Qt-QrCodeGenerator)
|
||||
configure_file(ApplicationConfig.h.in ApplicationConfig.h)
|
||||
|
||||
#Frontend applications
|
||||
add_subdirectory(UIs/GenericWidgets)
|
||||
add_subdirectory(UIs/BeetRoundWidgets)
|
||||
|
||||
### Tests
|
||||
add_subdirectory(tests/GenericCoreTests)
|
||||
|
||||
20
README.md
20
README.md
@ -1,19 +1,9 @@
|
||||
# GenericQtClient
|
||||
# BeetRound
|
||||
|
||||
This is a Qt application which can be used as a starting point for new software projects.
|
||||
BeetRound is a software project to manage the yearly crop share auction (german: Bietrunde) of a Community-supported agriculture (CSA, german: Solidarische Landwirtschaft (SoLaWi)).
|
||||
|
||||
Common features most Qt software clients need will be already implemented and can be easily configured for the specific needs.
|
||||
This is the management application. The project also includes a web server where the participants can submit their biddings.
|
||||
|
||||
## Implemented features:
|
||||
- Separated UI frontend and backend core (in its own git submodules)
|
||||
- Using Qt model/view framework with QT undo framework
|
||||
- Saving/Loading JSON files
|
||||
- CSV import/export
|
||||
- installable and updateable via Qt updater framework
|
||||
- only linux for now
|
||||
- Qt 6 libraries must be installed on the machine to run
|
||||
Further information will follow…
|
||||
|
||||
## Coming features:
|
||||
- REST client
|
||||
- Extensive use of sorting and filtering models to display data in different ways
|
||||
- ...
|
||||
This project is currently tailored for one specific CSA and will be expanded to broader use after the coming crop share auction in february.
|
||||
|
||||
@ -34,6 +34,8 @@ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
dialogs/edititemdialog.h dialogs/edititemdialog.cpp
|
||||
dialogs/settingsdialog.h dialogs/settingsdialog.cpp
|
||||
views/itemdetailmapper.h views/itemdetailmapper.cpp
|
||||
widgets/comboboxdelegate.h widgets/comboboxdelegate.cpp
|
||||
widgets/spinboxdelegate.h widgets/spinboxdelegate.cpp
|
||||
)
|
||||
# Define target properties for Android with Qt 6 as:
|
||||
# set_property(TARGET ${TARGET_APP} APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
|
||||
@ -63,7 +65,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_link_libraries(${TARGET_APP} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
|
||||
|
||||
target_include_directories(${TARGET_APP} PRIVATE ${CORE_LIB_DIR}/)
|
||||
target_link_libraries(${TARGET_APP} PRIVATE GenericCore)
|
||||
target_link_libraries(${TARGET_APP} PRIVATE BeetRoundCore)
|
||||
target_include_directories(${TARGET_APP} PRIVATE ${QR_LIB_DIR}/src)
|
||||
target_link_libraries(${TARGET_APP} PRIVATE qrcode)
|
||||
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
149
UIs/BeetRoundWidgets/dialogs/newitemdialog.cpp
Normal file
149
UIs/BeetRoundWidgets/dialogs/newitemdialog.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
#include "newitemdialog.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QSpinBox>
|
||||
#include <QStringListModel>
|
||||
#include "formats/jsonparser.h"
|
||||
#include "model/metadata.h"
|
||||
|
||||
NewItemDialog::NewItemDialog(QWidget* parent)
|
||||
: AbstractDialog(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, parent) {}
|
||||
|
||||
void NewItemDialog::createContent() {
|
||||
if (m_contentContainer) {
|
||||
delete m_contentContainer;
|
||||
}
|
||||
|
||||
setWindowTitle(tr("New item..."));
|
||||
|
||||
m_contentContainer = new QWidget(this);
|
||||
|
||||
// REFACTOR use a data structure for input widgets which can be iterated through
|
||||
// using a factory which iterates through the roles from metadata.h
|
||||
// and create the input widgets based on the data type of this role
|
||||
m_numberLabel = new QLabel(GET_HEADER_FOR_COLUMN(0));
|
||||
m_numberBox = new QSpinBox();
|
||||
m_numberBox->setMaximum(1000);
|
||||
|
||||
m_lastNameLabel = new QLabel(GET_HEADER_FOR_COLUMN(1));
|
||||
m_lastNameEdit = new QLineEdit();
|
||||
m_lastNameLabel->setBuddy(m_lastNameEdit);
|
||||
|
||||
m_firstNameLabel = new QLabel(GET_HEADER_FOR_COLUMN(2));
|
||||
m_firstNameEdit = new QLineEdit();
|
||||
m_firstNameLabel->setBuddy(m_firstNameEdit);
|
||||
|
||||
m_shareTypeLabel = new QLabel(GET_HEADER_FOR_COLUMN(3));
|
||||
m_shareTypeBox = new QComboBox();
|
||||
m_shareTypeLabel->setBuddy(m_shareTypeBox);
|
||||
m_shareTypeModel = new QStringListModel(SHARE_TYPES, this);
|
||||
m_shareTypeBox->setModel(m_shareTypeModel);
|
||||
|
||||
m_amountLabel = new QLabel(GET_HEADER_FOR_COLUMN(4));
|
||||
m_amountSpinBox = new QDoubleSpinBox();
|
||||
m_amountLabel->setBuddy(m_amountSpinBox);
|
||||
m_amountSpinBox->setValue(1.0);
|
||||
|
||||
m_biddingTypeLabel = new QLabel(GET_HEADER_FOR_COLUMN(5));
|
||||
m_biddingTypeBox = new QComboBox();
|
||||
m_biddingTypeLabel->setBuddy(m_biddingTypeBox);
|
||||
m_biddingTypeModel = new QStringListModel(BIDDING_TYPES, this);
|
||||
m_biddingTypeBox->setModel(m_biddingTypeModel);
|
||||
|
||||
m_bidding1Label = new QLabel(GET_HEADER_FOR_COLUMN(6));
|
||||
m_bidding1SpinBox = new QSpinBox();
|
||||
m_bidding1SpinBox->setMaximum(500);
|
||||
m_bidding2Label = new QLabel(GET_HEADER_FOR_COLUMN(7));
|
||||
m_bidding2SpinBox = new QSpinBox();
|
||||
m_bidding2SpinBox->setMaximum(500);
|
||||
m_bidding3Label = new QLabel(GET_HEADER_FOR_COLUMN(8));
|
||||
m_bidding3SpinBox = new QSpinBox();
|
||||
m_bidding3SpinBox->setMaximum(500);
|
||||
|
||||
m_depotWish1Label = new QLabel(GET_HEADER_FOR_COLUMN(9));
|
||||
m_depotWish1Edit = new QLineEdit();
|
||||
m_depotWish1Label->setBuddy(m_depotWish1Edit);
|
||||
m_depotWish2Label = new QLabel(GET_HEADER_FOR_COLUMN(10));
|
||||
m_depotWish2Edit = new QLineEdit();
|
||||
m_depotWish2Label->setBuddy(m_depotWish2Edit);
|
||||
|
||||
m_mailLabel = new QLabel(GET_HEADER_FOR_COLUMN(11));
|
||||
m_mailEdit = new QLineEdit();
|
||||
m_mailEdit->setMinimumWidth(200);
|
||||
m_mailLabel->setBuddy(m_mailEdit);
|
||||
|
||||
/// layouting
|
||||
QGridLayout* layout = new QGridLayout();
|
||||
layout->addWidget(m_numberLabel, 0, 0, 1, 1);
|
||||
layout->addWidget(m_numberBox, 0, 1, 1, 1);
|
||||
layout->addWidget(m_lastNameLabel, 1, 0, 1, 1);
|
||||
layout->addWidget(m_lastNameEdit, 1, 1, 1, 1);
|
||||
layout->addWidget(m_firstNameLabel, 2, 0, 1, 1);
|
||||
layout->addWidget(m_firstNameEdit, 2, 1, 1, 1);
|
||||
layout->addWidget(m_shareTypeLabel, 3, 0, 1, 1);
|
||||
layout->addWidget(m_shareTypeBox, 3, 1, 1, 1);
|
||||
layout->addWidget(m_amountLabel, 4, 0, 1, 1);
|
||||
layout->addWidget(m_amountSpinBox, 4, 1, 1, 1);
|
||||
layout->addWidget(m_biddingTypeLabel, 5, 0, 1, 1);
|
||||
layout->addWidget(m_biddingTypeBox, 5, 1, 1, 1);
|
||||
layout->addWidget(m_bidding1Label, 6, 0, 1, 1);
|
||||
layout->addWidget(m_bidding1SpinBox, 6, 1, 1, 1);
|
||||
layout->addWidget(m_bidding2Label, 7, 0, 1, 1);
|
||||
layout->addWidget(m_bidding2SpinBox, 7, 1, 1, 1);
|
||||
layout->addWidget(m_bidding3Label, 8, 0, 1, 1);
|
||||
layout->addWidget(m_bidding3SpinBox, 8, 1, 1, 1);
|
||||
layout->addWidget(m_depotWish1Label, 9, 0, 1, 1);
|
||||
layout->addWidget(m_depotWish1Edit, 9, 1, 1, 1);
|
||||
layout->addWidget(m_depotWish2Label, 10, 0, 1, 1);
|
||||
layout->addWidget(m_depotWish2Edit, 10, 1, 1, 1);
|
||||
layout->addWidget(m_mailLabel, 11, 0, 1, 1);
|
||||
layout->addWidget(m_mailEdit, 11, 1, 1, 1);
|
||||
|
||||
m_contentContainer->setLayout(layout);
|
||||
|
||||
m_outerLayout->insertWidget(0, m_contentContainer);
|
||||
}
|
||||
|
||||
void NewItemDialog::accept() {
|
||||
ModelItemValues itemValues;
|
||||
// TODO (after refactoring data structure for input widgets) use iteration through the relevant
|
||||
// roles and their input widgets
|
||||
// itemValues.insert(LastNameRole, m_nameEdit->text());
|
||||
itemValues.insert(GET_ROLE_FOR_COLUMN(0), m_numberBox->value());
|
||||
itemValues.insert(GET_ROLE_FOR_COLUMN(1), m_lastNameEdit->text());
|
||||
itemValues.insert(GET_ROLE_FOR_COLUMN(2), m_firstNameEdit->text());
|
||||
itemValues.insert(GET_ROLE_FOR_COLUMN(3), m_shareTypeBox->currentText());
|
||||
itemValues.insert(GET_ROLE_FOR_COLUMN(4), m_amountSpinBox->value());
|
||||
itemValues.insert(GET_ROLE_FOR_COLUMN(5), m_biddingTypeBox->currentText());
|
||||
itemValues.insert(GET_ROLE_FOR_COLUMN(6), m_bidding1SpinBox->value());
|
||||
itemValues.insert(GET_ROLE_FOR_COLUMN(7), m_bidding2SpinBox->value());
|
||||
itemValues.insert(GET_ROLE_FOR_COLUMN(8), m_bidding3SpinBox->value());
|
||||
itemValues.insert(GET_ROLE_FOR_COLUMN(9), m_depotWish1Edit->text());
|
||||
itemValues.insert(GET_ROLE_FOR_COLUMN(10), m_depotWish2Edit->text());
|
||||
itemValues.insert(GET_ROLE_FOR_COLUMN(11), m_mailEdit->text());
|
||||
|
||||
const QByteArray jsonDoc = JsonParser::itemValuesListToJson({itemValues}, ITEMS_KEY_STRING);
|
||||
emit addItems(jsonDoc);
|
||||
|
||||
resetContent();
|
||||
AbstractDialog::accept();
|
||||
}
|
||||
|
||||
void NewItemDialog::resetContent() {
|
||||
m_numberBox->setValue(0);
|
||||
m_lastNameEdit->setText("");
|
||||
m_firstNameEdit->setText("");
|
||||
m_shareTypeBox->setCurrentIndex(0);
|
||||
m_amountSpinBox->setValue(1);
|
||||
m_biddingTypeBox->setCurrentIndex(0);
|
||||
m_bidding1SpinBox->setValue(0);
|
||||
m_bidding2SpinBox->setValue(0);
|
||||
m_bidding3SpinBox->setValue(0);
|
||||
m_depotWish1Edit->setText("");
|
||||
m_depotWish2Edit->setText("");
|
||||
m_mailEdit->setText("");
|
||||
}
|
||||
68
UIs/BeetRoundWidgets/dialogs/newitemdialog.h
Normal file
68
UIs/BeetRoundWidgets/dialogs/newitemdialog.h
Normal file
@ -0,0 +1,68 @@
|
||||
#ifndef NEWITEMDIALOG_H
|
||||
#define NEWITEMDIALOG_H
|
||||
|
||||
#include "abstractdialog.h"
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
class QStringListModel;
|
||||
class QDoubleSpinBox;
|
||||
class QLineEdit;
|
||||
class QSpinBox;
|
||||
class QLabel;
|
||||
|
||||
class NewItemDialog : public AbstractDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NewItemDialog(QWidget* parent = nullptr);
|
||||
|
||||
void createContent() override;
|
||||
|
||||
signals:
|
||||
void addItems(const QByteArray& jsonDoc);
|
||||
|
||||
public slots:
|
||||
void accept() override;
|
||||
// void reject() override;
|
||||
|
||||
private:
|
||||
QLabel* m_numberLabel;
|
||||
QSpinBox* m_numberBox;
|
||||
|
||||
QLabel* m_lastNameLabel;
|
||||
QLineEdit* m_lastNameEdit;
|
||||
|
||||
QLabel* m_firstNameLabel;
|
||||
QLineEdit* m_firstNameEdit;
|
||||
|
||||
QLabel* m_shareTypeLabel;
|
||||
QComboBox* m_shareTypeBox;
|
||||
QStringListModel* m_shareTypeModel = nullptr;
|
||||
|
||||
QLabel* m_amountLabel;
|
||||
QDoubleSpinBox* m_amountSpinBox;
|
||||
|
||||
QLabel* m_biddingTypeLabel;
|
||||
QComboBox* m_biddingTypeBox;
|
||||
QStringListModel* m_biddingTypeModel = nullptr;
|
||||
|
||||
QLabel* m_bidding1Label;
|
||||
QSpinBox* m_bidding1SpinBox;
|
||||
QLabel* m_bidding2Label;
|
||||
QSpinBox* m_bidding2SpinBox;
|
||||
QLabel* m_bidding3Label;
|
||||
QSpinBox* m_bidding3SpinBox;
|
||||
|
||||
QLabel* m_depotWish1Label;
|
||||
QLineEdit* m_depotWish1Edit;
|
||||
QLabel* m_depotWish2Label;
|
||||
QLineEdit* m_depotWish2Edit;
|
||||
|
||||
QLabel* m_mailLabel;
|
||||
QLineEdit* m_mailEdit;
|
||||
|
||||
void resetContent();
|
||||
};
|
||||
|
||||
#endif // NEWITEMDIALOG_H
|
||||
@ -15,7 +15,10 @@
|
||||
#include "dialogs/settingsdialog.h"
|
||||
#include "genericcore.h"
|
||||
#include "model/generalsortfiltermodel.h"
|
||||
#include "model/metadata.h"
|
||||
#include "model/tablemodel.h"
|
||||
#include "widgets/comboboxdelegate.h"
|
||||
#include "widgets/spinboxdelegate.h"
|
||||
|
||||
static QStandardPaths::StandardLocation standardLocation = QStandardPaths::HomeLocation;
|
||||
static QString updateTextClean = "Do you want to update the application now?";
|
||||
@ -46,11 +49,7 @@ MainWindow::MainWindow(QWidget* parent)
|
||||
restoreGeometry(settings.value("geometry").toByteArray());
|
||||
restoreState(settings.value("windowState").toByteArray());
|
||||
|
||||
// m_tableModel = m_core->getModel();
|
||||
// ui->tableView->setModel(m_tableModel.get());
|
||||
m_proxyModel = m_core->getSortFilterModel();
|
||||
ui->tableView->setModel((QAbstractItemModel*)m_proxyModel.get());
|
||||
ui->tableView->setSortingEnabled(true);
|
||||
setupModelViews();
|
||||
|
||||
createActions();
|
||||
createHelpMenu();
|
||||
@ -147,8 +146,11 @@ void MainWindow::onSelectionChanged(const QItemSelection& selected,
|
||||
void MainWindow::onAboutClicked() {
|
||||
const QString applicationName = APPLICATION_NAME;
|
||||
const QString titlePrefix = tr("About ");
|
||||
// TODO read the about text from a rich text / markdown somewhere else.
|
||||
const QString aboutText =
|
||||
tr(QString("<b>%1 v%2</b> is a template for Qt applications."
|
||||
tr(QString("<b>%1 v%2</b> is a software project to manage the yearly crop share "
|
||||
"auction (german: Bietrunde) of a Community-supported agriculture (CSA, german: "
|
||||
"Solidarische Landwirtschaft (SoLaWi))."
|
||||
"<br><br><a href=\"https://working-copy.org/\">Working-Copy_Collective website</a>"
|
||||
"<br><br><a href=\"mailto:support@working-copy.org\">Mail to support</a>"
|
||||
"<br><br>It uses the <a href=\"https://qt.io\">Qt Framework</a>.")
|
||||
@ -340,6 +342,29 @@ void MainWindow::execSettingsDialog() {
|
||||
delete settingsDialog;
|
||||
}
|
||||
|
||||
void MainWindow::setupModelViews() {
|
||||
// m_tableModel = m_core->getModel();
|
||||
// ui->tableView->setModel(m_tableModel.get());
|
||||
m_proxyModel = m_core->getSortFilterModel();
|
||||
|
||||
/// setting number delegates to combo boxes
|
||||
SpinboxDelegate* spinboxDelegate = new SpinboxDelegate(this);
|
||||
ui->tableView->setItemDelegateForColumn(0, spinboxDelegate);
|
||||
ui->tableView->setItemDelegateForColumn(4, spinboxDelegate);
|
||||
ui->tableView->setItemDelegateForColumn(6, spinboxDelegate);
|
||||
ui->tableView->setItemDelegateForColumn(7, spinboxDelegate);
|
||||
ui->tableView->setItemDelegateForColumn(8, spinboxDelegate);
|
||||
|
||||
/// setting type delegates to combo boxes
|
||||
ComboboxDelegate* shareTypeDelegate = new ComboboxDelegate(SHARE_TYPES, this);
|
||||
ComboboxDelegate* biddingTypeDelegate = new ComboboxDelegate(BIDDING_TYPES, this);
|
||||
ui->tableView->setItemDelegateForColumn(3, shareTypeDelegate);
|
||||
ui->tableView->setItemDelegateForColumn(5, biddingTypeDelegate);
|
||||
|
||||
ui->tableView->setModel((QAbstractItemModel*)m_proxyModel.get());
|
||||
ui->tableView->setSortingEnabled(true);
|
||||
}
|
||||
|
||||
void MainWindow::createActions() {
|
||||
// TODO add generic menu actions (file/new, edit/cut, ...)
|
||||
createFileActions();
|
||||
@ -7,8 +7,8 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QUndoStack;
|
||||
|
||||
class QUndoView;
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
@ -110,6 +110,7 @@ class MainWindow : public QMainWindow {
|
||||
unique_ptr<EditItemDialog> m_editItemDialog;
|
||||
|
||||
/// Setup functions
|
||||
void setupModelViews();
|
||||
void createActions();
|
||||
void createFileActions();
|
||||
void createUndoActions();
|
||||
@ -1,6 +1,7 @@
|
||||
#include "itemdetailmapper.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QComboBox>
|
||||
#include <QDataWidgetMapper>
|
||||
#include <QGridLayout>
|
||||
#include <QJsonArray>
|
||||
@ -9,6 +10,7 @@
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QSpinBox>
|
||||
#include <QStringListModel>
|
||||
#include <QTableView>
|
||||
#include "model/metadata.h"
|
||||
|
||||
@ -34,42 +36,84 @@ ItemDetailMapper::ItemDetailMapper(QWidget* parent)
|
||||
|
||||
/// 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_numberLabel = new QLabel(GET_HEADER_FOR_COLUMN(0));
|
||||
m_numberBox = new QSpinBox();
|
||||
m_numberBox->setMaximum(1000);
|
||||
|
||||
m_descriptionLabel = new QLabel("&Description");
|
||||
m_descriptionEdit = new QLineEdit();
|
||||
m_descriptionLabel->setBuddy(m_descriptionEdit);
|
||||
m_lastNameLabel = new QLabel(GET_HEADER_FOR_COLUMN(1));
|
||||
m_lastNameEdit = new QLineEdit();
|
||||
m_lastNameLabel->setBuddy(m_lastNameEdit);
|
||||
|
||||
m_infoLabel = new QLabel("&Info");
|
||||
m_infoEdit = new QLineEdit();
|
||||
m_infoLabel->setBuddy(m_infoEdit);
|
||||
m_firstNameLabel = new QLabel(GET_HEADER_FOR_COLUMN(2));
|
||||
m_firstNameEdit = new QLineEdit();
|
||||
m_firstNameLabel->setBuddy(m_firstNameEdit);
|
||||
|
||||
m_amountLabel = new QLabel("&Amount");
|
||||
m_amountBox = new QSpinBox();
|
||||
m_amountBox->setMaximum(1000);
|
||||
m_amountLabel->setBuddy(m_amountBox);
|
||||
m_shareTypeLabel = new QLabel(GET_HEADER_FOR_COLUMN(3));
|
||||
m_shareTypeBox = new QComboBox();
|
||||
m_shareTypeLabel->setBuddy(m_shareTypeBox);
|
||||
m_shareTypeModel = new QStringListModel(SHARE_TYPES, this);
|
||||
m_shareTypeBox->setModel(m_shareTypeModel);
|
||||
|
||||
m_factorLabel = new QLabel("&Factor");
|
||||
m_factorBox = new QDoubleSpinBox();
|
||||
m_factorBox->setMaximum(1000);
|
||||
m_factorLabel->setBuddy(m_factorBox);
|
||||
m_amountLabel = new QLabel(GET_HEADER_FOR_COLUMN(4));
|
||||
m_amountSpinBox = new QDoubleSpinBox();
|
||||
m_amountLabel->setBuddy(m_amountSpinBox);
|
||||
|
||||
m_biddingTypeLabel = new QLabel(GET_HEADER_FOR_COLUMN(5));
|
||||
m_biddingTypeBox = new QComboBox();
|
||||
m_biddingTypeLabel->setBuddy(m_biddingTypeBox);
|
||||
m_biddingTypeModel = new QStringListModel(BIDDING_TYPES, this);
|
||||
m_biddingTypeBox->setModel(m_biddingTypeModel);
|
||||
|
||||
m_bidding1Label = new QLabel(GET_HEADER_FOR_COLUMN(6));
|
||||
m_bidding1SpinBox = new QSpinBox();
|
||||
m_bidding1SpinBox->setMaximum(500);
|
||||
m_bidding2Label = new QLabel(GET_HEADER_FOR_COLUMN(7));
|
||||
m_bidding2SpinBox = new QSpinBox();
|
||||
m_bidding2SpinBox->setMaximum(500);
|
||||
m_bidding3Label = new QLabel(GET_HEADER_FOR_COLUMN(8));
|
||||
m_bidding3SpinBox = new QSpinBox();
|
||||
m_bidding3SpinBox->setMaximum(500);
|
||||
|
||||
m_depotWish1Label = new QLabel(GET_HEADER_FOR_COLUMN(9));
|
||||
m_depotWish1Edit = new QLineEdit();
|
||||
m_depotWish1Label->setBuddy(m_depotWish1Edit);
|
||||
m_depotWish2Label = new QLabel(GET_HEADER_FOR_COLUMN(10));
|
||||
m_depotWish2Edit = new QLineEdit();
|
||||
m_depotWish2Label->setBuddy(m_depotWish2Edit);
|
||||
|
||||
m_mailLabel = new QLabel(GET_HEADER_FOR_COLUMN(11));
|
||||
m_mailEdit = new QLineEdit();
|
||||
m_mailEdit->setMinimumWidth(200);
|
||||
m_mailLabel->setBuddy(m_mailEdit);
|
||||
|
||||
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_numberLabel, 0, 0, 1, 1);
|
||||
layout->addWidget(m_numberBox, 0, 1, 1, 1);
|
||||
layout->addWidget(m_lastNameLabel, 1, 0, 1, 1);
|
||||
layout->addWidget(m_lastNameEdit, 1, 1, 1, 1);
|
||||
layout->addWidget(m_firstNameLabel, 2, 0, 1, 1);
|
||||
layout->addWidget(m_firstNameEdit, 2, 1, 1, 1);
|
||||
layout->addWidget(m_shareTypeLabel, 3, 0, 1, 1);
|
||||
layout->addWidget(m_shareTypeBox, 3, 1, 1, 1);
|
||||
layout->addWidget(m_amountLabel, 4, 0, 1, 1);
|
||||
layout->addWidget(m_amountSpinBox, 4, 1, 1, 1);
|
||||
layout->addWidget(m_biddingTypeLabel, 5, 0, 1, 1);
|
||||
layout->addWidget(m_biddingTypeBox, 5, 1, 1, 1);
|
||||
layout->addWidget(m_bidding1Label, 6, 0, 1, 1);
|
||||
layout->addWidget(m_bidding1SpinBox, 6, 1, 1, 1);
|
||||
layout->addWidget(m_bidding2Label, 7, 0, 1, 1);
|
||||
layout->addWidget(m_bidding2SpinBox, 7, 1, 1, 1);
|
||||
layout->addWidget(m_bidding3Label, 8, 0, 1, 1);
|
||||
layout->addWidget(m_bidding3SpinBox, 8, 1, 1, 1);
|
||||
layout->addWidget(m_depotWish1Label, 9, 0, 1, 1);
|
||||
layout->addWidget(m_depotWish1Edit, 9, 1, 1, 1);
|
||||
layout->addWidget(m_depotWish2Label, 10, 0, 1, 1);
|
||||
layout->addWidget(m_depotWish2Edit, 10, 1, 1, 1);
|
||||
layout->addWidget(m_mailLabel, 11, 0, 1, 1);
|
||||
layout->addWidget(m_mailEdit, 11, 1, 1, 1);
|
||||
|
||||
layout->addWidget(m_previousButton, 5, 0, 1, 1);
|
||||
layout->addWidget(m_nextButton, 5, 1, 1, 1);
|
||||
layout->addWidget(m_previousButton, 12, 0, 1, 1);
|
||||
layout->addWidget(m_nextButton, 12, 1, 1, 1);
|
||||
|
||||
setLayout(layout);
|
||||
}
|
||||
@ -81,11 +125,18 @@ void ItemDetailMapper::setModelMappings(QTableView* tableView) {
|
||||
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->addMapping(m_numberBox, 0);
|
||||
m_mapper->addMapping(m_lastNameEdit, 1);
|
||||
m_mapper->addMapping(m_firstNameEdit, 2);
|
||||
m_mapper->addMapping(m_shareTypeBox, 3, "currentText");
|
||||
m_mapper->addMapping(m_amountSpinBox, 4);
|
||||
m_mapper->addMapping(m_biddingTypeBox, 5, "currentText");
|
||||
m_mapper->addMapping(m_bidding1SpinBox, 6);
|
||||
m_mapper->addMapping(m_bidding2SpinBox, 7);
|
||||
m_mapper->addMapping(m_bidding3SpinBox, 8);
|
||||
m_mapper->addMapping(m_depotWish1Edit, 9);
|
||||
m_mapper->addMapping(m_depotWish2Edit, 10);
|
||||
m_mapper->addMapping(m_mailEdit, 11);
|
||||
|
||||
m_mapper->setCurrentIndex(m_selectionModel->currentIndex().row());
|
||||
|
||||
@ -119,11 +170,11 @@ 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();
|
||||
// m_nameEdit->clear();
|
||||
// m_descriptionEdit->clear();
|
||||
// m_infoEdit->clear();
|
||||
// m_amountBox->clear();
|
||||
// m_factorBox->clear();
|
||||
}
|
||||
|
||||
updateButtons(m_mapper->currentIndex());
|
||||
@ -6,11 +6,13 @@
|
||||
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QComboBox;
|
||||
class QDoubleSpinBox;
|
||||
class QSpinBox;
|
||||
class QPushButton;
|
||||
class QAbstractItemModel;
|
||||
class QItemSelectionModel;
|
||||
class QStringListModel;
|
||||
class QTableView;
|
||||
|
||||
class ItemDetailMapper : public QWidget {
|
||||
@ -45,21 +47,42 @@ class ItemDetailMapper : public QWidget {
|
||||
std::unique_ptr<QDataWidgetMapper> m_mapper;
|
||||
|
||||
/// GUI elements
|
||||
QLabel* m_nameLabel = nullptr;
|
||||
QLineEdit* m_nameEdit = nullptr;
|
||||
QLabel* m_numberLabel;
|
||||
QSpinBox* m_numberBox;
|
||||
|
||||
QLabel* m_descriptionLabel = nullptr;
|
||||
QLineEdit* m_descriptionEdit = nullptr;
|
||||
QLabel* m_lastNameLabel;
|
||||
QLineEdit* m_lastNameEdit;
|
||||
|
||||
QLabel* m_infoLabel = nullptr;
|
||||
QLineEdit* m_infoEdit = nullptr;
|
||||
QLabel* m_firstNameLabel;
|
||||
QLineEdit* m_firstNameEdit;
|
||||
|
||||
QLabel* m_amountLabel = nullptr;
|
||||
QSpinBox* m_amountBox = nullptr;
|
||||
QLabel* m_shareTypeLabel;
|
||||
QComboBox* m_shareTypeBox;
|
||||
QStringListModel* m_shareTypeModel = nullptr;
|
||||
|
||||
QLabel* m_factorLabel = nullptr;
|
||||
QDoubleSpinBox* m_factorBox = nullptr;
|
||||
QLabel* m_amountLabel;
|
||||
QDoubleSpinBox* m_amountSpinBox;
|
||||
|
||||
QLabel* m_biddingTypeLabel;
|
||||
QComboBox* m_biddingTypeBox;
|
||||
QStringListModel* m_biddingTypeModel = nullptr;
|
||||
|
||||
QLabel* m_bidding1Label;
|
||||
QSpinBox* m_bidding1SpinBox;
|
||||
QLabel* m_bidding2Label;
|
||||
QSpinBox* m_bidding2SpinBox;
|
||||
QLabel* m_bidding3Label;
|
||||
QSpinBox* m_bidding3SpinBox;
|
||||
|
||||
QLabel* m_depotWish1Label;
|
||||
QLineEdit* m_depotWish1Edit;
|
||||
QLabel* m_depotWish2Label;
|
||||
QLineEdit* m_depotWish2Edit;
|
||||
|
||||
QLabel* m_mailLabel;
|
||||
QLineEdit* m_mailEdit;
|
||||
|
||||
/// Model mapper stuff
|
||||
QPushButton* m_nextButton;
|
||||
QPushButton* m_previousButton;
|
||||
};
|
||||
66
UIs/BeetRoundWidgets/widgets/comboboxdelegate.cpp
Normal file
66
UIs/BeetRoundWidgets/widgets/comboboxdelegate.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include "comboboxdelegate.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QStringListModel>
|
||||
#include "model/metadata.h"
|
||||
|
||||
ComboboxDelegate::ComboboxDelegate(const QStringList items, QObject* parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
, m_types(new QStringListModel(items)) {}
|
||||
|
||||
void ComboboxDelegate::paint(QPainter* painter,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const {
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
|
||||
QSize ComboboxDelegate::sizeHint(const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const {
|
||||
return QStyledItemDelegate::sizeHint(option, index);
|
||||
}
|
||||
|
||||
QWidget* ComboboxDelegate::createEditor(QWidget* parent,
|
||||
const QStyleOptionViewItem& /*option*/,
|
||||
const QModelIndex& /*index*/) const {
|
||||
QComboBox* editor = new QComboBox(parent);
|
||||
editor->setModel(m_types);
|
||||
return editor;
|
||||
// return QStyledItemDelegate::createEditor(parent, option, index);
|
||||
}
|
||||
|
||||
void ComboboxDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const {
|
||||
/// Get the value via index of the Model
|
||||
const QAbstractItemModel* localModel = index.model();
|
||||
const QString headerText = localModel->headerData(index.column(), Qt::Horizontal).toString();
|
||||
|
||||
const UserRoles role = GET_ROLE_FOR_COLUMN(index.column());
|
||||
const bool isShareType = SHARE_TYPE_ROLES.contains(role);
|
||||
const bool isBiddingType = BIDDING_TYPE_ROLES.contains(role);
|
||||
/// Put the value into the SpinBox
|
||||
if (isShareType) {
|
||||
const QString valueString = index.model()->data(index, ShareTypeRole).toString();
|
||||
int value = SHARE_TYPES.indexOf(valueString);
|
||||
|
||||
QComboBox* combobox = static_cast<QComboBox*>(editor);
|
||||
combobox->setCurrentIndex(value);
|
||||
// QStyledItemDelegate::setEditorData(editor, index);
|
||||
} else if (isBiddingType) {
|
||||
const QString valueString = index.model()->data(index, BiddingTypeRole).toString();
|
||||
int value = BIDDING_TYPES.indexOf(valueString);
|
||||
|
||||
// Put the value into the SpinBox
|
||||
QComboBox* combobox = static_cast<QComboBox*>(editor);
|
||||
combobox->setCurrentIndex(value);
|
||||
// QStyledItemDelegate::setEditorData(editor, index);
|
||||
} else {
|
||||
qCritical() << "Could not find the correct type role for index:" << index << "!!!";
|
||||
QComboBox* combobox = static_cast<QComboBox*>(editor);
|
||||
combobox->setCurrentIndex(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void ComboboxDelegate::setModelData(QWidget* editor,
|
||||
QAbstractItemModel* model,
|
||||
const QModelIndex& index) const {
|
||||
QStyledItemDelegate::setModelData(editor, model, index);
|
||||
}
|
||||
30
UIs/BeetRoundWidgets/widgets/comboboxdelegate.h
Normal file
30
UIs/BeetRoundWidgets/widgets/comboboxdelegate.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef COMBOBOXDELEGATE_H
|
||||
#define COMBOBOXDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class QStringListModel;
|
||||
class ComboboxDelegate : public QStyledItemDelegate {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ComboboxDelegate(const QStringList items, QObject* parent = nullptr);
|
||||
|
||||
/// QAbstractItemDelegate interface
|
||||
public:
|
||||
void paint(QPainter* painter,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
QWidget* createEditor(QWidget* parent,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex&) const override;
|
||||
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
|
||||
void setModelData(QWidget* editor,
|
||||
QAbstractItemModel* model,
|
||||
const QModelIndex& index) const override;
|
||||
|
||||
private:
|
||||
QStringListModel* m_types = nullptr;
|
||||
};
|
||||
|
||||
#endif // COMBOBOXDELEGATE_H
|
||||
69
UIs/BeetRoundWidgets/widgets/spinboxdelegate.cpp
Normal file
69
UIs/BeetRoundWidgets/widgets/spinboxdelegate.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#include "spinboxdelegate.h"
|
||||
|
||||
#include <QSpinBox>
|
||||
|
||||
#include "model/metadata.h"
|
||||
|
||||
SpinboxDelegate::SpinboxDelegate(QObject* parent)
|
||||
: QStyledItemDelegate(parent) {}
|
||||
|
||||
void SpinboxDelegate::paint(QPainter* painter,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const {
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
|
||||
QSize SpinboxDelegate::sizeHint(const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const {
|
||||
return QStyledItemDelegate::sizeHint(option, index);
|
||||
}
|
||||
|
||||
QWidget* SpinboxDelegate::createEditor(QWidget* parent,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const {
|
||||
const QAbstractItemModel* localModel = index.model();
|
||||
QString headerText = localModel->headerData(index.column(), Qt::Horizontal).toString();
|
||||
|
||||
const UserRoles role = GET_ROLE_FOR_COLUMN(index.column());
|
||||
const bool isInt = INT_ROLES.contains(role);
|
||||
if (isInt) {
|
||||
QSpinBox* editor = new QSpinBox(parent);
|
||||
editor->setMinimum(0);
|
||||
editor->setMaximum(23000);
|
||||
return editor;
|
||||
} else {
|
||||
QDoubleSpinBox* editor = new QDoubleSpinBox(parent);
|
||||
editor->setMinimum(0);
|
||||
editor->setMaximum(23000);
|
||||
return editor;
|
||||
}
|
||||
// return QStyledItemDelegate::createEditor(parent, option, index);
|
||||
}
|
||||
|
||||
void SpinboxDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const {
|
||||
// Get the value via index of the Model
|
||||
const QAbstractItemModel* localModel = index.model();
|
||||
QString headerText = localModel->headerData(index.column(), Qt::Horizontal).toString();
|
||||
|
||||
const UserRoles role = GET_ROLE_FOR_COLUMN(index.column());
|
||||
const bool isInt = INT_ROLES.contains(role);
|
||||
if (isInt) {
|
||||
int value = index.model()->data(index, Qt::EditRole).toInt();
|
||||
// Put the value into the SpinBox
|
||||
QSpinBox* spinbox = static_cast<QSpinBox*>(editor);
|
||||
spinbox->setValue(value);
|
||||
} else {
|
||||
// Put the value into the SpinBox
|
||||
qreal value = index.model()->data(index, Qt::EditRole).toReal();
|
||||
QDoubleSpinBox* spinbox = static_cast<QDoubleSpinBox*>(editor);
|
||||
spinbox->setValue(value);
|
||||
}
|
||||
|
||||
// QStyledItemDelegate::setEditorData(editor, index);
|
||||
}
|
||||
|
||||
void SpinboxDelegate::setModelData(QWidget* editor,
|
||||
QAbstractItemModel* model,
|
||||
const QModelIndex& index) const {
|
||||
QStyledItemDelegate::setModelData(editor, model, index);
|
||||
}
|
||||
26
UIs/BeetRoundWidgets/widgets/spinboxdelegate.h
Normal file
26
UIs/BeetRoundWidgets/widgets/spinboxdelegate.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef SPINBOXDELEGATE_H
|
||||
#define SPINBOXDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class SpinboxDelegate : public QStyledItemDelegate {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SpinboxDelegate(QObject* parent = nullptr);
|
||||
|
||||
/// QAbstractItemDelegate interface
|
||||
public:
|
||||
void paint(QPainter* painter,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
QWidget* createEditor(QWidget* parent,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const override;
|
||||
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
|
||||
void setModelData(QWidget* editor,
|
||||
QAbstractItemModel* model,
|
||||
const QModelIndex& index) const override;
|
||||
};
|
||||
|
||||
#endif // SPINBOXDELEGATE_H
|
||||
@ -1,81 +0,0 @@
|
||||
#include "newitemdialog.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QSpinBox>
|
||||
#include "formats/jsonparser.h"
|
||||
#include "model/metadata.h"
|
||||
|
||||
NewItemDialog::NewItemDialog(QWidget* parent)
|
||||
: AbstractDialog(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, parent) {}
|
||||
|
||||
void NewItemDialog::createContent() {
|
||||
if (m_contentContainer) {
|
||||
delete m_contentContainer;
|
||||
}
|
||||
|
||||
setWindowTitle(tr("New item..."));
|
||||
|
||||
m_contentContainer = new QWidget(this);
|
||||
|
||||
// REFACTOR use a data structure for input widgets which can be iterated through
|
||||
// using a factory which iterates through the roles from metadata.h
|
||||
// and create the input widgets based on the data type of this role
|
||||
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);
|
||||
|
||||
m_contentContainer->setLayout(layout);
|
||||
|
||||
m_outerLayout->insertWidget(0, m_contentContainer);
|
||||
}
|
||||
|
||||
void NewItemDialog::accept() {
|
||||
ModelItemValues itemValues;
|
||||
// TODO (after refactoring data structure for input widgets) use iteration through the relevant
|
||||
// roles and their input widgets
|
||||
itemValues.insert(NameRole, m_nameEdit->text());
|
||||
itemValues.insert(DescriptionRole, m_descriptionEdit->text());
|
||||
itemValues.insert(InfoRole, m_infoEdit->text());
|
||||
itemValues.insert(AmountRole, m_amountBox->value());
|
||||
itemValues.insert(FactorRole, m_factorBox->value());
|
||||
|
||||
const QByteArray jsonDoc = JsonParser::itemValuesListToJson({itemValues}, ITEMS_KEY_STRING);
|
||||
emit addItems(jsonDoc);
|
||||
|
||||
// resetContent();
|
||||
AbstractDialog::accept();
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
#ifndef NEWITEMDIALOG_H
|
||||
#define NEWITEMDIALOG_H
|
||||
|
||||
#include "abstractdialog.h"
|
||||
|
||||
class QDoubleSpinBox;
|
||||
class QLineEdit;
|
||||
class QSpinBox;
|
||||
class QLabel;
|
||||
|
||||
class NewItemDialog : public AbstractDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NewItemDialog(QWidget* parent = nullptr);
|
||||
|
||||
void createContent() override;
|
||||
|
||||
signals:
|
||||
void addItems(const QByteArray& jsonDoc);
|
||||
|
||||
public slots:
|
||||
void accept() override;
|
||||
// void reject() override;
|
||||
|
||||
private:
|
||||
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 // NEWITEMDIALOG_H
|
||||
@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(TARGET_APP "GenericCore")
|
||||
set(TARGET_APP "BeetRoundCore")
|
||||
project(${TARGET_APP} VERSION 0.1.0 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
@ -43,8 +43,8 @@ add_library(${TARGET_APP} STATIC
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
target_link_libraries(${TARGET_APP} PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Gui)
|
||||
target_link_libraries(GenericCore PRIVATE Qt${QT_VERSION_MAJOR}::Test)
|
||||
target_link_libraries(GenericCore PRIVATE Qt${QT_VERSION_MAJOR}::Network)
|
||||
target_link_libraries(${TARGET_APP} PRIVATE Qt${QT_VERSION_MAJOR}::Test)
|
||||
target_link_libraries(${TARGET_APP} PRIVATE Qt${QT_VERSION_MAJOR}::Network)
|
||||
|
||||
target_compile_definitions(${TARGET_APP} PRIVATE ${TARGET_APP}_LIBRARY)
|
||||
|
||||
@ -52,6 +52,11 @@ bool CsvParser::isCsvCompatible(const rapidcsv::Document& doc) {
|
||||
qInfo() << "Checking CSV document for compatiblity...";
|
||||
const std::vector<std::string> columnNames = doc.GetColumnNames();
|
||||
for (const QString& headerName : GET_HEADER_NAMES()) {
|
||||
if (OPTIONAL_CSV_HEADERS.contains(headerName)) {
|
||||
/// no need to have a column for the optional values
|
||||
continue;
|
||||
}
|
||||
/// these column must be found in CSV document
|
||||
bool isHeaderNameFound = false;
|
||||
if (std::find(columnNames.begin(), columnNames.end(), headerName) != columnNames.end()) {
|
||||
qDebug() << QString("Header found in column names: %1").arg(headerName);
|
||||
@ -86,14 +91,13 @@ QHash<QString, std::vector<std::string>> CsvParser::extractColumnValues(
|
||||
const rapidcsv::Document& doc) {
|
||||
QHash<QString, std::vector<std::string>> columnValueMap;
|
||||
for (const QString& columnName : headerNames) {
|
||||
// TODO add support for optional columns
|
||||
// if (optionalCsvHeaderNames.contains(columnName)) {
|
||||
// const std::vector<std::string> columnNames = doc.GetColumnNames();
|
||||
// int columnIdx = doc.GetColumnIdx(columnName.toStdString());
|
||||
// if (columnIdx == -1) {
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
if (OPTIONAL_CSV_HEADERS.contains(columnName)) {
|
||||
const std::vector<std::string> columnNames = doc.GetColumnNames();
|
||||
int columnIdx = doc.GetColumnIdx(columnName.toStdString());
|
||||
if (columnIdx == -1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const std::vector<std::string> columnValues =
|
||||
doc.GetColumn<std::string>(columnName.toStdString());
|
||||
columnValueMap.insert(columnName, columnValues);
|
||||
@ -86,14 +86,6 @@ QJsonArray JsonParser::extractItemArray(const QJsonDocument& doc, const QString&
|
||||
ModelItemValues JsonParser::jsonObjectToItemValues(const QJsonObject& itemJsonObject) {
|
||||
ModelItemValues values;
|
||||
|
||||
const UserRoles idRole = IdRole;
|
||||
const QString idRoleName = ROLE_NAMES.value(idRole);
|
||||
// QVariant idValue = data(idRole);
|
||||
if (itemJsonObject.contains(idRoleName)) {
|
||||
std::pair<int, QVariant> keyValuePair = getKeyValuePair(itemJsonObject, idRole);
|
||||
values.insert(keyValuePair.first, keyValuePair.second);
|
||||
}
|
||||
|
||||
QListIterator<UserRoles> i(USER_FACING_ROLES);
|
||||
while (i.hasNext()) {
|
||||
const UserRoles role = i.next();
|
||||
@ -26,11 +26,6 @@ EditItemCommand::EditItemCommand(TableModel* model,
|
||||
.arg(roleName)
|
||||
.arg(index.data(DEFAULT_ROLE).toString())
|
||||
.arg(value.toString());
|
||||
} else if (role == IdRole) {
|
||||
commandText = QString("Setting '%1' of item '%2' to '%3'")
|
||||
.arg(roleName)
|
||||
.arg(index.data(DEFAULT_ROLE).toString())
|
||||
.arg(value.toString());
|
||||
} else {
|
||||
qWarning() << "Role didn't match! Using a generic command text...";
|
||||
commandText = QString("Edit item '%1'").arg(index.data(DEFAULT_ROLE).toString());
|
||||
@ -24,7 +24,7 @@ QItemSelection GeneralSortFilterModel::findItems(const QString& text) const {
|
||||
}
|
||||
|
||||
QString GeneralSortFilterModel::getUuid(const QModelIndex& itemIndex) const {
|
||||
return data(itemIndex, IdRole).toString();
|
||||
return data(itemIndex, OnlineIdRole).toString();
|
||||
}
|
||||
|
||||
QByteArray GeneralSortFilterModel::jsonDataForServer(const QModelIndex& proxyIndex) {
|
||||
151
libs/BeetRoundCore/model/metadata.h
Normal file
151
libs/BeetRoundCore/model/metadata.h
Normal file
@ -0,0 +1,151 @@
|
||||
#ifndef METADATA_H
|
||||
#define METADATA_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
// TODO add namespace
|
||||
|
||||
/// model data
|
||||
enum UserRoles {
|
||||
LastNameRole = Qt::UserRole + 1,
|
||||
FirstNameRole,
|
||||
MembershipNumberRole,
|
||||
Bidding1Role,
|
||||
Bidding2Role,
|
||||
Bidding3Role,
|
||||
DepotWish1Role,
|
||||
DepotWish2Role,
|
||||
ShareAmountRole,
|
||||
MailRole,
|
||||
ShareTypeRole,
|
||||
BiddingTypeRole,
|
||||
OnlineIdRole,
|
||||
AccessCodeRole,
|
||||
// read-only (calculated)
|
||||
FullNameRole,
|
||||
FactoredBiddingRole,
|
||||
ToStringRole,
|
||||
JsonObjectRole
|
||||
};
|
||||
|
||||
static UserRoles DEFAULT_ROLE = FullNameRole;
|
||||
// TODO ?rename USER_FACING_ROLES -> MAIN_ROLES ?
|
||||
static QList<UserRoles> USER_FACING_ROLES = {
|
||||
LastNameRole, FirstNameRole, MembershipNumberRole, Bidding1Role, Bidding2Role,
|
||||
Bidding3Role, DepotWish1Role, DepotWish2Role, ShareAmountRole, MailRole,
|
||||
ShareTypeRole, BiddingTypeRole, OnlineIdRole, AccessCodeRole};
|
||||
static QHash<int, QByteArray> ROLE_NAMES = {{MembershipNumberRole, "Mitglieds-nr."},
|
||||
{LastNameRole, "Name"},
|
||||
{FirstNameRole, "Vorname"},
|
||||
{Bidding1Role, "Gebot 1"},
|
||||
{Bidding2Role, "Gebot 2"},
|
||||
{Bidding3Role, "Gebot 3"},
|
||||
{DepotWish1Role, "Wunsch 1"},
|
||||
{DepotWish2Role, "Wunsch 2"},
|
||||
{ShareAmountRole, "Anzahl"},
|
||||
{MailRole, "Mail"},
|
||||
{ShareTypeRole, "Art"},
|
||||
{BiddingTypeRole, "Bietart"},
|
||||
{OnlineIdRole, "Online ID"},
|
||||
{AccessCodeRole, "Access Code"},
|
||||
{FactoredBiddingRole, "factoredBidding"}};
|
||||
|
||||
static const QList<QString> SHARE_TYPES = {"bezahlt", "teils/teils", "erarbeitet", ""};
|
||||
static const QList<QString> BIDDING_TYPES = {"paper", "digital", "online", "offline", ""};
|
||||
|
||||
static QList<UserRoles> STRING_ROLES = {LastNameRole, FirstNameRole, DepotWish1Role,
|
||||
DepotWish2Role, MailRole, ShareTypeRole,
|
||||
BiddingTypeRole, OnlineIdRole, AccessCodeRole};
|
||||
static QList<UserRoles> INT_ROLES = {
|
||||
MembershipNumberRole,
|
||||
Bidding1Role,
|
||||
Bidding2Role,
|
||||
Bidding3Role,
|
||||
};
|
||||
static QList<UserRoles> DOUBLE_ROLES = {
|
||||
ShareAmountRole,
|
||||
};
|
||||
|
||||
static const QList<UserRoles> TYPE_ROLES = {ShareTypeRole, BiddingTypeRole};
|
||||
static const QList<UserRoles> SHARE_TYPE_ROLES = {ShareTypeRole};
|
||||
static const QList<UserRoles> BIDDING_TYPE_ROLES = {BiddingTypeRole};
|
||||
|
||||
static const QStringList OPTIONAL_CSV_HEADERS = {"Bietart", "Online ID", "Access Code"};
|
||||
|
||||
/// JSON keys
|
||||
static const QString ITEMS_KEY_STRING = "items";
|
||||
static const QString ITEM_KEY_STRING = "item";
|
||||
|
||||
/// file naming
|
||||
static const QString ITEMS_FILE_NAME = ITEMS_KEY_STRING + ".json";
|
||||
|
||||
/// functions
|
||||
static UserRoles GET_ROLE_FOR_COLUMN(const int column) {
|
||||
switch (column) {
|
||||
case 0:
|
||||
return MembershipNumberRole;
|
||||
break;
|
||||
case 1:
|
||||
return LastNameRole;
|
||||
break;
|
||||
case 2:
|
||||
return FirstNameRole;
|
||||
break;
|
||||
case 3:
|
||||
return ShareTypeRole;
|
||||
break;
|
||||
case 4:
|
||||
return ShareAmountRole;
|
||||
break;
|
||||
case 5:
|
||||
return BiddingTypeRole;
|
||||
break;
|
||||
case 6:
|
||||
return Bidding1Role;
|
||||
break;
|
||||
case 7:
|
||||
return Bidding2Role;
|
||||
break;
|
||||
case 8:
|
||||
return Bidding3Role;
|
||||
break;
|
||||
case 9:
|
||||
return DepotWish1Role;
|
||||
break;
|
||||
case 10:
|
||||
return DepotWish2Role;
|
||||
break;
|
||||
case 11:
|
||||
return MailRole;
|
||||
break;
|
||||
case 12:
|
||||
return OnlineIdRole;
|
||||
break;
|
||||
case 13:
|
||||
return AccessCodeRole;
|
||||
break;
|
||||
default:
|
||||
qWarning() << QString("No role found for column %1! Returning 'FullNameRole'...").arg(column);
|
||||
return FullNameRole;
|
||||
break;
|
||||
}
|
||||
}
|
||||
static QList<QString> GET_HEADER_NAMES() {
|
||||
QList<QString> result;
|
||||
for (const UserRoles& role : USER_FACING_ROLES) {
|
||||
const QString headerName = ROLE_NAMES.value(role);
|
||||
result.append(headerName);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static QString GET_HEADER_FOR_COLUMN(const int column) {
|
||||
const UserRoles role = GET_ROLE_FOR_COLUMN(column);
|
||||
const QString headerName = ROLE_NAMES.value(role);
|
||||
return headerName;
|
||||
}
|
||||
|
||||
#endif // METADATA_H
|
||||
@ -8,8 +8,28 @@
|
||||
ModelItem::ModelItem(const ModelItemValues values)
|
||||
: m_values(values) {}
|
||||
|
||||
QVariant ModelItem::data(int role) const { return m_values.value(role); }
|
||||
|
||||
QVariant ModelItem::data(int role) const {
|
||||
switch (role) {
|
||||
case FullNameRole:
|
||||
return fullName();
|
||||
break;
|
||||
case ToStringRole:
|
||||
return toString();
|
||||
break;
|
||||
case JsonObjectRole:
|
||||
return toJsonObject();
|
||||
break;
|
||||
case MembershipNumberRole:
|
||||
case ShareAmountRole:
|
||||
case Bidding1Role:
|
||||
case Bidding2Role:
|
||||
case Bidding3Role:
|
||||
return getValueButReplaceZeroValueWithEmptyString(role);
|
||||
break;
|
||||
default:
|
||||
return m_values.value(role);
|
||||
}
|
||||
}
|
||||
bool ModelItem::setData(const QVariant& value, int role) {
|
||||
bool valueChanged = false;
|
||||
if (m_values.contains(role)) {
|
||||
@ -44,6 +64,10 @@ bool ModelItem::setItemData(const QMap<int, QVariant>& changedValues) {
|
||||
return valueChanged;
|
||||
}
|
||||
|
||||
QString ModelItem::fullName() const {
|
||||
return QString("%1 %2").arg(data(FirstNameRole).toString(), data(LastNameRole).toString());
|
||||
}
|
||||
|
||||
QString ModelItem::toString() const {
|
||||
QString result;
|
||||
|
||||
@ -52,15 +76,7 @@ QString ModelItem::toString() const {
|
||||
const UserRoles role = i.next();
|
||||
const QString roleName = ROLE_NAMES.value(role);
|
||||
const QVariant value = data(role);
|
||||
// result.append(value.toString());
|
||||
result.append(QString("%1: %2\n").arg(roleName, data(role).toString()));
|
||||
}
|
||||
|
||||
const UserRoles idRole = IdRole;
|
||||
QVariant idValue = data(idRole);
|
||||
if (!idValue.isNull()) {
|
||||
const QString idRoleName = ROLE_NAMES.value(idRole);
|
||||
result.append(QString("%1: %2\n").arg(idRoleName, idValue.toString()));
|
||||
result.append(QString("%1: %2\n").arg(roleName, value.toString()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -68,12 +84,6 @@ QString ModelItem::toString() const {
|
||||
QJsonObject ModelItem::toJsonObject() const {
|
||||
QJsonObject itemObject;
|
||||
// TODO add UUID and dates (entry, modification, end)
|
||||
const UserRoles idRole = IdRole;
|
||||
QVariant idValue = data(idRole);
|
||||
if (!idValue.isNull()) {
|
||||
const QString idRoleName = ROLE_NAMES.value(idRole);
|
||||
itemObject.insert(idRoleName, idValue.toString());
|
||||
}
|
||||
|
||||
QListIterator<UserRoles> i(USER_FACING_ROLES);
|
||||
while (i.hasNext()) {
|
||||
@ -92,3 +102,12 @@ QJsonObject ModelItem::toJsonObject() const {
|
||||
}
|
||||
return itemObject;
|
||||
}
|
||||
|
||||
QVariant ModelItem::getValueButReplaceZeroValueWithEmptyString(const int role) const {
|
||||
QVariant localValue = m_values.value(role, QVariant());
|
||||
if (localValue == 0) {
|
||||
return QVariant();
|
||||
} else {
|
||||
return localValue;
|
||||
}
|
||||
}
|
||||
@ -14,11 +14,14 @@ class ModelItem {
|
||||
// TODO change return value to list of changed roles
|
||||
bool setItemData(const QMap<int, QVariant>& changedValues);
|
||||
|
||||
QString fullName() const;
|
||||
QString toString() const;
|
||||
QJsonObject toJsonObject() const;
|
||||
|
||||
private:
|
||||
ModelItemValues m_values;
|
||||
|
||||
QVariant getValueButReplaceZeroValueWithEmptyString(const int role) const;
|
||||
};
|
||||
|
||||
#endif // MODELITEM_H
|
||||
@ -21,11 +21,20 @@ QByteArray TableModel::generateExampleItems() {
|
||||
QJsonObject itemObject;
|
||||
// itemObject.insert("uuid", m_uuid.toString());
|
||||
// itemObject.insert("entryDateUTC", m_entryDateUTC.toString(Qt::ISODate));
|
||||
itemObject.insert(ROLE_NAMES.value(NameRole), QString("Item %1").arg(row));
|
||||
itemObject.insert(ROLE_NAMES.value(DescriptionRole), QString("This is item %1").arg(row));
|
||||
itemObject.insert(ROLE_NAMES.value(InfoRole), QString("Info of item %1").arg(row));
|
||||
itemObject.insert(ROLE_NAMES.value(AmountRole), row);
|
||||
itemObject.insert(ROLE_NAMES.value(FactorRole), row * 1.1);
|
||||
itemObject.insert(ROLE_NAMES.value(MembershipNumberRole), row);
|
||||
itemObject.insert(ROLE_NAMES.value(LastNameRole), QString("Nachname%1").arg(row));
|
||||
itemObject.insert(ROLE_NAMES.value(FirstNameRole), QString("Vorname%1").arg(row));
|
||||
itemObject.insert(ROLE_NAMES.value(Bidding1Role), 100 + row);
|
||||
itemObject.insert(ROLE_NAMES.value(DepotWish1Role), QString("Depot X%1").arg(row));
|
||||
itemObject.insert(ROLE_NAMES.value(DepotWish2Role), QString("Depot Y%1").arg(row));
|
||||
itemObject.insert(ROLE_NAMES.value(MailRole),
|
||||
QString("%1@%2.com")
|
||||
.arg(itemObject.value(ROLE_NAMES.value(FirstNameRole)).toString(),
|
||||
itemObject.value(ROLE_NAMES.value(LastNameRole)).toString()));
|
||||
itemObject.insert(ROLE_NAMES.value(ShareAmountRole), 1);
|
||||
itemObject.insert(ROLE_NAMES.value(ShareTypeRole), SHARE_TYPES.at(row % 3));
|
||||
itemObject.insert(ROLE_NAMES.value(BiddingTypeRole), BIDDING_TYPES.at(row % 4));
|
||||
// itemObject.insert(ROLE_NAMES.value(FactorRole), row * 1.1);
|
||||
|
||||
array.append(itemObject);
|
||||
}
|
||||
@ -73,22 +82,32 @@ QVariant TableModel::data(const QModelIndex& index, int role) const {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int roleForColumn = GET_ROLE_FOR_COLUMN(column);
|
||||
const int roleForColumn = GET_ROLE_FOR_COLUMN(column);
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
return m_items.at(row)->data(roleForColumn);
|
||||
case NameRole:
|
||||
case DescriptionRole:
|
||||
case InfoRole:
|
||||
case AmountRole:
|
||||
case FactorRole:
|
||||
case IdRole:
|
||||
return m_items.at(row)->data(role);
|
||||
case Qt::ToolTipRole:
|
||||
return m_items.at(index.row())->data(ToStringRole);
|
||||
break;
|
||||
case MembershipNumberRole:
|
||||
case LastNameRole:
|
||||
case FirstNameRole:
|
||||
case FullNameRole:
|
||||
case Bidding1Role:
|
||||
case Bidding2Role:
|
||||
case Bidding3Role:
|
||||
case DepotWish1Role:
|
||||
case DepotWish2Role:
|
||||
case ShareAmountRole:
|
||||
case MailRole:
|
||||
case ShareTypeRole:
|
||||
case BiddingTypeRole:
|
||||
case OnlineIdRole:
|
||||
case AccessCodeRole:
|
||||
case ToStringRole:
|
||||
return m_items.at(row)->toString();
|
||||
case ToJsonRole:
|
||||
return m_items.at(row)->toJsonObject();
|
||||
case JsonObjectRole:
|
||||
return m_items.at(row)->data(role);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
@ -174,7 +193,7 @@ QList<QStringList> TableModel::getItemsAsStringLists() const {
|
||||
|
||||
// TODO use item selection as parameter to wrap multiple items into JSON data structure
|
||||
QByteArray TableModel::jsonDataForServer(const QModelIndex& currentIndex) const {
|
||||
const QJsonObject itemObject = data(currentIndex, ToJsonRole).toJsonObject();
|
||||
const QJsonObject itemObject = data(currentIndex, JsonObjectRole).toJsonObject();
|
||||
QJsonObject rootObject;
|
||||
rootObject.insert(ITEM_KEY_STRING, itemObject);
|
||||
const QJsonDocument jsonDoc(rootObject);
|
||||
@ -350,8 +369,9 @@ QModelIndex TableModel::searchItemIndex(const ModelItemValues givenItemValues) c
|
||||
bool TableModel::isItemEqualToItemValues(const QModelIndex& itemIndex,
|
||||
const ModelItemValues givenItemValues) const {
|
||||
/// do both have a UUID?
|
||||
QVariant idOfItem = data(itemIndex, IdRole);
|
||||
QVariant given = givenItemValues.value(IdRole);
|
||||
const UserRoles idRole = OnlineIdRole;
|
||||
QVariant idOfItem = data(itemIndex, idRole);
|
||||
QVariant given = givenItemValues.value(idRole);
|
||||
if (idOfItem.isValid() && given.isValid()) {
|
||||
/// are the UUIDs the same?
|
||||
if (idOfItem.toString() == given.toString()) {
|
||||
@ -1,77 +0,0 @@
|
||||
#ifndef METADATA_H
|
||||
#define METADATA_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
// TODO add namespace
|
||||
|
||||
/// model data
|
||||
enum UserRoles {
|
||||
NameRole = Qt::UserRole + 1,
|
||||
DescriptionRole,
|
||||
InfoRole,
|
||||
AmountRole,
|
||||
FactorRole,
|
||||
/// Non user facing
|
||||
IdRole,
|
||||
/// read only roles
|
||||
ToStringRole,
|
||||
ToJsonRole
|
||||
};
|
||||
|
||||
static UserRoles DEFAULT_ROLE = NameRole;
|
||||
// TODO ?rename USER_FACING_ROLES -> MAIN_ROLES ?
|
||||
static QList<UserRoles> USER_FACING_ROLES = {NameRole, DescriptionRole, InfoRole, AmountRole,
|
||||
FactorRole};
|
||||
static QHash<int, QByteArray> ROLE_NAMES = {
|
||||
{NameRole, "name"}, {DescriptionRole, "description"}, {InfoRole, "info"},
|
||||
{AmountRole, "amount"}, {FactorRole, "factor"}, {ToStringRole, "ToString"},
|
||||
{IdRole, "id"}};
|
||||
static QList<UserRoles> STRING_ROLES = {NameRole, DescriptionRole, InfoRole, IdRole};
|
||||
static QList<UserRoles> INT_ROLES = {AmountRole};
|
||||
static QList<UserRoles> DOUBLE_ROLES = {FactorRole};
|
||||
|
||||
/// JSON keys
|
||||
static const QString ITEMS_KEY_STRING = "items";
|
||||
static const QString ITEM_KEY_STRING = "item";
|
||||
|
||||
/// file naming
|
||||
static const QString ITEMS_FILE_NAME = ITEMS_KEY_STRING + ".json";
|
||||
|
||||
/// functions
|
||||
static int GET_ROLE_FOR_COLUMN(const int column) {
|
||||
switch (column) {
|
||||
case 0:
|
||||
return NameRole;
|
||||
break;
|
||||
case 1:
|
||||
return DescriptionRole;
|
||||
break;
|
||||
case 2:
|
||||
return InfoRole;
|
||||
break;
|
||||
case 3:
|
||||
return AmountRole;
|
||||
break;
|
||||
case 4:
|
||||
return FactorRole;
|
||||
break;
|
||||
default:
|
||||
qWarning() << QString("No role found for column %1! Returning 'NameRole'...").arg(column);
|
||||
return NameRole;
|
||||
break;
|
||||
}
|
||||
}
|
||||
static QList<QString> GET_HEADER_NAMES() {
|
||||
QList<QString> result;
|
||||
for (const UserRoles& role : USER_FACING_ROLES) {
|
||||
const QString headerName = ROLE_NAMES.value(role);
|
||||
result.append(headerName);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // METADATA_H
|
||||
@ -24,7 +24,7 @@ target_include_directories(${TARGET_APP} PRIVATE ${CORE_LIB_DIR}/include)
|
||||
target_link_libraries(${TARGET_APP}
|
||||
PRIVATE
|
||||
GTest::GTest
|
||||
GenericCore)
|
||||
BeetRoundCore)
|
||||
target_link_libraries(${TARGET_APP} PUBLIC Qt${QT_VERSION_MAJOR}::Core)
|
||||
|
||||
add_test(core_gtests ${TARGET_APP})
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "../../libs/GenericCore/genericcore.h"
|
||||
#include "../../libs/BeetRoundCore/genericcore.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
inline void PrintTo(const QString& qString, ::std::ostream* os) { *os << qUtf8Printable(qString); }
|
||||
@ -10,7 +10,7 @@ QT_END_NAMESPACE
|
||||
|
||||
TEST(CoreTests, TestEqualString) {
|
||||
const QString coreName("GenericCore");
|
||||
const QString coreVersion("0.2.0");
|
||||
const QString coreVersion("0.1.0");
|
||||
const auto expected = QString("%1 (Version %2)").arg(coreName).arg(coreVersion);
|
||||
auto core = std::make_unique<GenericCore>();
|
||||
const auto actual = core->toString();
|
||||
|
||||
Reference in New Issue
Block a user