Compare commits
19 Commits
c83ba2da9d
...
7fa8612313
| Author | SHA1 | Date | |
|---|---|---|---|
| 7fa8612313 | |||
| 8dbceabb8a | |||
| 2d8c97b5f0 | |||
| 2fb7560e6e | |||
| 560cadb2c0 | |||
| 0e7f803d42 | |||
| d56af7231c | |||
| 385dc7ca76 | |||
| 5e3950f6ba | |||
| 34a34891b4 | |||
| 4c4d734b1b | |||
| 0eef55fc32 | |||
| d109eb31f8 | |||
| a9f24ac8f2 | |||
| 67d9a3914d | |||
| 518bebcbb7 | |||
| 8f61c6bc2f | |||
| a966b26185 | |||
| a8bf5b4032 |
@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(TARGET_APP "GenericQtClient-Widgets")
|
||||
project(${TARGET_APP} VERSION 0.2.0 LANGUAGES CXX)
|
||||
project(${TARGET_APP} VERSION 0.3.0 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
@ -27,12 +27,15 @@ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
qt_add_executable(${TARGET_APP}
|
||||
MANUAL_FINALIZATION
|
||||
${PROJECT_SOURCES}
|
||||
utils/messagehandler.h
|
||||
|
||||
assets/icons.qrc
|
||||
dialogs/abstractdialog.h dialogs/abstractdialog.cpp
|
||||
dialogs/newitemdialog.h dialogs/newitemdialog.cpp
|
||||
dialogs/edititemdialog.h dialogs/edititemdialog.cpp
|
||||
dialogs/settingsdialog.h dialogs/settingsdialog.cpp
|
||||
views/itemdetailmapper.h views/itemdetailmapper.cpp
|
||||
widgets/controls/comboboxdelegate.h widgets/controls/comboboxdelegate.cpp
|
||||
widgethelper.h widgethelper.cpp
|
||||
)
|
||||
# Define target properties for Android with Qt 6 as:
|
||||
# set_property(TARGET ${TARGET_APP} APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
|
||||
@ -63,6 +66,8 @@ 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_include_directories(${TARGET_APP} PRIVATE ${QR_LIB_DIR}/src)
|
||||
target_link_libraries(${TARGET_APP} PRIVATE qrcode)
|
||||
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB |
@ -1,7 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>software-application.png</file>
|
||||
<file>feature.png</file>
|
||||
<file>no-picture-taking.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 22 KiB |
@ -1,13 +1,15 @@
|
||||
#include "edititemdialog.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "../views/itemdetailmapper.h"
|
||||
|
||||
EditItemDialog::EditItemDialog(QTableView* tableView, QWidget* parent)
|
||||
: AbstractDialog(QDialogButtonBox::Close, parent)
|
||||
, m_tableView(tableView) {}
|
||||
: AbstractDialog(QDialogButtonBox::Ok, parent)
|
||||
, m_tableView(tableView)
|
||||
, m_qrCodeDisplay(new QLabel("QR Code")) {}
|
||||
|
||||
void EditItemDialog::createContent() {
|
||||
if (m_contentContainer) {
|
||||
@ -16,9 +18,16 @@ void EditItemDialog::createContent() {
|
||||
|
||||
setWindowTitle(tr("Edit item..."));
|
||||
|
||||
m_detailMapper = new ItemDetailMapper(this);
|
||||
m_detailMapper->setModelMappings(m_tableView);
|
||||
m_contentContainer = m_detailMapper;
|
||||
m_contentContainer = new QWidget(this);
|
||||
QHBoxLayout* innerLayout = new QHBoxLayout();
|
||||
m_contentContainer->setLayout(innerLayout);
|
||||
|
||||
m_detailMapper = new ItemDetailMapper(m_tableView, this);
|
||||
innerLayout->addWidget(m_detailMapper);
|
||||
|
||||
updateQRCode();
|
||||
connect(m_detailMapper, &ItemDetailMapper::contentChanged, this, &EditItemDialog::updateQRCode);
|
||||
innerLayout->addWidget(m_qrCodeDisplay);
|
||||
|
||||
m_outerLayout->insertWidget(0, m_contentContainer);
|
||||
}
|
||||
@ -32,3 +41,16 @@ void EditItemDialog::reject() {
|
||||
m_detailMapper->revert();
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void EditItemDialog::updateQRCode(const QString text) {
|
||||
QImage unscaledImage;
|
||||
if (text.isEmpty()) {
|
||||
unscaledImage = QImage("://no-picture-taking.png");
|
||||
} else {
|
||||
unscaledImage = m_generator.generateQr(text);
|
||||
}
|
||||
QImage image = unscaledImage.scaled(250, 250);
|
||||
|
||||
m_qrCodeDisplay->setPixmap(QPixmap::fromImage(image));
|
||||
m_qrCodeDisplay->setToolTip(text);
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#ifndef EDITITEMDIALOG_H
|
||||
#define EDITITEMDIALOG_H
|
||||
|
||||
#include "QrCodeGenerator.h"
|
||||
#include "abstractdialog.h"
|
||||
|
||||
class QDoubleSpinBox;
|
||||
@ -23,6 +24,9 @@ class EditItemDialog : public AbstractDialog {
|
||||
void accept() override;
|
||||
void reject() override;
|
||||
|
||||
private slots:
|
||||
void updateQRCode(const QString text = "");
|
||||
|
||||
private:
|
||||
QTableView* m_tableView = nullptr;
|
||||
ItemDetailMapper* m_detailMapper;
|
||||
@ -41,6 +45,9 @@ class EditItemDialog : public AbstractDialog {
|
||||
|
||||
QLabel* m_factorLabel = nullptr;
|
||||
QDoubleSpinBox* m_factorBox = nullptr;
|
||||
|
||||
QLabel* m_qrCodeDisplay = nullptr;
|
||||
QrCodeGenerator m_generator;
|
||||
};
|
||||
|
||||
#endif // EDITITEMDIALOG_H
|
||||
|
||||
@ -1,11 +1,15 @@
|
||||
#include "newitemdialog.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QGridLayout>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QSpinBox>
|
||||
#include <QStringListModel>
|
||||
|
||||
#include "../widgethelper.h"
|
||||
#include "formats/jsonparser.h"
|
||||
#include "model/metadata.h"
|
||||
|
||||
@ -21,61 +25,84 @@ void NewItemDialog::createContent() {
|
||||
|
||||
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_layout = new QGridLayout();
|
||||
|
||||
m_descriptionLabel = new QLabel("&Description");
|
||||
m_descriptionEdit = new QLineEdit();
|
||||
m_descriptionLabel->setBuddy(m_descriptionEdit);
|
||||
for (int i = 0; i < USER_FACING_ROLES.size(); ++i) {
|
||||
setupWidgetPairForColumn(i);
|
||||
}
|
||||
|
||||
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_contentContainer->setLayout(m_layout);
|
||||
|
||||
m_outerLayout->insertWidget(0, m_contentContainer);
|
||||
}
|
||||
|
||||
void NewItemDialog::accept() {
|
||||
QHash<int, QVariant> 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());
|
||||
addItemToModel();
|
||||
|
||||
const QByteArray jsonDoc = JsonParser::itemValuesListToJson({itemValues}, ITEM_KEY_STRING);
|
||||
emit addItems(jsonDoc);
|
||||
resetContent();
|
||||
|
||||
// resetContent();
|
||||
AbstractDialog::accept();
|
||||
}
|
||||
|
||||
void NewItemDialog::setupWidgetPairForColumn(const int column) {
|
||||
// REFACTOR consolidate NewItemDialog::setupWidgetPairForColumn(...)
|
||||
// with ItemDetailMapper::setupWidgetPairForColumn(...)
|
||||
const UserRoles role = GET_ROLE_FOR_COLUMN(column);
|
||||
|
||||
QWidget* control = WidgetHelper::createControlWidget(role, this);
|
||||
|
||||
const QString string = QString("&%1").arg(GET_HEADER_FOR_COLUMN(column));
|
||||
QLabel* label = new QLabel(string);
|
||||
label->setBuddy(control);
|
||||
|
||||
m_layout->addWidget(label, column, 0);
|
||||
m_layout->addWidget(control, column, 1);
|
||||
m_controlWidgets.append(control);
|
||||
}
|
||||
|
||||
void NewItemDialog::addItemToModel() {
|
||||
ModelItemValues itemValues;
|
||||
|
||||
for (int i = 0; i < m_controlWidgets.size(); ++i) {
|
||||
const UserRoles role = GET_ROLE_FOR_COLUMN(i);
|
||||
if (STRING_ROLES.contains(role)) {
|
||||
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(m_controlWidgets[i]);
|
||||
itemValues.insert(role, lineEdit->text());
|
||||
} else if (TYPE_ROLES.contains(role)) {
|
||||
QComboBox* comboBox = dynamic_cast<QComboBox*>(m_controlWidgets[i]);
|
||||
itemValues.insert(role, comboBox->currentText());
|
||||
} else if (INT_ROLES.contains(role)) {
|
||||
QSpinBox* spinBox = dynamic_cast<QSpinBox*>(m_controlWidgets[i]);
|
||||
itemValues.insert(role, spinBox->value());
|
||||
} else if (DOUBLE_ROLES.contains(role)) {
|
||||
QDoubleSpinBox* doubleSpinBox = dynamic_cast<QDoubleSpinBox*>(m_controlWidgets[i]);
|
||||
itemValues.insert(role, doubleSpinBox->value());
|
||||
} else {
|
||||
qCritical() << "Could not reset content for control widget in column:" << i << "!";
|
||||
}
|
||||
}
|
||||
|
||||
const QByteArray jsonDoc = JsonParser::itemValuesListToJson({itemValues}, ITEMS_KEY_STRING);
|
||||
emit addItems(jsonDoc);
|
||||
}
|
||||
|
||||
void NewItemDialog::resetContent() {
|
||||
for (int i = 0; i < m_controlWidgets.size(); ++i) {
|
||||
const UserRoles role = GET_ROLE_FOR_COLUMN(i);
|
||||
if (STRING_ROLES.contains(role)) {
|
||||
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(m_controlWidgets[i]);
|
||||
lineEdit->clear();
|
||||
} else if (TYPE_ROLES.contains(role)) {
|
||||
QComboBox* comboBox = dynamic_cast<QComboBox*>(m_controlWidgets[i]);
|
||||
comboBox->setCurrentText("");
|
||||
} else if (INT_ROLES.contains(role)) {
|
||||
QSpinBox* spinBox = dynamic_cast<QSpinBox*>(m_controlWidgets[i]);
|
||||
spinBox->setValue(0);
|
||||
} else if (DOUBLE_ROLES.contains(role)) {
|
||||
QDoubleSpinBox* doubleSpinBox = dynamic_cast<QDoubleSpinBox*>(m_controlWidgets[i]);
|
||||
doubleSpinBox->setValue(0.0);
|
||||
} else {
|
||||
qCritical() << "Could not reset content for control widget in column:" << i << "!";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,20 +24,13 @@ class NewItemDialog : public AbstractDialog {
|
||||
// void reject() override;
|
||||
|
||||
private:
|
||||
QLabel* m_nameLabel = nullptr;
|
||||
QLineEdit* m_nameEdit = nullptr;
|
||||
QGridLayout* m_layout;
|
||||
QList<QWidget*> m_controlWidgets;
|
||||
|
||||
QLabel* m_descriptionLabel = nullptr;
|
||||
QLineEdit* m_descriptionEdit = nullptr;
|
||||
void setupWidgetPairForColumn(const int column);
|
||||
|
||||
QLabel* m_infoLabel = nullptr;
|
||||
QLineEdit* m_infoEdit = nullptr;
|
||||
|
||||
QLabel* m_amountLabel = nullptr;
|
||||
QSpinBox* m_amountBox = nullptr;
|
||||
|
||||
QLabel* m_factorLabel = nullptr;
|
||||
QDoubleSpinBox* m_factorBox = nullptr;
|
||||
void addItemToModel();
|
||||
void resetContent();
|
||||
};
|
||||
|
||||
#endif // NEWITEMDIALOG_H
|
||||
|
||||
63
dialogs/settingsdialog.cpp
Normal file
63
dialogs/settingsdialog.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include "settingsdialog.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QTabWidget>
|
||||
|
||||
SettingsDialog::SettingsDialog(QWidget* parent)
|
||||
: AbstractDialog(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, parent) {}
|
||||
|
||||
void SettingsDialog::createContent() {
|
||||
if (m_contentContainer) {
|
||||
delete m_contentContainer;
|
||||
}
|
||||
|
||||
const QString dialogTitle = tr("Settings - ");
|
||||
const QString applicationName = QCoreApplication::applicationName();
|
||||
|
||||
setWindowTitle(dialogTitle + applicationName);
|
||||
setModal(true);
|
||||
setGeometry(0, 0, 350, 250);
|
||||
QGridLayout* serverLayout = new QGridLayout();
|
||||
QLabel* urlLabel = new QLabel("Server URL:");
|
||||
m_urlEdit = new QLineEdit();
|
||||
serverLayout->addWidget(urlLabel, 0, 0);
|
||||
serverLayout->addWidget(m_urlEdit, 0, 1);
|
||||
QLabel* emailLabel = new QLabel("Email:");
|
||||
m_emailEdit = new QLineEdit();
|
||||
m_emailEdit->setEnabled(false);
|
||||
serverLayout->addWidget(emailLabel, 1, 0);
|
||||
serverLayout->addWidget(m_emailEdit, 1, 1);
|
||||
QLabel* passwordLabel = new QLabel("Password:");
|
||||
m_passwordEdit = new QLineEdit();
|
||||
m_passwordEdit->setEnabled(false);
|
||||
m_passwordEdit->setEchoMode(QLineEdit::Password);
|
||||
serverLayout->addWidget(passwordLabel, 2, 0);
|
||||
serverLayout->addWidget(m_passwordEdit, 2, 1);
|
||||
|
||||
QWidget* serverTab = new QWidget();
|
||||
serverTab->setLayout(serverLayout);
|
||||
|
||||
QTabWidget* widget = new QTabWidget();
|
||||
widget->addTab(serverTab, "Server");
|
||||
|
||||
m_contentContainer = widget;
|
||||
m_outerLayout->insertWidget(0, m_contentContainer);
|
||||
}
|
||||
|
||||
void SettingsDialog::fillContent(const QVariantMap& settings) {
|
||||
m_urlEdit->setText(settings.value("url").toString());
|
||||
m_emailEdit->setText(settings.value("email").toString());
|
||||
m_passwordEdit->setText(settings.value("password").toString());
|
||||
}
|
||||
|
||||
QVariantMap SettingsDialog::getSettings() const {
|
||||
QVariantMap result;
|
||||
result.insert("url", m_urlEdit->text());
|
||||
result.insert("email", m_emailEdit->text());
|
||||
result.insert("password", m_passwordEdit->text());
|
||||
|
||||
return result;
|
||||
}
|
||||
23
dialogs/settingsdialog.h
Normal file
23
dialogs/settingsdialog.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef SETTINGSDIALOG_H
|
||||
#define SETTINGSDIALOG_H
|
||||
|
||||
#include "abstractdialog.h"
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
class SettingsDialog : public AbstractDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
SettingsDialog(QWidget* parent = nullptr);
|
||||
|
||||
void createContent() override;
|
||||
void fillContent(const QVariantMap& settings);
|
||||
QVariantMap getSettings() const;
|
||||
|
||||
private:
|
||||
QLineEdit* m_urlEdit = nullptr;
|
||||
QLineEdit* m_emailEdit = nullptr;
|
||||
QLineEdit* m_passwordEdit = nullptr;
|
||||
};
|
||||
|
||||
#endif // SETTINGSDIALOG_H
|
||||
108
mainwindow.cpp
108
mainwindow.cpp
@ -10,12 +10,14 @@
|
||||
#include <QUndoView>
|
||||
|
||||
#include "../../ApplicationConfig.h"
|
||||
#include "data/settingshandler.h"
|
||||
#include "dialogs/edititemdialog.h"
|
||||
#include "dialogs/newitemdialog.h"
|
||||
#include "dialogs/settingsdialog.h"
|
||||
#include "genericcore.h"
|
||||
#include "model/generalsortfiltermodel.h"
|
||||
#include "model/metadata.h"
|
||||
#include "model/tablemodel.h"
|
||||
#include "widgets/controls/comboboxdelegate.h"
|
||||
|
||||
static QStandardPaths::StandardLocation standardLocation = QStandardPaths::HomeLocation;
|
||||
static QString updateTextClean = "Do you want to update the application now?";
|
||||
@ -31,26 +33,24 @@ MainWindow::MainWindow(QWidget* parent)
|
||||
setWindowTitle(QCoreApplication::applicationName() + " [*]");
|
||||
|
||||
/// application icon
|
||||
const QString iconString = "://feature.png";
|
||||
const QString iconString = "://software-application.png";
|
||||
#ifdef QT_DEBUG
|
||||
QPixmap pixmap = QPixmap(iconString);
|
||||
QTransform transform = QTransform();
|
||||
transform.rotate(180);
|
||||
QPixmap rotated = pixmap.transformed(transform);
|
||||
QIcon appIcon = QIcon(rotated);
|
||||
qWarning() << "appIcon.availableSizes():" << appIcon.availableSizes();
|
||||
setWindowIcon(QIcon(rotated));
|
||||
#else
|
||||
setWindowIcon(QIcon(iconString));
|
||||
#endif
|
||||
|
||||
const QVariantMap settings = SettingsHandler::getSettings("GUI");
|
||||
const QVariantMap settings = m_core->getSettings("GUI");
|
||||
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();
|
||||
@ -106,8 +106,7 @@ void MainWindow::closeEvent(QCloseEvent* event) {
|
||||
|
||||
if (event->isAccepted()) {
|
||||
qInfo() << "Saving GUI settings...";
|
||||
SettingsHandler::saveSettings({{"geometry", saveGeometry()}, {"windowState", saveState()}},
|
||||
"GUI");
|
||||
m_core->applySettings({{"geometry", saveGeometry()}, {"windowState", saveState()}}, "GUI");
|
||||
}
|
||||
}
|
||||
|
||||
@ -297,11 +296,70 @@ void MainWindow::findItems() {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::fetchItems() {
|
||||
showStatusMessage(tr("Invoked 'Server|Fetch items'"));
|
||||
emit m_core->fetchItemsFromServer();
|
||||
}
|
||||
|
||||
void MainWindow::postItems() {
|
||||
showStatusMessage(tr("Invoked 'Server|Post items'"));
|
||||
const QModelIndex currentIndex = ui->tableView->currentIndex();
|
||||
const QByteArray jsonData = m_proxyModel->jsonDataForServer(currentIndex);
|
||||
emit m_core->postItemToServer(jsonData);
|
||||
}
|
||||
|
||||
void MainWindow::deleteItem() {
|
||||
showStatusMessage(tr("Invoked 'Server|Delete items'"));
|
||||
const QModelIndex currentIndex = ui->tableView->currentIndex();
|
||||
// const QByteArray jsonData = m_proxyModel->jsonDataForServer(currentIndex);
|
||||
const QString currentId = m_proxyModel->getUuid(currentIndex);
|
||||
emit m_core->deleteItemFromServer(currentId);
|
||||
}
|
||||
|
||||
void MainWindow::execSettingsDialog() {
|
||||
showStatusMessage(tr("Invoked 'Tools|Settings'"));
|
||||
QVariantMap oldSettings = m_core->getSettings("Server");
|
||||
// SettingsDialog* settingsDialog = new SettingsDialog(settingMap, this);
|
||||
SettingsDialog* settingsDialog = new SettingsDialog(this);
|
||||
settingsDialog->createContent();
|
||||
settingsDialog->fillContent(oldSettings);
|
||||
|
||||
int returnCode = settingsDialog->exec();
|
||||
if (returnCode == QDialog::Accepted) {
|
||||
qDebug() << "Settings dialog accepted, writing settings...";
|
||||
const QVariantMap settings = settingsDialog->getSettings();
|
||||
|
||||
m_core->applySettings(settings, "Server");
|
||||
// TODO use signal-slot connection Core::syncServerSetupChanged(bool enabled) ->
|
||||
// MainWindow::onSyncServerSetupChanged(bool enabled)
|
||||
|
||||
// enableDisableServerActions();
|
||||
} else {
|
||||
qDebug() << "Settings dialog rejected";
|
||||
}
|
||||
delete settingsDialog;
|
||||
}
|
||||
|
||||
void MainWindow::setupModelViews() {
|
||||
// m_tableModel = m_core->getModel();
|
||||
// ui->tableView->setModel(m_tableModel.get());
|
||||
m_proxyModel = m_core->getSortFilterModel();
|
||||
|
||||
const int typeColumn = GET_COLUMN_FOR_ROLE(TypeRole);
|
||||
ComboboxDelegate* shareTypeDelegate = new ComboboxDelegate(TYPES, this);
|
||||
ui->tableView->setItemDelegateForColumn(typeColumn, shareTypeDelegate);
|
||||
|
||||
ui->tableView->setModel((QAbstractItemModel*)m_proxyModel.get());
|
||||
ui->tableView->setSortingEnabled(true);
|
||||
}
|
||||
|
||||
void MainWindow::createActions() {
|
||||
// TODO add generic menu actions (file/new, edit/cut, ...)
|
||||
createFileActions();
|
||||
createUndoActions();
|
||||
createEditActions();
|
||||
createServerActions();
|
||||
createToolsActions();
|
||||
}
|
||||
|
||||
void MainWindow::createFileActions() {
|
||||
@ -433,7 +491,7 @@ void MainWindow::createEditActions() {
|
||||
ui->menu_Edit->addAction(m_openEditItemDialogAct.get());
|
||||
|
||||
m_deleteItemAct = make_unique<QAction>(tr("&Delete item(s)"), this);
|
||||
m_deleteItemAct->setShortcuts(QKeySequence::Delete);
|
||||
m_deleteItemAct->setShortcut(QKeySequence::Delete);
|
||||
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::deleteCurrentItem);
|
||||
@ -448,6 +506,34 @@ void MainWindow::createEditActions() {
|
||||
ui->menu_Edit->addAction(m_findItemAct.get());
|
||||
}
|
||||
|
||||
void MainWindow::createServerActions() {
|
||||
m_fetchItemsAct = make_unique<QAction>(tr("&Fetch item(s)"), this);
|
||||
m_fetchItemsAct->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_Down));
|
||||
m_fetchItemsAct->setStatusTip(tr("Fetches all item on configured server"));
|
||||
connect(m_fetchItemsAct.get(), &QAction::triggered, this, &MainWindow::fetchItems);
|
||||
ui->menu_Server->addAction(m_fetchItemsAct.get());
|
||||
|
||||
m_postItemsAct = make_unique<QAction>(tr("&Post item(s)"), this);
|
||||
m_postItemsAct->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_Up));
|
||||
// m_postItemsAct->setStatusTip(tr("Posts the selected items on configured server"));
|
||||
m_postItemsAct->setStatusTip(tr("Posts the current item on configured server"));
|
||||
connect(m_postItemsAct.get(), &QAction::triggered, this, &MainWindow::postItems);
|
||||
ui->menu_Server->addAction(m_postItemsAct.get());
|
||||
|
||||
m_deleteItemsAct = make_unique<QAction>(tr("&Delete item"), this);
|
||||
m_deleteItemsAct->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_Backspace));
|
||||
// m_deleteItemsAct->setStatusTip(tr("Deletes the selected items on configured server"));
|
||||
m_deleteItemsAct->setStatusTip(tr("Deletes the current item on configured server"));
|
||||
connect(m_deleteItemsAct.get(), &QAction::triggered, this, &MainWindow::deleteItem);
|
||||
ui->menu_Server->addAction(m_deleteItemsAct.get());
|
||||
}
|
||||
|
||||
void MainWindow::createToolsActions() {
|
||||
QMenu* menu = ui->menu_Tools;
|
||||
QAction* settingsAct = menu->addAction(tr("&Settings"), this, &MainWindow::execSettingsDialog);
|
||||
settingsAct->setStatusTip(tr("Opens a dialog to configure applications settings."));
|
||||
}
|
||||
|
||||
void MainWindow::createHelpMenu() {
|
||||
QMenu* helpMenu = ui->menu_Help;
|
||||
helpMenu->addSeparator();
|
||||
|
||||
16
mainwindow.h
16
mainwindow.h
@ -63,6 +63,14 @@ class MainWindow : public QMainWindow {
|
||||
/// 'Edit' slots
|
||||
void findItems();
|
||||
|
||||
/// 'Server' slots
|
||||
void fetchItems();
|
||||
void postItems();
|
||||
void deleteItem();
|
||||
|
||||
/// 'Tools' slots
|
||||
void execSettingsDialog();
|
||||
|
||||
private:
|
||||
Ui::MainWindow* ui;
|
||||
|
||||
@ -89,6 +97,11 @@ class MainWindow : public QMainWindow {
|
||||
unique_ptr<QAction> m_openEditItemDialogAct;
|
||||
unique_ptr<QAction> m_deleteItemAct;
|
||||
unique_ptr<QAction> m_findItemAct;
|
||||
/// Server actions
|
||||
unique_ptr<QAction> m_fetchItemsAct;
|
||||
unique_ptr<QAction> m_postItemsAct;
|
||||
unique_ptr<QAction> m_deleteItemsAct;
|
||||
|
||||
/// View actions
|
||||
unique_ptr<QAction> m_showModelUndoViewAct;
|
||||
|
||||
@ -97,10 +110,13 @@ class MainWindow : public QMainWindow {
|
||||
unique_ptr<EditItemDialog> m_editItemDialog;
|
||||
|
||||
/// Setup functions
|
||||
void setupModelViews();
|
||||
void createActions();
|
||||
void createFileActions();
|
||||
void createUndoActions();
|
||||
void createEditActions();
|
||||
void createServerActions();
|
||||
void createToolsActions();
|
||||
void createHelpMenu();
|
||||
void createGuiDialogs();
|
||||
};
|
||||
|
||||
@ -40,7 +40,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>25</height>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
@ -64,9 +64,21 @@
|
||||
</property>
|
||||
<addaction name="actionCheck_for_update"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Server">
|
||||
<property name="title">
|
||||
<string>&Server</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Tools">
|
||||
<property name="title">
|
||||
<string>&Tools</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="menu_File"/>
|
||||
<addaction name="menu_Edit"/>
|
||||
<addaction name="menu_View"/>
|
||||
<addaction name="menu_Server"/>
|
||||
<addaction name="menu_Tools"/>
|
||||
<addaction name="menu_Help"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
|
||||
@ -1,164 +0,0 @@
|
||||
#ifndef MESSAGEHANDLER_H
|
||||
#define MESSAGEHANDLER_H
|
||||
/**
|
||||
* Color and formatting codes
|
||||
* @see: http://misc.flogisoft.com/bash/tip_colors_and_formatting
|
||||
*/
|
||||
|
||||
#include <QObject>
|
||||
|
||||
// qSetMessagePattern("%{file}(%{line}): %{message}");
|
||||
// qSetMessagePattern("%{type}(%{line}):\t%{message}");
|
||||
// qSetMessagePattern("%{type}%{file}(%{line}):\t%{message}");
|
||||
|
||||
void consoleHandlerColoredVerbose(QtMsgType type,
|
||||
const QMessageLogContext& context,
|
||||
const QString& msg) {
|
||||
QByteArray localMsg = msg.toLocal8Bit();
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
// fprintf(stderr, "\033[1;30mDebug: (%s:%u, %s) \t%s\n\033[0m", context.file,
|
||||
// context.line, context.function, localMsg.constData()); // bold
|
||||
fprintf(stderr, "\033[107;30mDebug: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line,
|
||||
context.function, localMsg.constData());
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
fprintf(stderr, "\033[107;32mInfo: (%s:%u) \t%s\n\033[0m", context.file, context.line,
|
||||
localMsg.constData());
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
fprintf(stderr, "\033[43;30mWarning: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line,
|
||||
context.function, localMsg.constData());
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
fprintf(stderr, "\033[41;30mCritical: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line,
|
||||
context.function, localMsg.constData());
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
fprintf(stderr, "\033[41;30mFatal: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line,
|
||||
context.function, localMsg.constData());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void consoleHandlerColoredVerboseInDarkTheme(QtMsgType type,
|
||||
const QMessageLogContext& context,
|
||||
const QString& msg) {
|
||||
QByteArray localMsg = msg.toLocal8Bit();
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
// fprintf(stderr, "\033[1;30mDebug: (%s:%u, %s) \t%s\n\033[0m", context.file,
|
||||
// context.line, context.function, localMsg.constData()); // bold
|
||||
fprintf(stderr, "\033[107;37mDebug: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line,
|
||||
context.function, localMsg.constData());
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
fprintf(stderr, "\033[107;32mInfo: (%s:%u) \t%s\n\033[0m", context.file, context.line,
|
||||
localMsg.constData());
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
fprintf(stderr, "\033[43;30mWarning: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line,
|
||||
context.function, localMsg.constData());
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
fprintf(stderr, "\033[41;30mCritical: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line,
|
||||
context.function, localMsg.constData());
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
fprintf(stderr, "\033[41;30mFatal: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line,
|
||||
context.function, localMsg.constData());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void consoleHandlerColored(QtMsgType type, const QMessageLogContext& context, const QString& msg) {
|
||||
QByteArray localMsg = msg.toLocal8Bit();
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
fprintf(stderr, "\033[1;30mDebug: (%s:%u) \t%s\n\033[0m", context.file, context.line,
|
||||
localMsg.constData());
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
fprintf(stderr, "\033[0;30mInfo: (%s:%u) \t%s\n\033[0m", context.file, context.line,
|
||||
localMsg.constData());
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
fprintf(stderr, "\033[1;33mWarning: (%s:%u) \t%s\n\033[0m", context.file, context.line,
|
||||
localMsg.constData());
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
fprintf(stderr, "\033[31mCritical: (%s:%u) \t%s\n\033[0m", context.file, context.line,
|
||||
localMsg.constData());
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
fprintf(stderr, "\033[31mFatal: (%s:%u) \t%s\n\033[0m", context.file, context.line,
|
||||
localMsg.constData());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void myMessageOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) {
|
||||
QByteArray localMsg = msg.toLocal8Bit();
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line,
|
||||
context.function);
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line,
|
||||
context.function);
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line,
|
||||
context.function);
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file,
|
||||
context.line, context.function);
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line,
|
||||
context.function);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
#include <android/log.h>
|
||||
|
||||
const char* const applicationName = "Pensieve";
|
||||
void androidMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) {
|
||||
QString report = msg;
|
||||
if (context.file && !QString(context.file).isEmpty()) {
|
||||
report += " in file ";
|
||||
report += QString(context.file);
|
||||
report += " line ";
|
||||
report += QString::number(context.line);
|
||||
}
|
||||
if (context.function && !QString(context.function).isEmpty()) {
|
||||
report += +" function ";
|
||||
report += QString(context.function);
|
||||
}
|
||||
const char* const local = report.toLocal8Bit().constData();
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
__android_log_write(ANDROID_LOG_DEBUG, applicationName, local);
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
__android_log_write(ANDROID_LOG_INFO, applicationName, local);
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
__android_log_write(ANDROID_LOG_WARN, applicationName, local);
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
__android_log_write(ANDROID_LOG_ERROR, applicationName, local);
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
default:
|
||||
__android_log_write(ANDROID_LOG_FATAL, applicationName, local);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // MESSAGEHANDLER_H
|
||||
@ -11,7 +11,9 @@
|
||||
#include <QSpinBox>
|
||||
#include <QTableView>
|
||||
|
||||
ItemDetailMapper::ItemDetailMapper(QWidget* parent)
|
||||
#include "../widgethelper.h"
|
||||
|
||||
ItemDetailMapper::ItemDetailMapper(QTableView* tableView, QWidget* parent)
|
||||
: QWidget{parent} {
|
||||
/// model mapping
|
||||
m_mapper = std::make_unique<QDataWidgetMapper>(this);
|
||||
@ -24,76 +26,16 @@ ItemDetailMapper::ItemDetailMapper(QWidget* parent)
|
||||
// m_mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
|
||||
m_mapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);
|
||||
|
||||
/// model mapping buttons
|
||||
m_nextButton = new QPushButton(tr("Ne&xt"));
|
||||
m_previousButton = new QPushButton(tr("&Previous"));
|
||||
|
||||
connect(m_previousButton, &QAbstractButton::clicked, this, &ItemDetailMapper::toPrevious);
|
||||
connect(m_nextButton, &QAbstractButton::clicked, this, &ItemDetailMapper::toNext);
|
||||
|
||||
/// the individual widgets
|
||||
// REFACTOR deduce label names and types from meta data & use a factory
|
||||
m_nameLabel = new QLabel("&Name");
|
||||
m_nameEdit = new QLineEdit();
|
||||
m_nameLabel->setBuddy(m_nameEdit);
|
||||
|
||||
m_descriptionLabel = new QLabel("&Description");
|
||||
m_descriptionEdit = new QLineEdit();
|
||||
m_descriptionLabel->setBuddy(m_descriptionEdit);
|
||||
|
||||
m_infoLabel = new QLabel("&Info");
|
||||
m_infoEdit = new QLineEdit();
|
||||
m_infoLabel->setBuddy(m_infoEdit);
|
||||
|
||||
m_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());
|
||||
setupWidgets();
|
||||
|
||||
connect(m_model, &QAbstractItemModel::rowsInserted, this, &ItemDetailMapper::rowsInserted);
|
||||
connect(m_model, &QAbstractItemModel::rowsRemoved, this, &ItemDetailMapper::rowsRemoved);
|
||||
connect(m_selectionModel, &QItemSelectionModel::currentChanged, this,
|
||||
&ItemDetailMapper::onCurrentIndexChanged);
|
||||
|
||||
updateButtons(m_selectionModel->currentIndex().row());
|
||||
setupConnections();
|
||||
}
|
||||
|
||||
bool ItemDetailMapper::submit() { return m_mapper->submit(); }
|
||||
@ -101,12 +43,13 @@ bool ItemDetailMapper::submit() { return m_mapper->submit(); }
|
||||
void ItemDetailMapper::revert() { m_mapper->revert(); }
|
||||
|
||||
void ItemDetailMapper::onCurrentIndexChanged(const QModelIndex& current,
|
||||
const QModelIndex& previous) {
|
||||
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) {
|
||||
@ -115,13 +58,7 @@ void ItemDetailMapper::rowsInserted(const QModelIndex& parent, int start, int en
|
||||
|
||||
void ItemDetailMapper::rowsRemoved(const QModelIndex& parent, int start, int end) {
|
||||
if (m_model->rowCount() == 0) {
|
||||
setEnabled(false);
|
||||
|
||||
m_nameEdit->clear();
|
||||
m_descriptionEdit->clear();
|
||||
m_infoEdit->clear();
|
||||
m_amountBox->clear();
|
||||
m_factorBox->clear();
|
||||
clearControlWidgets();
|
||||
}
|
||||
|
||||
updateButtons(m_mapper->currentIndex());
|
||||
@ -147,3 +84,108 @@ 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);
|
||||
|
||||
const int nRows = m_layout->rowCount();
|
||||
m_layout->addWidget(m_previousButton, nRows, 0);
|
||||
m_layout->addWidget(m_nextButton, nRows, 1);
|
||||
}
|
||||
|
||||
void ItemDetailMapper::setupWidgets() {
|
||||
m_layout = new QGridLayout();
|
||||
|
||||
for (int i = 0; i < USER_FACING_ROLES.size(); ++i) {
|
||||
setupWidgetPairForColumn(i);
|
||||
}
|
||||
setupNavigationButtons();
|
||||
|
||||
setLayout(m_layout);
|
||||
}
|
||||
|
||||
void ItemDetailMapper::setupWidgetPairForColumn(const int column) {
|
||||
// REFACTOR consolidate ItemDetailMapper::setupWidgetPairForColumn(...)
|
||||
// with NewItemDialog::setupWidgetPairForColumn(...)
|
||||
const UserRoles role = GET_ROLE_FOR_COLUMN(column);
|
||||
|
||||
QWidget* control = WidgetHelper::createControlWidget(role, this);
|
||||
|
||||
const QString string = QString("&%1").arg(GET_HEADER_FOR_COLUMN(column));
|
||||
QLabel* label = new QLabel(string);
|
||||
label->setBuddy(control);
|
||||
|
||||
m_layout->addWidget(label, column, 0);
|
||||
m_layout->addWidget(control, column, 1);
|
||||
m_controlWidgets.append(control);
|
||||
|
||||
if (TYPE_ROLES.contains(role)) {
|
||||
m_mapper->addMapping(control, column, "currentText");
|
||||
} else {
|
||||
m_mapper->addMapping(control, column);
|
||||
}
|
||||
}
|
||||
|
||||
void ItemDetailMapper::clearControlWidgets() {
|
||||
setEnabled(false);
|
||||
|
||||
for (int i = 0; i < m_controlWidgets.size(); ++i) {
|
||||
const UserRoles role = GET_ROLE_FOR_COLUMN(i);
|
||||
if (STRING_ROLES.contains(role)) {
|
||||
clearLineEdit(i);
|
||||
} else if (TYPE_ROLES.contains(role)) {
|
||||
clearComboBox(i);
|
||||
} else if (INT_ROLES.contains(role)) {
|
||||
clearSpinBox(i);
|
||||
} else if (DOUBLE_ROLES.contains(role)) {
|
||||
clearSpinBox(i);
|
||||
} else {
|
||||
qCritical() << "Could not reset content for control widget in column:" << i << "!";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ItemDetailMapper::clearLineEdit(const int column) {
|
||||
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(m_controlWidgets[column]);
|
||||
if (lineEdit) {
|
||||
lineEdit->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ItemDetailMapper::clearComboBox(const int column) {
|
||||
QComboBox* comboBox = dynamic_cast<QComboBox*>(m_controlWidgets[column]);
|
||||
if (comboBox) {
|
||||
comboBox->setCurrentText("");
|
||||
}
|
||||
}
|
||||
|
||||
void ItemDetailMapper::clearSpinBox(const int column) {
|
||||
QAbstractSpinBox* spinBox = dynamic_cast<QAbstractSpinBox*>(m_controlWidgets[column]);
|
||||
if (spinBox) {
|
||||
spinBox->clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
#ifndef ITEMDETAILMAPPER_H
|
||||
#define ITEMDETAILMAPPER_H
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDataWidgetMapper>
|
||||
#include <QStringListModel>
|
||||
#include <QWidget>
|
||||
#include "model/metadata.h"
|
||||
|
||||
class QGridLayout;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QDoubleSpinBox;
|
||||
@ -16,14 +20,13 @@ class QTableView;
|
||||
class ItemDetailMapper : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ItemDetailMapper(QWidget* parent = nullptr);
|
||||
|
||||
void setModelMappings(QTableView* tableView);
|
||||
explicit ItemDetailMapper(QTableView* tableView, QWidget* parent = nullptr);
|
||||
|
||||
bool submit();
|
||||
void revert();
|
||||
|
||||
signals:
|
||||
void contentChanged(const QString text);
|
||||
|
||||
private slots:
|
||||
void onCurrentIndexChanged(const QModelIndex& current, const QModelIndex& previous);
|
||||
@ -32,6 +35,7 @@ class ItemDetailMapper : public QWidget {
|
||||
void toPrevious();
|
||||
void toNext();
|
||||
void updateButtons(int row);
|
||||
void emitContentChanged(const QModelIndex& currentIndex);
|
||||
|
||||
private:
|
||||
/// *** members ***
|
||||
@ -43,23 +47,22 @@ class ItemDetailMapper : public QWidget {
|
||||
std::unique_ptr<QDataWidgetMapper> m_mapper;
|
||||
|
||||
/// GUI elements
|
||||
QLabel* m_nameLabel = nullptr;
|
||||
QLineEdit* m_nameEdit = nullptr;
|
||||
|
||||
QLabel* m_descriptionLabel = nullptr;
|
||||
QLineEdit* m_descriptionEdit = nullptr;
|
||||
|
||||
QLabel* m_infoLabel = nullptr;
|
||||
QLineEdit* m_infoEdit = nullptr;
|
||||
|
||||
QLabel* m_amountLabel = nullptr;
|
||||
QSpinBox* m_amountBox = nullptr;
|
||||
|
||||
QLabel* m_factorLabel = nullptr;
|
||||
QDoubleSpinBox* m_factorBox = nullptr;
|
||||
QGridLayout* m_layout;
|
||||
QList<QWidget*> m_controlWidgets;
|
||||
|
||||
QPushButton* m_nextButton;
|
||||
QPushButton* m_previousButton;
|
||||
|
||||
void setupConnections();
|
||||
void setupNavigationButtons();
|
||||
void setupWidgets();
|
||||
|
||||
void setupWidgetPairForColumn(const int column);
|
||||
|
||||
void clearControlWidgets();
|
||||
void clearLineEdit(const int column);
|
||||
void clearComboBox(const int column);
|
||||
void clearSpinBox(const int column);
|
||||
};
|
||||
|
||||
#endif // ITEMDETAILMAPPER_H
|
||||
|
||||
45
widgethelper.cpp
Normal file
45
widgethelper.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#include "widgethelper.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
#include <QSpinBox>
|
||||
#include <QStringListModel>
|
||||
|
||||
QWidget* WidgetHelper::createControlWidget(const UserRoles role, QWidget* parent) {
|
||||
QWidget* control;
|
||||
if (STRING_ROLES.contains(role)) {
|
||||
control = new QLineEdit();
|
||||
} else if (TYPE_ROLES.contains(role)) {
|
||||
control = createComboBox(role, parent);
|
||||
} else if (INT_ROLES.contains(role)) {
|
||||
QSpinBox* spinBox = new QSpinBox();
|
||||
spinBox->setMaximum(1000);
|
||||
control = spinBox;
|
||||
} else if (DOUBLE_ROLES.contains(role)) {
|
||||
QDoubleSpinBox* spinBox = new QDoubleSpinBox();
|
||||
spinBox->setMaximum(1000);
|
||||
control = spinBox;
|
||||
} else {
|
||||
qCritical() << QString("Unsupported role %1!!!").arg(role);
|
||||
qDebug() << "Using line edit as well and pretend it's a string role...";
|
||||
control = new QLineEdit();
|
||||
}
|
||||
return control;
|
||||
}
|
||||
|
||||
QWidget* WidgetHelper::createComboBox(const UserRoles role, QWidget* parent) {
|
||||
QStringListModel* typeModel;
|
||||
if (role == TypeRole) {
|
||||
typeModel = new QStringListModel(TYPES, parent);
|
||||
} else {
|
||||
qCritical() << "Unsupported type with role:" << role
|
||||
<< "- Using string list model with only one empty string!";
|
||||
typeModel = new QStringListModel({""}, parent);
|
||||
}
|
||||
QComboBox* comboBox = new QComboBox();
|
||||
comboBox->setModel(typeModel);
|
||||
comboBox->setCurrentText("");
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
WidgetHelper::WidgetHelper() {}
|
||||
17
widgethelper.h
Normal file
17
widgethelper.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef WIDGETHELPER_H
|
||||
#define WIDGETHELPER_H
|
||||
|
||||
#include "model/metadata.h"
|
||||
|
||||
class QWidget;
|
||||
|
||||
class WidgetHelper {
|
||||
public:
|
||||
static QWidget* createControlWidget(const UserRoles role, QWidget* parent);
|
||||
static QWidget* createComboBox(const UserRoles role, QWidget* parent);
|
||||
|
||||
private:
|
||||
explicit WidgetHelper();
|
||||
};
|
||||
|
||||
#endif // WIDGETHELPER_H
|
||||
57
widgets/controls/comboboxdelegate.cpp
Normal file
57
widgets/controls/comboboxdelegate.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#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 isType = TYPE_ROLES.contains(role);
|
||||
/// Put the value into the SpinBox
|
||||
if (isType) {
|
||||
const QString valueString = index.model()->data(index, TypeRole).toString();
|
||||
int value = TYPES.indexOf(valueString);
|
||||
|
||||
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);
|
||||
}
|
||||
31
widgets/controls/comboboxdelegate.h
Normal file
31
widgets/controls/comboboxdelegate.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef COMBOBOXDELEGATE_H
|
||||
#define COMBOBOXDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
class QStringListModel;
|
||||
|
||||
class ComboboxDelegate : public QStyledItemDelegate {
|
||||
// TODO move source code files into subfolder "widgets/delegate"
|
||||
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
|
||||
Reference in New Issue
Block a user