Choice model settings was added
This commit is contained in:
@@ -17,10 +17,14 @@ set(TS_FILES beerlog_ru_RU.ts)
|
|||||||
set(PROJECT_SOURCES
|
set(PROJECT_SOURCES
|
||||||
main.cpp
|
main.cpp
|
||||||
qml/qml.qrc
|
qml/qml.qrc
|
||||||
models/abstractmodel.h models/abstractmodel.cpp
|
models/basemodel.h models/basemodel.cpp
|
||||||
models/summarymodel.h models/summarymodel.cpp
|
models/ordersmodel.h models/ordersmodel.cpp
|
||||||
models/usersmodel.h models/usersmodel.cpp
|
models/usersmodel.h models/usersmodel.cpp
|
||||||
viewmodels/usersviewmodel.h viewmodels/usersviewmodel.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/beerservice.h services/beerservice.cpp
|
||||||
services/settingsservice.h services/settingsservice.cpp
|
services/settingsservice.h services/settingsservice.cpp
|
||||||
${TS_FILES}
|
${TS_FILES}
|
||||||
@@ -55,8 +59,6 @@ else()
|
|||||||
qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
|
qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
qt_add_translations(beerlog TS_FILES beerlog_ru_RU.ts)
|
|
||||||
|
|
||||||
target_link_libraries(beerlog
|
target_link_libraries(beerlog
|
||||||
PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick Qt${QT_VERSION_MAJOR}::WebSockets)
|
PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick Qt${QT_VERSION_MAJOR}::WebSockets)
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,27 @@
|
|||||||
<translation>Не в сети</translation>
|
<translation>Не в сети</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</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>
|
<context>
|
||||||
<name>SettingsView</name>
|
<name>SettingsView</name>
|
||||||
<message>
|
<message>
|
||||||
@@ -40,24 +61,29 @@
|
|||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/main.qml" line="72"/>
|
<location filename="qml/main.qml" line="73"/>
|
||||||
<source>BeerLog v0.1</source>
|
<source>BeerLog v0.1</source>
|
||||||
<oldsource>BeerLog v1.0.0</oldsource>
|
<oldsource>BeerLog v1.0.0</oldsource>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<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>
|
<source>Settings</source>
|
||||||
<translation>Настройки</translation>
|
<translation>Настройки</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/main.qml" line="81"/>
|
<location filename="qml/main.qml" line="86"/>
|
||||||
<location filename="qml/main.qml" line="117"/>
|
<location filename="qml/main.qml" line="122"/>
|
||||||
<source>Quit</source>
|
<source>Quit</source>
|
||||||
<translation>Выход</translation>
|
<translation>Выход</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/main.qml" line="121"/>
|
<location filename="qml/main.qml" line="126"/>
|
||||||
<source>Realy quit the application?</source>
|
<source>Realy quit the application?</source>
|
||||||
<translation>Действительно выйти из приложения?</translation>
|
<translation>Действительно выйти из приложения?</translation>
|
||||||
</message>
|
</message>
|
||||||
|
|||||||
14
main.cpp
14
main.cpp
@@ -6,6 +6,11 @@
|
|||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
|
|
||||||
#include "viewmodels/usersviewmodel.h"
|
#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/beerservice.h"
|
||||||
#include "services/settingsservice.h"
|
#include "services/settingsservice.h"
|
||||||
|
|
||||||
@@ -17,11 +22,6 @@ int main(int argc, char *argv[])
|
|||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
QTranslator translator;
|
QTranslator translator;
|
||||||
|
|
||||||
if (!translator.load("qt_ru.qm", "qrc:/")) {
|
|
||||||
qWarning() << "Cant load";
|
|
||||||
}
|
|
||||||
|
|
||||||
const QStringList uiLanguages = QLocale::system().uiLanguages();
|
const QStringList uiLanguages = QLocale::system().uiLanguages();
|
||||||
for (const QString &locale : uiLanguages) {
|
for (const QString &locale : uiLanguages) {
|
||||||
const QString baseName = "beerlog_" + QLocale(locale).name();
|
const QString baseName = "beerlog_" + QLocale(locale).name();
|
||||||
@@ -45,6 +45,10 @@ int main(int argc, char *argv[])
|
|||||||
engine.rootContext()->setContextProperty("settingsService", SettingsService::instance());
|
engine.rootContext()->setContextProperty("settingsService", SettingsService::instance());
|
||||||
|
|
||||||
qmlRegisterType<UsersViewModel>("ru.ded.beerlog", 1, 0, "UsersViewModel");
|
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);
|
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 "usersmodel.h"
|
||||||
|
|
||||||
#include "services/beerservice.h"
|
|
||||||
|
|
||||||
namespace Keys {
|
namespace Keys {
|
||||||
|
|
||||||
constexpr auto Users = "users";
|
|
||||||
constexpr auto Name = "name";
|
constexpr auto Name = "name";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UsersModel::UsersModel(QObject *parent)
|
UsersModel::UsersModel(QObject *parent) : BaseModel{ "users", parent }
|
||||||
: AbstractModel{parent}
|
|
||||||
{
|
{
|
||||||
service()->connectListener(this);
|
|
||||||
service()->sendCommand(Keys::Users, "get");
|
|
||||||
}
|
|
||||||
|
|
||||||
QString UsersModel::entity() const
|
|
||||||
{
|
|
||||||
return Keys::Users;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UsersModel::connected(const QVariant &data)
|
void UsersModel::connected(const QVariant &data)
|
||||||
@@ -33,10 +22,5 @@ void UsersModel::disconnected(const QVariant &data)
|
|||||||
|
|
||||||
QVariantList UsersModel::users() const
|
QVariantList UsersModel::users() const
|
||||||
{
|
{
|
||||||
return m_data.values();
|
return items();
|
||||||
}
|
|
||||||
|
|
||||||
QString UsersModel::userName(const QString &userId) const
|
|
||||||
{
|
|
||||||
return m_data.value(userId).toMap().value(Keys::Name).toString();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,19 +4,16 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
|
|
||||||
#include "models/abstractmodel.h"
|
#include "models/basemodel.h"
|
||||||
|
|
||||||
class UsersModel : public AbstractModel
|
class UsersModel : public BaseModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit UsersModel(QObject *parent = nullptr);
|
explicit UsersModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
QString entity() const override;
|
|
||||||
|
|
||||||
QVariantList users() const;
|
QVariantList users() const;
|
||||||
QString userName(const QString &userId) const;
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void connected(const QVariant &data);
|
void connected(const QVariant &data);
|
||||||
|
|||||||
@@ -1,12 +1,63 @@
|
|||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.15
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import ru.ded.beerlog 1.0
|
||||||
|
|
||||||
Page {
|
Page {
|
||||||
|
|
||||||
Label {
|
title: qsTr("Orders")
|
||||||
anchors.centerIn: parent
|
|
||||||
|
|
||||||
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 2.15
|
||||||
import QtQuick.Controls 2.15
|
import QtQuick.Controls 2.15
|
||||||
import Components 1.0
|
import Components 1.0
|
||||||
|
import ru.ded.beerlog 1.0
|
||||||
|
|
||||||
Page {
|
Page {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
title: qsTr("Settings")
|
title: qsTr("Settings")
|
||||||
|
|
||||||
ListModel {
|
property var controls: {
|
||||||
|
"text": textComponent,
|
||||||
|
"choice": choiceComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsViewModel {
|
||||||
id: settingsModel
|
id: settingsModel
|
||||||
|
|
||||||
ListElement {
|
|
||||||
title: qsTr("BeerLog service address")
|
|
||||||
name: "serverAddress"
|
|
||||||
}
|
|
||||||
|
|
||||||
ListElement {
|
|
||||||
title: qsTr("Selected user id")
|
|
||||||
name: "selectedUserId"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
@@ -35,6 +31,8 @@ Page {
|
|||||||
onClicked: {
|
onClicked: {
|
||||||
inputDialog.title = model.title
|
inputDialog.title = model.title
|
||||||
inputDialog.name = model.name
|
inputDialog.name = model.name
|
||||||
|
inputDialog.control = controls[model.control]
|
||||||
|
inputDialog.choiceModel = model.choiceModel
|
||||||
inputDialog.open()
|
inputDialog.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,6 +42,8 @@ Page {
|
|||||||
id: inputDialog
|
id: inputDialog
|
||||||
|
|
||||||
property string name: ""
|
property string name: ""
|
||||||
|
property var choiceModel: undefined
|
||||||
|
property alias control: editor.sourceComponent
|
||||||
|
|
||||||
width: root.width * 0.8
|
width: root.width * 0.8
|
||||||
|
|
||||||
@@ -53,22 +53,54 @@ Page {
|
|||||||
modal: true
|
modal: true
|
||||||
standardButtons: Dialog.Ok | Dialog.Cancel
|
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||||
|
|
||||||
Column {
|
Loader {
|
||||||
spacing: 20
|
id: editor
|
||||||
|
|
||||||
|
property var value: item && item.value
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
onAccepted: {
|
||||||
|
settingsService[inputDialog.name] = editor.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: textComponent
|
||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: textField
|
id: textField
|
||||||
|
|
||||||
width: parent.width
|
property alias value: textField.text
|
||||||
|
|
||||||
inputMethodHints: Qt.ImhNoAutoUppercase
|
inputMethodHints: Qt.ImhNoAutoUppercase
|
||||||
placeholderText: inputDialog.title
|
|
||||||
text: settingsService[inputDialog.name] || ""
|
text: settingsService[inputDialog.name] || ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onAccepted: {
|
ButtonGroup {
|
||||||
settingsService[inputDialog.name] = textField.text
|
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 {
|
Label {
|
||||||
text: stackView.currentItem.title || usersModel.selectedUserName
|
text: stackView.currentItem.title || usersModel.selectedUserName
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.minimumWidth: 100
|
||||||
horizontalAlignment: Qt.AlignCenter
|
horizontalAlignment: Qt.AlignCenter
|
||||||
|
|
||||||
MouseArea {
|
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 {
|
MainMenu {
|
||||||
id: mainMenu
|
id: mainMenu
|
||||||
|
|
||||||
readonly property var actions: {
|
readonly property var actions: {
|
||||||
|
"orders": () => { stackView.openPage("Views/OrdersView.qml") },
|
||||||
"settings": () => { stackView.openPage("Views/SettingsView.qml") },
|
"settings": () => { stackView.openPage("Views/SettingsView.qml") },
|
||||||
"quit": () => { Qt.quit() }
|
"quit": () => { Qt.quit() }
|
||||||
}
|
}
|
||||||
|
|
||||||
width: parent.width * 0.66
|
|
||||||
height: parent.height
|
|
||||||
|
|
||||||
logo: "qrc:/logo.png"
|
logo: "qrc:/logo.png"
|
||||||
appName: qsTr("BeerLog v0.1")
|
appName: qsTr("BeerLog v0.1")
|
||||||
connected: beerService.connected
|
connected: beerService.connected
|
||||||
|
|
||||||
model: ListModel {
|
model: ListModel {
|
||||||
|
ListElement {
|
||||||
|
title: qsTr("Orders")
|
||||||
|
action: "orders"
|
||||||
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
title: qsTr("Settings")
|
title: qsTr("Settings")
|
||||||
action: "settings"
|
action: "settings"
|
||||||
@@ -88,7 +111,7 @@ ApplicationWindow {
|
|||||||
|
|
||||||
StackView {
|
StackView {
|
||||||
id: stackView
|
id: stackView
|
||||||
initialItem: "Views/OrdersView.qml"
|
initialItem: "Views/ProductsView.qml"
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
function openPage(page) {
|
function openPage(page) {
|
||||||
|
|||||||
@@ -11,5 +11,6 @@
|
|||||||
<file>Components/SubtitledItemDelegate.qml</file>
|
<file>Components/SubtitledItemDelegate.qml</file>
|
||||||
<file>Components/qmldir</file>
|
<file>Components/qmldir</file>
|
||||||
<file>qt_ru.qm</file>
|
<file>qt_ru.qm</file>
|
||||||
|
<file>Views/ProductsView.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@@ -12,6 +12,13 @@
|
|||||||
BeerService::BeerService()
|
BeerService::BeerService()
|
||||||
: QObject{nullptr}
|
: QObject{nullptr}
|
||||||
{
|
{
|
||||||
|
m_actions = {
|
||||||
|
{ ActionGet, "get" },
|
||||||
|
{ ActionAdd, "add" },
|
||||||
|
{ ActionDelete, "del" },
|
||||||
|
{ ActionModify, "mod" }
|
||||||
|
};
|
||||||
|
|
||||||
restoreStash();
|
restoreStash();
|
||||||
|
|
||||||
connect(&m_socket, &QWebSocket::textMessageReceived, this, [this](QString message) {
|
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();
|
qInfo() << error << m_socket.errorString();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -60,11 +67,13 @@ SettingsService *BeerService::settings() const
|
|||||||
return SettingsService::instance();
|
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 {
|
sendCommand(QVariantMap {
|
||||||
{ "entity", entity },
|
{ "entity", entity },
|
||||||
{ "action", action },
|
{ "action", m_actions[action] },
|
||||||
{ "data", data }
|
{ "data", data }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -75,6 +84,12 @@ void BeerService::connectListener(QObject *listener)
|
|||||||
m_listeners.insert(entity, 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
|
QString BeerService::stashFileName() const
|
||||||
{
|
{
|
||||||
return QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/command.stash";
|
return QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/command.stash";
|
||||||
@@ -102,6 +117,7 @@ void BeerService::restoreStash()
|
|||||||
QJsonDocument doc = QJsonDocument::fromJson(stash.readAll());
|
QJsonDocument doc = QJsonDocument::fromJson(stash.readAll());
|
||||||
m_commandStash = doc.array().toVariantList();
|
m_commandStash = doc.array().toVariantList();
|
||||||
stash.close();
|
stash.close();
|
||||||
|
stash.remove();
|
||||||
} else {
|
} else {
|
||||||
qWarning() << stash.errorString();
|
qWarning() << stash.errorString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,18 @@ public:
|
|||||||
return &i;
|
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 connectListener(QObject *listener);
|
||||||
|
void removeListener(QObject *listener);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void connectedChanged();
|
void connectedChanged();
|
||||||
@@ -42,6 +52,7 @@ private:
|
|||||||
|
|
||||||
QWebSocket m_socket;
|
QWebSocket m_socket;
|
||||||
QVariantList m_commandStash;
|
QVariantList m_commandStash;
|
||||||
|
QMap<Action, QString> m_actions;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BEERSERVICE_H
|
#endif // BEERSERVICE_H
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace Keys {
|
|||||||
|
|
||||||
constexpr auto ServerAddress = "server_address";
|
constexpr auto ServerAddress = "server_address";
|
||||||
constexpr auto SelectedUser = "selected_user";
|
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
|
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)
|
void SettingsService::setServerAddress(const QString &address)
|
||||||
{
|
{
|
||||||
m_settings.setValue(Keys::ServerAddress, address);
|
if (serverAddress() == address) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue(Keys::ServerAddress, address);
|
||||||
emit serverAddressChanged();
|
emit serverAddressChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SettingsService::selectedUserId() const
|
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)
|
void SettingsService::setSelectedUserId(const QString &userId)
|
||||||
{
|
{
|
||||||
m_settings.setValue(Keys::SelectedUser, userId);
|
if (selectedUserId() == userId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue(Keys::SelectedUser, userId);
|
||||||
emit selectedUserIdChanged();
|
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 serverAddress READ serverAddress WRITE setServerAddress NOTIFY serverAddressChanged)
|
||||||
Q_PROPERTY(QString selectedUserId READ selectedUserId WRITE setSelectedUserId NOTIFY selectedUserIdChanged)
|
Q_PROPERTY(QString selectedUserId READ selectedUserId WRITE setSelectedUserId NOTIFY selectedUserIdChanged)
|
||||||
|
Q_PROPERTY(QString selectedStoreId READ selectedStoreId WRITE setSelectedStoreId NOTIFY selectedStoreIdChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static SettingsService *instance()
|
static SettingsService *instance()
|
||||||
@@ -18,20 +19,24 @@ public:
|
|||||||
return &i;
|
return &i;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
|
|
||||||
void setValue(const QString &key, const QVariant &value);
|
|
||||||
|
|
||||||
QString serverAddress() const;
|
QString serverAddress() const;
|
||||||
void setServerAddress(const QString &address);
|
void setServerAddress(const QString &address);
|
||||||
|
|
||||||
QString selectedUserId() const;
|
QString selectedUserId() const;
|
||||||
void setSelectedUserId(const QString &userId);
|
void setSelectedUserId(const QString &userId);
|
||||||
|
|
||||||
|
QString selectedStoreId() const;
|
||||||
|
void setSelectedStoreId(const QString &storeId);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void serverAddressChanged();
|
void serverAddressChanged();
|
||||||
void selectedUserIdChanged();
|
void selectedUserIdChanged();
|
||||||
|
void selectedStoreIdChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QVariant value(const QString &key, const QVariant &defaultValue = QVariant{}) const;
|
||||||
|
void setValue(const QString &key, const QVariant &value);
|
||||||
|
|
||||||
SettingsService() = default;
|
SettingsService() = default;
|
||||||
~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)
|
UsersViewModel::UsersViewModel(QObject *parent)
|
||||||
: QObject{parent}
|
: QObject{parent}
|
||||||
{
|
{
|
||||||
connect(&m_usersModel, &AbstractModel::dataChanged, this, &UsersViewModel::usersChanged);
|
connect(&m_usersModel, &BaseModel::dataChanged, this, &UsersViewModel::usersChanged);
|
||||||
connect(&m_usersModel, &AbstractModel::dataChanged, this, &UsersViewModel::selectedUserNameChanged);
|
connect(&m_usersModel, &BaseModel::dataChanged, this, &UsersViewModel::selectedUserNameChanged);
|
||||||
|
|
||||||
connect(settings(), &SettingsService::selectedUserIdChanged, this, &UsersViewModel::selectedUserChanged);
|
connect(settings(), &SettingsService::selectedUserIdChanged, this, &UsersViewModel::selectedUserChanged);
|
||||||
connect(settings(), &SettingsService::selectedUserIdChanged, this, &UsersViewModel::selectedUserNameChanged);
|
connect(settings(), &SettingsService::selectedUserIdChanged, this, &UsersViewModel::selectedUserNameChanged);
|
||||||
@@ -24,16 +24,12 @@ QString UsersViewModel::selectedUser() const
|
|||||||
|
|
||||||
void UsersViewModel::setSelectedUser(const QString &newSelectedUser)
|
void UsersViewModel::setSelectedUser(const QString &newSelectedUser)
|
||||||
{
|
{
|
||||||
if (selectedUser() == newSelectedUser) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
settings()->setSelectedUserId(newSelectedUser);
|
settings()->setSelectedUserId(newSelectedUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString UsersViewModel::selectedUserName() const
|
QString UsersViewModel::selectedUserName() const
|
||||||
{
|
{
|
||||||
return m_usersModel.userName(selectedUser());
|
return m_usersModel.itemProperty(selectedUser(), "name").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsService *UsersViewModel::settings() const
|
SettingsService *UsersViewModel::settings() const
|
||||||
|
|||||||
Reference in New Issue
Block a user