Choice model settings was added
This commit is contained in:
@@ -17,10 +17,14 @@ set(TS_FILES beerlog_ru_RU.ts)
|
||||
set(PROJECT_SOURCES
|
||||
main.cpp
|
||||
qml/qml.qrc
|
||||
models/abstractmodel.h models/abstractmodel.cpp
|
||||
models/summarymodel.h models/summarymodel.cpp
|
||||
models/basemodel.h models/basemodel.cpp
|
||||
models/ordersmodel.h models/ordersmodel.cpp
|
||||
models/usersmodel.h models/usersmodel.cpp
|
||||
viewmodels/usersviewmodel.h viewmodels/usersviewmodel.cpp
|
||||
viewmodels/storesviewmodel.h viewmodels/storesviewmodel.cpp
|
||||
viewmodels/productsviewmodel.h viewmodels/productsviewmodel.cpp
|
||||
viewmodels/ordersviewmodel.h viewmodels/ordersviewmodel.cpp
|
||||
viewmodels/settingsviewmodel.h viewmodels/settingsviewmodel.cpp
|
||||
services/beerservice.h services/beerservice.cpp
|
||||
services/settingsservice.h services/settingsservice.cpp
|
||||
${TS_FILES}
|
||||
@@ -55,8 +59,6 @@ else()
|
||||
qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
|
||||
endif()
|
||||
|
||||
qt_add_translations(beerlog TS_FILES beerlog_ru_RU.ts)
|
||||
|
||||
target_link_libraries(beerlog
|
||||
PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick Qt${QT_VERSION_MAJOR}::WebSockets)
|
||||
|
||||
|
||||
@@ -14,6 +14,27 @@
|
||||
<translation>Не в сети</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OrdersView</name>
|
||||
<message>
|
||||
<location filename="qml/Views/OrdersView.qml" line="56"/>
|
||||
<source>Summary: %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ProductsView</name>
|
||||
<message>
|
||||
<location filename="qml/Views/ProductsView.qml" line="88"/>
|
||||
<source>Summary: %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/Views/ProductsView.qml" line="95"/>
|
||||
<source>Order</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsView</name>
|
||||
<message>
|
||||
@@ -40,24 +61,29 @@
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/main.qml" line="72"/>
|
||||
<location filename="qml/main.qml" line="73"/>
|
||||
<source>BeerLog v0.1</source>
|
||||
<oldsource>BeerLog v1.0.0</oldsource>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/main.qml" line="77"/>
|
||||
<location filename="qml/main.qml" line="78"/>
|
||||
<source>Orders</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/main.qml" line="82"/>
|
||||
<source>Settings</source>
|
||||
<translation>Настройки</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/main.qml" line="81"/>
|
||||
<location filename="qml/main.qml" line="117"/>
|
||||
<location filename="qml/main.qml" line="86"/>
|
||||
<location filename="qml/main.qml" line="122"/>
|
||||
<source>Quit</source>
|
||||
<translation>Выход</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/main.qml" line="121"/>
|
||||
<location filename="qml/main.qml" line="126"/>
|
||||
<source>Realy quit the application?</source>
|
||||
<translation>Действительно выйти из приложения?</translation>
|
||||
</message>
|
||||
|
||||
14
main.cpp
14
main.cpp
@@ -6,6 +6,11 @@
|
||||
#include <QQmlContext>
|
||||
|
||||
#include "viewmodels/usersviewmodel.h"
|
||||
#include "viewmodels/productsviewmodel.h"
|
||||
#include "viewmodels/ordersviewmodel.h"
|
||||
#include "viewmodels/storesviewmodel.h"
|
||||
#include "viewmodels/settingsviewmodel.h"
|
||||
|
||||
#include "services/beerservice.h"
|
||||
#include "services/settingsservice.h"
|
||||
|
||||
@@ -17,11 +22,6 @@ int main(int argc, char *argv[])
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QTranslator translator;
|
||||
|
||||
if (!translator.load("qt_ru.qm", "qrc:/")) {
|
||||
qWarning() << "Cant load";
|
||||
}
|
||||
|
||||
const QStringList uiLanguages = QLocale::system().uiLanguages();
|
||||
for (const QString &locale : uiLanguages) {
|
||||
const QString baseName = "beerlog_" + QLocale(locale).name();
|
||||
@@ -45,6 +45,10 @@ int main(int argc, char *argv[])
|
||||
engine.rootContext()->setContextProperty("settingsService", SettingsService::instance());
|
||||
|
||||
qmlRegisterType<UsersViewModel>("ru.ded.beerlog", 1, 0, "UsersViewModel");
|
||||
qmlRegisterType<ProductsViewModel>("ru.ded.beerlog", 1, 0, "ProductsViewModel");
|
||||
qmlRegisterType<OrdersViewModel>("ru.ded.beerlog", 1, 0, "OrdersViewModel");
|
||||
qmlRegisterType<StoresViewModel>("ru.ded.beerlog", 1, 0, "StoresViewModel");
|
||||
qmlRegisterType<SettingsViewModel>("ru.ded.beerlog", 1, 0, "SettingsViewModel");
|
||||
|
||||
engine.load(url);
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
#include "abstractmodel.h"
|
||||
|
||||
#include "services/beerservice.h"
|
||||
|
||||
AbstractModel::AbstractModel(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
}
|
||||
|
||||
void AbstractModel::created(const QVariant &data)
|
||||
{
|
||||
modified(data);
|
||||
}
|
||||
|
||||
void AbstractModel::modified(const QVariant &data)
|
||||
{
|
||||
QVariantMap d = data.toMap();
|
||||
m_data[d.value("id").toString()] = d;
|
||||
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
void AbstractModel::deleted(const QVariant &data)
|
||||
{
|
||||
QString id = data.toString();
|
||||
m_data.remove(id);
|
||||
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
void AbstractModel::received(const QVariant &data)
|
||||
{
|
||||
m_data = data.toMap();
|
||||
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
BeerService *AbstractModel::service() const
|
||||
{
|
||||
return BeerService::instance();
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
#ifndef ABSTRACTMODEL_H
|
||||
#define ABSTRACTMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
class BeerService;
|
||||
class AbstractModel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString entity READ entity CONSTANT)
|
||||
|
||||
public:
|
||||
explicit AbstractModel(QObject *parent = nullptr);
|
||||
|
||||
virtual QString entity() const = 0;
|
||||
|
||||
public slots:
|
||||
void created(const QVariant &data);
|
||||
void modified(const QVariant &data);
|
||||
void deleted(const QVariant &data);
|
||||
void received(const QVariant &data);
|
||||
|
||||
signals:
|
||||
void dataChanged();
|
||||
|
||||
protected:
|
||||
BeerService *service() const;
|
||||
|
||||
QVariantMap m_data;
|
||||
};
|
||||
|
||||
#endif // ABSTRACTMODEL_H
|
||||
90
models/basemodel.cpp
Normal file
90
models/basemodel.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#include "basemodel.h"
|
||||
|
||||
#include "services/beerservice.h"
|
||||
|
||||
BaseModel::BaseModel(const QString &entity, QObject *parent) : QObject{parent},
|
||||
m_entity(entity)
|
||||
{
|
||||
Q_ASSERT(!m_entity.isEmpty());
|
||||
|
||||
service()->connectListener(this);
|
||||
service()->sendCommand(m_entity, BeerService::ActionGet);
|
||||
}
|
||||
|
||||
BaseModel::~BaseModel()
|
||||
{
|
||||
service()->removeListener(this);
|
||||
}
|
||||
|
||||
QString BaseModel::entity() const
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
|
||||
QVariantList BaseModel::items() const
|
||||
{
|
||||
return m_data.values();
|
||||
}
|
||||
|
||||
QVariantMap BaseModel::item(const QString &itemId) const
|
||||
{
|
||||
return m_data.value(itemId).toMap();
|
||||
}
|
||||
|
||||
QVariant BaseModel::itemProperty(const QString &itemId, const QString &propertyName, const QVariant &def) const
|
||||
{
|
||||
return item(itemId).value(propertyName, def);
|
||||
}
|
||||
|
||||
void BaseModel::addItem(const QVariantMap &item) const
|
||||
{
|
||||
service()->sendCommand(entity(), BeerService::ActionAdd, item);
|
||||
}
|
||||
|
||||
void BaseModel::deleteItem(const QString &itemId) const
|
||||
{
|
||||
service()->sendCommand(entity(), BeerService::ActionDelete, QVariantMap { { "id", itemId } });
|
||||
}
|
||||
|
||||
void BaseModel::modifyItem(const QString &itemId, const QVariantMap &properties) const
|
||||
{
|
||||
QVariantMap item = this->item(itemId);
|
||||
for (auto it = properties.constBegin(); it != properties.constEnd(); ++it) {
|
||||
item[it.key()] = it.value();
|
||||
}
|
||||
|
||||
service()->sendCommand(entity(), BeerService::ActionModify, item);
|
||||
}
|
||||
|
||||
void BaseModel::created(const QVariant &data)
|
||||
{
|
||||
modified(data);
|
||||
}
|
||||
|
||||
void BaseModel::modified(const QVariant &data)
|
||||
{
|
||||
QVariantMap d = data.toMap();
|
||||
m_data[d.value("id").toString()] = d;
|
||||
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
void BaseModel::deleted(const QVariant &data)
|
||||
{
|
||||
QString id = data.toString();
|
||||
m_data.remove(id);
|
||||
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
void BaseModel::received(const QVariant &data)
|
||||
{
|
||||
m_data = data.toMap();
|
||||
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
BeerService *BaseModel::service() const
|
||||
{
|
||||
return BeerService::instance();
|
||||
}
|
||||
44
models/basemodel.h
Normal file
44
models/basemodel.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef BASEMODEL_H
|
||||
#define BASEMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
class BeerService;
|
||||
class BaseModel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString entity READ entity CONSTANT)
|
||||
|
||||
public:
|
||||
explicit BaseModel(const QString &entity, QObject *parent = nullptr);
|
||||
virtual ~BaseModel();
|
||||
|
||||
QString entity() const;
|
||||
|
||||
QVariantList items() const;
|
||||
QVariantMap item(const QString &itemId) const;
|
||||
QVariant itemProperty(const QString &itemId, const QString &propertyName, const QVariant &def = QVariant{}) const;
|
||||
|
||||
void addItem(const QVariantMap &item) const;
|
||||
void deleteItem(const QString &itemId) const;
|
||||
void modifyItem(const QString &itemId, const QVariantMap &properties) const;
|
||||
|
||||
public slots:
|
||||
void created(const QVariant &data);
|
||||
void modified(const QVariant &data);
|
||||
void deleted(const QVariant &data);
|
||||
void received(const QVariant &data);
|
||||
|
||||
signals:
|
||||
void dataChanged();
|
||||
|
||||
private:
|
||||
BeerService *service() const;
|
||||
|
||||
QVariantMap m_data;
|
||||
QString m_entity;
|
||||
};
|
||||
|
||||
#endif // BASEMODEL_H
|
||||
15
models/ordersmodel.cpp
Normal file
15
models/ordersmodel.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "ordersmodel.h"
|
||||
|
||||
OrdersModel::OrdersModel(QObject *parent) : BaseModel { "orders", parent }
|
||||
{
|
||||
}
|
||||
|
||||
QVariantList OrdersModel::orders() const
|
||||
{
|
||||
return items();
|
||||
}
|
||||
|
||||
void OrdersModel::submitOrder(const QVariantMap &order) const
|
||||
{
|
||||
addItem(order);
|
||||
}
|
||||
17
models/ordersmodel.h
Normal file
17
models/ordersmodel.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef ORDERSMODEL_H
|
||||
#define ORDERSMODEL_H
|
||||
|
||||
#include "basemodel.h"
|
||||
|
||||
class OrdersModel : public BaseModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OrdersModel(QObject *parent = nullptr);
|
||||
|
||||
QVariantList orders() const;
|
||||
void submitOrder(const QVariantMap &order) const;
|
||||
};
|
||||
|
||||
#endif // ORDERSMODEL_H
|
||||
@@ -1,39 +0,0 @@
|
||||
#include "summarymodel.h"
|
||||
|
||||
QVariantList SummaryModel::items() const
|
||||
{
|
||||
return m_items.values();
|
||||
}
|
||||
|
||||
float SummaryModel::sum() const
|
||||
{
|
||||
float res = 0.0;
|
||||
for (auto it = m_items.constBegin(); it != m_items.constEnd(); ++it) {
|
||||
QVariantMap item = it.value().toMap();
|
||||
int count = item.value("count", 0).toInt();
|
||||
float price = item.value("cost", 0.0).toFloat();
|
||||
res += count * price;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void SummaryModel::setItemCount(QVariantMap item, int count)
|
||||
{
|
||||
QString id = item.value("id", QString()).toString();
|
||||
|
||||
if (count) {
|
||||
item["count"] = count;
|
||||
m_items[id] = item;
|
||||
} else {
|
||||
m_items.remove(id);
|
||||
}
|
||||
|
||||
emit itemsChanged();
|
||||
}
|
||||
|
||||
void SummaryModel::clear()
|
||||
{
|
||||
m_items.clear();
|
||||
|
||||
emit itemsChanged();
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#ifndef SUMMARYMODEL_H
|
||||
#define SUMMARYMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
class SummaryModel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QVariantList items READ items NOTIFY itemsChanged)
|
||||
Q_PROPERTY(float sum READ sum NOTIFY itemsChanged)
|
||||
|
||||
public:
|
||||
QVariantList items() const;
|
||||
float sum() const;
|
||||
|
||||
Q_INVOKABLE void setItemCount(QVariantMap item, int count);
|
||||
Q_INVOKABLE void clear();
|
||||
|
||||
signals:
|
||||
void itemsChanged();
|
||||
|
||||
private:
|
||||
QVariantMap m_items;
|
||||
};
|
||||
|
||||
#endif // SUMMARYMODEL_H
|
||||
@@ -1,24 +1,13 @@
|
||||
#include "usersmodel.h"
|
||||
|
||||
#include "services/beerservice.h"
|
||||
|
||||
namespace Keys {
|
||||
|
||||
constexpr auto Users = "users";
|
||||
constexpr auto Name = "name";
|
||||
|
||||
}
|
||||
|
||||
UsersModel::UsersModel(QObject *parent)
|
||||
: AbstractModel{parent}
|
||||
UsersModel::UsersModel(QObject *parent) : BaseModel{ "users", parent }
|
||||
{
|
||||
service()->connectListener(this);
|
||||
service()->sendCommand(Keys::Users, "get");
|
||||
}
|
||||
|
||||
QString UsersModel::entity() const
|
||||
{
|
||||
return Keys::Users;
|
||||
}
|
||||
|
||||
void UsersModel::connected(const QVariant &data)
|
||||
@@ -33,10 +22,5 @@ void UsersModel::disconnected(const QVariant &data)
|
||||
|
||||
QVariantList UsersModel::users() const
|
||||
{
|
||||
return m_data.values();
|
||||
}
|
||||
|
||||
QString UsersModel::userName(const QString &userId) const
|
||||
{
|
||||
return m_data.value(userId).toMap().value(Keys::Name).toString();
|
||||
return items();
|
||||
}
|
||||
|
||||
@@ -4,19 +4,16 @@
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
#include "models/abstractmodel.h"
|
||||
#include "models/basemodel.h"
|
||||
|
||||
class UsersModel : public AbstractModel
|
||||
class UsersModel : public BaseModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UsersModel(QObject *parent = nullptr);
|
||||
|
||||
QString entity() const override;
|
||||
|
||||
QVariantList users() const;
|
||||
QString userName(const QString &userId) const;
|
||||
|
||||
public slots:
|
||||
void connected(const QVariant &data);
|
||||
|
||||
@@ -1,12 +1,63 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import ru.ded.beerlog 1.0
|
||||
|
||||
Page {
|
||||
|
||||
Label {
|
||||
anchors.centerIn: parent
|
||||
title: qsTr("Orders")
|
||||
|
||||
text: "Orders"
|
||||
OrdersViewModel {
|
||||
id: ordersModel
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: ordersList
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: 10
|
||||
|
||||
model: ordersModel
|
||||
|
||||
section.criteria: ViewSection.FullString
|
||||
section.property: "date"
|
||||
section.delegate: Label {
|
||||
text: section
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
delegate: Column {
|
||||
width: ordersList.width
|
||||
height: productsList.heigt
|
||||
|
||||
ListView {
|
||||
id: productsList
|
||||
|
||||
width: ordersList.width
|
||||
height: contentHeight
|
||||
|
||||
model: products
|
||||
|
||||
header: Label {
|
||||
padding: 10
|
||||
font.bold: true
|
||||
text: "%1 (%2), %3".arg(userName).arg(storeName).arg(time.toLocaleTimeString(Qt.locale(), Locale.ShortFormat))
|
||||
}
|
||||
|
||||
delegate: Label {
|
||||
width: ordersList.width
|
||||
leftPadding: 20
|
||||
|
||||
text: "%1 x%2, %3".arg(modelData.product).arg(modelData.quantity.toLocaleString(Qt.locale())).arg(modelData.price.toLocaleCurrencyString(Qt.locale()))
|
||||
}
|
||||
|
||||
footer: Label {
|
||||
padding: 10
|
||||
font.bold: true
|
||||
text: qsTr("Summary: %1").arg(amount.toLocaleCurrencyString(Qt.locale()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
106
qml/Views/ProductsView.qml
Normal file
106
qml/Views/ProductsView.qml
Normal file
@@ -0,0 +1,106 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import ru.ded.beerlog 1.0
|
||||
|
||||
Page {
|
||||
|
||||
ProductsViewModel {
|
||||
id: productsModel
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
ListView {
|
||||
id: productsList
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: parent.height
|
||||
|
||||
model: productsModel.products
|
||||
|
||||
delegate: ItemDelegate {
|
||||
width: productsList.width
|
||||
|
||||
text: modelData.name
|
||||
height: spinbox.height
|
||||
|
||||
SpinBox {
|
||||
id: spinbox
|
||||
|
||||
width: 150
|
||||
from: 0
|
||||
to: 100 * 100
|
||||
stepSize: 50
|
||||
anchors.right: parent.right
|
||||
editable: true
|
||||
|
||||
property int decimals: 1
|
||||
property real realValue: value / 100
|
||||
|
||||
validator: DoubleValidator {
|
||||
bottom: Math.min(spinbox.from, spinbox.to)
|
||||
top: Math.max(spinbox.from, spinbox.to)
|
||||
}
|
||||
|
||||
textFromValue: function(value, locale) {
|
||||
return value === 0 ? "" : Number(value / 100).toLocaleString(locale, 'f', spinbox.decimals)
|
||||
}
|
||||
|
||||
valueFromText: function(text, locale) {
|
||||
return Number.fromLocaleString(locale, text) * 100
|
||||
}
|
||||
|
||||
onRealValueChanged: productsModel.setOrderValue(modelData.id, realValue)
|
||||
}
|
||||
}
|
||||
|
||||
function reload() {
|
||||
model = undefined
|
||||
model = productsModel.products
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: orderList
|
||||
|
||||
Layout.minimumWidth: parent.width * 0.3
|
||||
Layout.preferredHeight: parent.height
|
||||
|
||||
model: productsModel.order
|
||||
|
||||
delegate: ItemDelegate {
|
||||
width: orderList.width
|
||||
|
||||
text: "%1 x%2".arg(modelData.name).arg(modelData.count.toLocaleString(Qt.locale()))
|
||||
}
|
||||
|
||||
footer: Column {
|
||||
width: orderList.width
|
||||
|
||||
Label {
|
||||
anchors.right: parent.right
|
||||
anchors.margins: 10
|
||||
|
||||
text: qsTr("Summary: %1").arg(productsModel.orderSum.toLocaleCurrencyString(Qt.locale()))
|
||||
}
|
||||
|
||||
Button {
|
||||
anchors.right: parent.right
|
||||
anchors.margins: 10
|
||||
|
||||
text: qsTr("Order")
|
||||
|
||||
enabled: productsModel.orderSum > 0
|
||||
|
||||
onClicked: {
|
||||
productsModel.submitOrder()
|
||||
productsList.reload()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,20 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import Components 1.0
|
||||
import ru.ded.beerlog 1.0
|
||||
|
||||
Page {
|
||||
id: root
|
||||
|
||||
title: qsTr("Settings")
|
||||
|
||||
ListModel {
|
||||
property var controls: {
|
||||
"text": textComponent,
|
||||
"choice": choiceComponent
|
||||
}
|
||||
|
||||
SettingsViewModel {
|
||||
id: settingsModel
|
||||
|
||||
ListElement {
|
||||
title: qsTr("BeerLog service address")
|
||||
name: "serverAddress"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
title: qsTr("Selected user id")
|
||||
name: "selectedUserId"
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
@@ -35,6 +31,8 @@ Page {
|
||||
onClicked: {
|
||||
inputDialog.title = model.title
|
||||
inputDialog.name = model.name
|
||||
inputDialog.control = controls[model.control]
|
||||
inputDialog.choiceModel = model.choiceModel
|
||||
inputDialog.open()
|
||||
}
|
||||
}
|
||||
@@ -44,6 +42,8 @@ Page {
|
||||
id: inputDialog
|
||||
|
||||
property string name: ""
|
||||
property var choiceModel: undefined
|
||||
property alias control: editor.sourceComponent
|
||||
|
||||
width: root.width * 0.8
|
||||
|
||||
@@ -53,22 +53,54 @@ Page {
|
||||
modal: true
|
||||
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||
|
||||
Column {
|
||||
spacing: 20
|
||||
Loader {
|
||||
id: editor
|
||||
|
||||
property var value: item && item.value
|
||||
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
settingsService[inputDialog.name] = editor.value
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: textComponent
|
||||
|
||||
TextField {
|
||||
id: textField
|
||||
|
||||
width: parent.width
|
||||
property alias value: textField.text
|
||||
|
||||
inputMethodHints: Qt.ImhNoAutoUppercase
|
||||
placeholderText: inputDialog.title
|
||||
text: settingsService[inputDialog.name] || ""
|
||||
}
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
settingsService[inputDialog.name] = textField.text
|
||||
ButtonGroup {
|
||||
id: group
|
||||
}
|
||||
|
||||
Component {
|
||||
id: choiceComponent
|
||||
|
||||
Column {
|
||||
|
||||
property var value: group.checkedButton && group.checkedButton.valueId
|
||||
|
||||
Repeater {
|
||||
model: inputDialog.choiceModel
|
||||
|
||||
delegate: RadioDelegate {
|
||||
property var valueId: modelData.id
|
||||
text: modelData.name
|
||||
width: parent.width
|
||||
checked: settingsService[inputDialog.name] === valueId
|
||||
ButtonGroup.group: group
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
31
qml/main.qml
31
qml/main.qml
@@ -26,6 +26,7 @@ ApplicationWindow {
|
||||
Label {
|
||||
text: stackView.currentItem.title || usersModel.selectedUserName
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 100
|
||||
horizontalAlignment: Qt.AlignCenter
|
||||
|
||||
MouseArea {
|
||||
@@ -55,24 +56,46 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Menu {
|
||||
id: storesMenu
|
||||
|
||||
StoresViewModel {
|
||||
id: storesModel
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: storesModel.stores
|
||||
|
||||
MenuItem {
|
||||
text: modelData.name
|
||||
|
||||
onClicked: {
|
||||
storesModel.selectedStore = modelData.id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MainMenu {
|
||||
id: mainMenu
|
||||
|
||||
readonly property var actions: {
|
||||
"orders": () => { stackView.openPage("Views/OrdersView.qml") },
|
||||
"settings": () => { stackView.openPage("Views/SettingsView.qml") },
|
||||
"quit": () => { Qt.quit() }
|
||||
}
|
||||
|
||||
width: parent.width * 0.66
|
||||
height: parent.height
|
||||
|
||||
logo: "qrc:/logo.png"
|
||||
appName: qsTr("BeerLog v0.1")
|
||||
connected: beerService.connected
|
||||
|
||||
model: ListModel {
|
||||
ListElement {
|
||||
title: qsTr("Orders")
|
||||
action: "orders"
|
||||
}
|
||||
ListElement {
|
||||
title: qsTr("Settings")
|
||||
action: "settings"
|
||||
@@ -88,7 +111,7 @@ ApplicationWindow {
|
||||
|
||||
StackView {
|
||||
id: stackView
|
||||
initialItem: "Views/OrdersView.qml"
|
||||
initialItem: "Views/ProductsView.qml"
|
||||
anchors.fill: parent
|
||||
|
||||
function openPage(page) {
|
||||
|
||||
@@ -11,5 +11,6 @@
|
||||
<file>Components/SubtitledItemDelegate.qml</file>
|
||||
<file>Components/qmldir</file>
|
||||
<file>qt_ru.qm</file>
|
||||
<file>Views/ProductsView.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -12,6 +12,13 @@
|
||||
BeerService::BeerService()
|
||||
: QObject{nullptr}
|
||||
{
|
||||
m_actions = {
|
||||
{ ActionGet, "get" },
|
||||
{ ActionAdd, "add" },
|
||||
{ ActionDelete, "del" },
|
||||
{ ActionModify, "mod" }
|
||||
};
|
||||
|
||||
restoreStash();
|
||||
|
||||
connect(&m_socket, &QWebSocket::textMessageReceived, this, [this](QString message) {
|
||||
@@ -31,7 +38,7 @@ BeerService::BeerService()
|
||||
}
|
||||
});
|
||||
|
||||
connect(&m_socket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error), this, [this](QAbstractSocket::SocketError error) {
|
||||
connect(&m_socket, &QWebSocket::errorOccurred, this, [this](QAbstractSocket::SocketError error) {
|
||||
qInfo() << error << m_socket.errorString();
|
||||
});
|
||||
|
||||
@@ -60,11 +67,13 @@ SettingsService *BeerService::settings() const
|
||||
return SettingsService::instance();
|
||||
}
|
||||
|
||||
void BeerService::sendCommand(const QString &entity, const QString &action, const QVariantMap &data)
|
||||
void BeerService::sendCommand(const QString &entity, Action action, const QVariantMap &data)
|
||||
{
|
||||
Q_ASSERT(action != ActionUndefined);
|
||||
|
||||
sendCommand(QVariantMap {
|
||||
{ "entity", entity },
|
||||
{ "action", action },
|
||||
{ "action", m_actions[action] },
|
||||
{ "data", data }
|
||||
});
|
||||
}
|
||||
@@ -75,6 +84,12 @@ void BeerService::connectListener(QObject *listener)
|
||||
m_listeners.insert(entity, listener);
|
||||
}
|
||||
|
||||
void BeerService::removeListener(QObject *listener)
|
||||
{
|
||||
QString entity = listener->property("entity").toString();
|
||||
m_listeners.remove(entity, listener);
|
||||
}
|
||||
|
||||
QString BeerService::stashFileName() const
|
||||
{
|
||||
return QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/command.stash";
|
||||
@@ -102,6 +117,7 @@ void BeerService::restoreStash()
|
||||
QJsonDocument doc = QJsonDocument::fromJson(stash.readAll());
|
||||
m_commandStash = doc.array().toVariantList();
|
||||
stash.close();
|
||||
stash.remove();
|
||||
} else {
|
||||
qWarning() << stash.errorString();
|
||||
}
|
||||
|
||||
@@ -18,8 +18,18 @@ public:
|
||||
return &i;
|
||||
}
|
||||
|
||||
void sendCommand(const QString &entity, const QString &action, const QVariantMap &data = QVariantMap());
|
||||
enum Action
|
||||
{
|
||||
ActionUndefined = 0,
|
||||
ActionGet,
|
||||
ActionAdd,
|
||||
ActionDelete,
|
||||
ActionModify
|
||||
};
|
||||
|
||||
void sendCommand(const QString &entity, Action action, const QVariantMap &data = QVariantMap());
|
||||
void connectListener(QObject *listener);
|
||||
void removeListener(QObject *listener);
|
||||
|
||||
signals:
|
||||
void connectedChanged();
|
||||
@@ -42,6 +52,7 @@ private:
|
||||
|
||||
QWebSocket m_socket;
|
||||
QVariantList m_commandStash;
|
||||
QMap<Action, QString> m_actions;
|
||||
};
|
||||
|
||||
#endif // BEERSERVICE_H
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace Keys {
|
||||
|
||||
constexpr auto ServerAddress = "server_address";
|
||||
constexpr auto SelectedUser = "selected_user";
|
||||
constexpr auto SelectedStore = "selected_store";
|
||||
|
||||
}
|
||||
|
||||
@@ -26,22 +27,45 @@ void SettingsService::setValue(const QString &key, const QVariant &value)
|
||||
|
||||
QString SettingsService::serverAddress() const
|
||||
{
|
||||
return m_settings.value(Keys::ServerAddress, Defaults::ServerAddress).toString();
|
||||
return value(Keys::ServerAddress, Defaults::ServerAddress).toString();
|
||||
}
|
||||
|
||||
void SettingsService::setServerAddress(const QString &address)
|
||||
{
|
||||
m_settings.setValue(Keys::ServerAddress, address);
|
||||
if (serverAddress() == address) {
|
||||
return;
|
||||
}
|
||||
|
||||
setValue(Keys::ServerAddress, address);
|
||||
emit serverAddressChanged();
|
||||
}
|
||||
|
||||
QString SettingsService::selectedUserId() const
|
||||
{
|
||||
return m_settings.value(Keys::SelectedUser, Defaults::GuestUserId).toString();
|
||||
return value(Keys::SelectedUser, Defaults::GuestUserId).toString();
|
||||
}
|
||||
|
||||
void SettingsService::setSelectedUserId(const QString &userId)
|
||||
{
|
||||
m_settings.setValue(Keys::SelectedUser, userId);
|
||||
if (selectedUserId() == userId) {
|
||||
return;
|
||||
}
|
||||
|
||||
setValue(Keys::SelectedUser, userId);
|
||||
emit selectedUserIdChanged();
|
||||
}
|
||||
|
||||
QString SettingsService::selectedStoreId() const
|
||||
{
|
||||
return value(Keys::SelectedStore).toString();
|
||||
}
|
||||
|
||||
void SettingsService::setSelectedStoreId(const QString &storeId)
|
||||
{
|
||||
if (selectedStoreId() == storeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
setValue(Keys::SelectedStore, storeId);
|
||||
emit selectedStoreIdChanged();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ class SettingsService : public QObject
|
||||
|
||||
Q_PROPERTY(QString serverAddress READ serverAddress WRITE setServerAddress NOTIFY serverAddressChanged)
|
||||
Q_PROPERTY(QString selectedUserId READ selectedUserId WRITE setSelectedUserId NOTIFY selectedUserIdChanged)
|
||||
Q_PROPERTY(QString selectedStoreId READ selectedStoreId WRITE setSelectedStoreId NOTIFY selectedStoreIdChanged)
|
||||
|
||||
public:
|
||||
static SettingsService *instance()
|
||||
@@ -18,20 +19,24 @@ public:
|
||||
return &i;
|
||||
}
|
||||
|
||||
QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
|
||||
void setValue(const QString &key, const QVariant &value);
|
||||
|
||||
QString serverAddress() const;
|
||||
void setServerAddress(const QString &address);
|
||||
|
||||
QString selectedUserId() const;
|
||||
void setSelectedUserId(const QString &userId);
|
||||
|
||||
QString selectedStoreId() const;
|
||||
void setSelectedStoreId(const QString &storeId);
|
||||
|
||||
signals:
|
||||
void serverAddressChanged();
|
||||
void selectedUserIdChanged();
|
||||
void selectedStoreIdChanged();
|
||||
|
||||
private:
|
||||
QVariant value(const QString &key, const QVariant &defaultValue = QVariant{}) const;
|
||||
void setValue(const QString &key, const QVariant &value);
|
||||
|
||||
SettingsService() = default;
|
||||
~SettingsService() = default;
|
||||
|
||||
|
||||
72
viewmodels/ordersviewmodel.cpp
Normal file
72
viewmodels/ordersviewmodel.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "ordersviewmodel.h"
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
OrdersViewModel::OrdersViewModel(QObject *parent)
|
||||
: QAbstractListModel{parent}
|
||||
{
|
||||
connect(&m_ordersModel, &BaseModel::dataChanged, this, &OrdersViewModel::reload);
|
||||
connect(&m_usersModel, &BaseModel::dataChanged, this, &OrdersViewModel::reload);
|
||||
connect(&m_productsModel, &BaseModel::dataChanged, this, &OrdersViewModel::reload);
|
||||
connect(&m_storesModel, &BaseModel::dataChanged, this, &OrdersViewModel::reload);
|
||||
|
||||
reload();
|
||||
}
|
||||
|
||||
int OrdersViewModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return m_model.count();
|
||||
}
|
||||
|
||||
QVariant OrdersViewModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return m_model.at(index.row()).toMap()[roleNames().value(role)];
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> OrdersViewModel::roleNames() const
|
||||
{
|
||||
return QHash<int, QByteArray> {
|
||||
{ Roles::UserName, "userName" },
|
||||
{ Roles::StoreName, "storeName" },
|
||||
{ Roles::Date, "date" },
|
||||
{ Roles::Time, "time"},
|
||||
{ Roles::Amount, "amount" },
|
||||
{ Roles::Products, "products" }
|
||||
};
|
||||
}
|
||||
|
||||
void OrdersViewModel::reload()
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
m_model.clear();
|
||||
|
||||
for (const QVariant &vOrder : m_ordersModel.orders()) {
|
||||
QVariantMap order = vOrder.toMap();
|
||||
QDateTime orderTime = QDateTime::fromSecsSinceEpoch(order.value("ts", 0).toDouble());
|
||||
order["date"] = orderTime.date();
|
||||
order["time"] = orderTime.time();
|
||||
order["userName"] = m_usersModel.itemProperty(order["userId"].toString(), "name").toString();
|
||||
order["storeName"] = m_storesModel.itemProperty(order["storeId"].toString(), "name").toString();
|
||||
|
||||
QVariantList prodModel;
|
||||
for (const QVariant &prod : order["products"].toList()) {
|
||||
QVariantMap product = prod.toMap();
|
||||
product["product"] = m_productsModel.itemProperty(product.value("productId").toString(), "name");
|
||||
prodModel << product;
|
||||
}
|
||||
order["products"] = prodModel;
|
||||
|
||||
m_model << order;
|
||||
}
|
||||
|
||||
std::sort(m_model.begin(), m_model.end(), [](const QVariant &l, const QVariant &r) {
|
||||
return l.toMap().value("ts").toDouble() < r.toMap().value("ts").toDouble();
|
||||
});
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
43
viewmodels/ordersviewmodel.h
Normal file
43
viewmodels/ordersviewmodel.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef ORDERSVIEWMODEL_H
|
||||
#define ORDERSVIEWMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
#include "models/ordersmodel.h"
|
||||
#include "models/usersmodel.h"
|
||||
|
||||
class OrdersViewModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OrdersViewModel(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
signals:
|
||||
void ordersChanged();
|
||||
|
||||
private:
|
||||
enum Roles {
|
||||
UserName = Qt::UserRole + 1,
|
||||
StoreName,
|
||||
Date,
|
||||
Time,
|
||||
Amount,
|
||||
Products
|
||||
};
|
||||
|
||||
void reload();
|
||||
|
||||
OrdersModel m_ordersModel;
|
||||
UsersModel m_usersModel;
|
||||
BaseModel m_productsModel = BaseModel("products", this);
|
||||
BaseModel m_storesModel = BaseModel("stores", this);
|
||||
|
||||
QVariantList m_model;
|
||||
};
|
||||
|
||||
#endif // ORDERSVIEWMODEL_H
|
||||
78
viewmodels/productsviewmodel.cpp
Normal file
78
viewmodels/productsviewmodel.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#include "productsviewmodel.h"
|
||||
|
||||
#include "services/settingsservice.h"
|
||||
#include "models/ordersmodel.h"
|
||||
|
||||
ProductsViewModel::ProductsViewModel(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
connect(&m_productsModel, &BaseModel::dataChanged, this, &ProductsViewModel::productsChanged);
|
||||
}
|
||||
|
||||
QVariantList ProductsViewModel::products() const
|
||||
{
|
||||
return m_productsModel.items();
|
||||
}
|
||||
|
||||
QVariantList ProductsViewModel::order() const
|
||||
{
|
||||
QVariantList res;
|
||||
|
||||
for (auto it = m_order.constBegin(); it != m_order.constEnd(); ++it) {
|
||||
QVariantMap product = m_productsModel.item(it.key());
|
||||
product["count"] = it.value().toMap().value("quantity").toDouble();
|
||||
res << product;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
float ProductsViewModel::orderSum() const
|
||||
{
|
||||
float res = 0.0;
|
||||
|
||||
for (auto it = m_order.constBegin(); it != m_order.constEnd(); ++it) {
|
||||
QVariantMap product = m_productsModel.item(it.key());
|
||||
float price = product.value("price", 0.0).toFloat();
|
||||
float quantity = it.value().toMap().value("quantity").toDouble();
|
||||
res += quantity * price;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void ProductsViewModel::setOrderValue(const QString &productId, float value)
|
||||
{
|
||||
if (value) {
|
||||
float price = m_productsModel.itemProperty(productId, "price", 0.0).toFloat();
|
||||
m_order[productId] = QVariantMap {
|
||||
{ "productId", productId },
|
||||
{ "quantity", value},
|
||||
{ "price", price }
|
||||
};
|
||||
} else {
|
||||
m_order.remove(productId);
|
||||
}
|
||||
|
||||
emit orderChanged();
|
||||
}
|
||||
|
||||
void ProductsViewModel::submitOrder()
|
||||
{
|
||||
OrdersModel model;
|
||||
model.submitOrder(QVariantMap {
|
||||
{ "userId", settings()->selectedUserId() },
|
||||
{ "storeId", settings()->selectedStoreId() },
|
||||
{ "products", m_order.values() },
|
||||
{ "amount", orderSum() }
|
||||
});
|
||||
|
||||
m_order.clear();
|
||||
|
||||
emit orderChanged();
|
||||
}
|
||||
|
||||
SettingsService *ProductsViewModel::settings() const
|
||||
{
|
||||
return SettingsService::instance();
|
||||
}
|
||||
38
viewmodels/productsviewmodel.h
Normal file
38
viewmodels/productsviewmodel.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef PRODUCTSVIEWMODEL_H
|
||||
#define PRODUCTSVIEWMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "models/basemodel.h"
|
||||
|
||||
class SettingsService;
|
||||
class ProductsViewModel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QVariantList products READ products NOTIFY productsChanged)
|
||||
Q_PROPERTY(QVariantList order READ order NOTIFY orderChanged)
|
||||
Q_PROPERTY(float orderSum READ orderSum NOTIFY orderChanged)
|
||||
|
||||
public:
|
||||
explicit ProductsViewModel(QObject *parent = nullptr);
|
||||
|
||||
QVariantList products() const;
|
||||
QVariantList order() const;
|
||||
float orderSum() const;
|
||||
|
||||
Q_INVOKABLE void setOrderValue(const QString &productId, float value);
|
||||
Q_INVOKABLE void submitOrder();
|
||||
|
||||
signals:
|
||||
void productsChanged();
|
||||
void orderChanged();
|
||||
|
||||
private:
|
||||
SettingsService *settings() const;
|
||||
|
||||
BaseModel m_productsModel = BaseModel("products", this);
|
||||
QVariantMap m_order;
|
||||
};
|
||||
|
||||
#endif // PRODUCTSVIEWMODEL_H
|
||||
57
viewmodels/settingsviewmodel.cpp
Normal file
57
viewmodels/settingsviewmodel.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "settingsviewmodel.h"
|
||||
|
||||
SettingsViewModel::SettingsViewModel(QObject *parent)
|
||||
: QAbstractListModel{parent}
|
||||
{
|
||||
m_items << SettingItem { tr("BeerLog service address"), "serverAddress", "text" }
|
||||
<< SettingItem { tr("Selected user id"), "selectedUserId", "choice", "users" }
|
||||
<< SettingItem { tr("Selected store"), "selectedStoreId", "choice", "stores" };
|
||||
|
||||
m_models["users"] = new BaseModel("users", this);
|
||||
m_models["stores"] = new BaseModel("stores", this);
|
||||
}
|
||||
|
||||
|
||||
int SettingsViewModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return m_items.count();
|
||||
}
|
||||
|
||||
QVariant SettingsViewModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
SettingItem item = m_items.at(index.row());
|
||||
|
||||
switch (role) {
|
||||
case Roles::Title: return item.title;
|
||||
case Roles::PropertyName: return item.propertyName;
|
||||
case Roles::ControlType: return item.controlType;
|
||||
case Roles::Model: return model(item.modelName);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> SettingsViewModel::roleNames() const
|
||||
{
|
||||
return QHash<int, QByteArray> {
|
||||
{ Roles::Title, "title" },
|
||||
{ Roles::PropertyName, "name" },
|
||||
{ Roles::ControlType, "control" },
|
||||
{ Roles::Model, "choiceModel" }
|
||||
};
|
||||
}
|
||||
|
||||
QVariant SettingsViewModel::model(const QString &modelName) const
|
||||
{
|
||||
if (!m_models.contains(modelName)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return m_models[modelName]->items();
|
||||
}
|
||||
47
viewmodels/settingsviewmodel.h
Normal file
47
viewmodels/settingsviewmodel.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef SETTINGSVIEWMODEL_H
|
||||
#define SETTINGSVIEWMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
#include "models/basemodel.h"
|
||||
|
||||
class SettingsViewModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsViewModel(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
private:
|
||||
enum Roles {
|
||||
Title = Qt::UserRole + 1,
|
||||
PropertyName,
|
||||
ControlType,
|
||||
Model
|
||||
};
|
||||
|
||||
struct SettingItem
|
||||
{
|
||||
QString title;
|
||||
QString propertyName;
|
||||
QString controlType;
|
||||
QString modelName;
|
||||
|
||||
SettingItem(const QString &title, const QString &propertyName, const QString &controlType, const QString &modelName = {}) :
|
||||
title(title),
|
||||
propertyName(propertyName),
|
||||
controlType(controlType),
|
||||
modelName(modelName) {}
|
||||
};
|
||||
|
||||
QVariant model(const QString &modelName) const;
|
||||
|
||||
QList<SettingItem> m_items;
|
||||
QMap<QString, BaseModel *> m_models;
|
||||
};
|
||||
|
||||
#endif // SETTINGSVIEWMODEL_H
|
||||
38
viewmodels/storesviewmodel.cpp
Normal file
38
viewmodels/storesviewmodel.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "storesviewmodel.h"
|
||||
|
||||
#include "services/settingsservice.h"
|
||||
|
||||
StoresViewModel::StoresViewModel(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
connect(&m_storesModel, &BaseModel::dataChanged, this, &StoresViewModel::storesChanged);
|
||||
connect(&m_storesModel, &BaseModel::dataChanged, this, &StoresViewModel::selectedStoreNameChanged);
|
||||
|
||||
connect(settings(), &SettingsService::selectedStoreIdChanged, this, &StoresViewModel::selectedStoreChanged);
|
||||
connect(settings(), &SettingsService::selectedStoreIdChanged, this, &StoresViewModel::selectedStoreNameChanged);
|
||||
}
|
||||
|
||||
QVariantList StoresViewModel::stores() const
|
||||
{
|
||||
return m_storesModel.items();
|
||||
}
|
||||
|
||||
QString StoresViewModel::selectedStore() const
|
||||
{
|
||||
return settings()->selectedStoreId();
|
||||
}
|
||||
|
||||
void StoresViewModel::setSelectedStore(const QString &newSelectedStore)
|
||||
{
|
||||
settings()->setSelectedStoreId(newSelectedStore);
|
||||
}
|
||||
|
||||
QString StoresViewModel::selectedStoreName() const
|
||||
{
|
||||
return m_storesModel.itemProperty(selectedStore(), "name").toString();
|
||||
}
|
||||
|
||||
SettingsService *StoresViewModel::settings() const
|
||||
{
|
||||
return SettingsService::instance();
|
||||
}
|
||||
36
viewmodels/storesviewmodel.h
Normal file
36
viewmodels/storesviewmodel.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef STORESVIEWMODEL_H
|
||||
#define STORESVIEWMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "models/basemodel.h"
|
||||
|
||||
class SettingsService;
|
||||
class StoresViewModel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QVariantList stores READ stores NOTIFY storesChanged)
|
||||
Q_PROPERTY(QString selectedStore READ selectedStore WRITE setSelectedStore NOTIFY selectedStoreChanged)
|
||||
Q_PROPERTY(QString selectedStoreName READ selectedStoreName NOTIFY selectedStoreNameChanged)
|
||||
|
||||
public:
|
||||
explicit StoresViewModel(QObject *parent = nullptr);
|
||||
|
||||
QVariantList stores() const;
|
||||
QString selectedStore() const;
|
||||
void setSelectedStore(const QString &newSelectedStore);
|
||||
QString selectedStoreName() const;
|
||||
|
||||
signals:
|
||||
void storesChanged();
|
||||
void selectedStoreChanged();
|
||||
void selectedStoreNameChanged();
|
||||
|
||||
private:
|
||||
SettingsService *settings() const;
|
||||
|
||||
BaseModel m_storesModel = BaseModel("stores", this);
|
||||
};
|
||||
|
||||
#endif // STORESVIEWMODEL_H
|
||||
@@ -5,8 +5,8 @@
|
||||
UsersViewModel::UsersViewModel(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
connect(&m_usersModel, &AbstractModel::dataChanged, this, &UsersViewModel::usersChanged);
|
||||
connect(&m_usersModel, &AbstractModel::dataChanged, this, &UsersViewModel::selectedUserNameChanged);
|
||||
connect(&m_usersModel, &BaseModel::dataChanged, this, &UsersViewModel::usersChanged);
|
||||
connect(&m_usersModel, &BaseModel::dataChanged, this, &UsersViewModel::selectedUserNameChanged);
|
||||
|
||||
connect(settings(), &SettingsService::selectedUserIdChanged, this, &UsersViewModel::selectedUserChanged);
|
||||
connect(settings(), &SettingsService::selectedUserIdChanged, this, &UsersViewModel::selectedUserNameChanged);
|
||||
@@ -24,16 +24,12 @@ QString UsersViewModel::selectedUser() const
|
||||
|
||||
void UsersViewModel::setSelectedUser(const QString &newSelectedUser)
|
||||
{
|
||||
if (selectedUser() == newSelectedUser) {
|
||||
return;
|
||||
}
|
||||
|
||||
settings()->setSelectedUserId(newSelectedUser);
|
||||
}
|
||||
|
||||
QString UsersViewModel::selectedUserName() const
|
||||
{
|
||||
return m_usersModel.userName(selectedUser());
|
||||
return m_usersModel.itemProperty(selectedUser(), "name").toString();
|
||||
}
|
||||
|
||||
SettingsService *UsersViewModel::settings() const
|
||||
|
||||
Reference in New Issue
Block a user