From 4ed4ecd42995b9d6ba7ff94b9a04f9e3c668ee60 Mon Sep 17 00:00:00 2001 From: "Denis V. Dedkov" Date: Tue, 11 Apr 2023 09:42:27 +0200 Subject: [PATCH] Models registry was added --- CMakeLists.txt | 2 +- main.cpp | 5 +++ models/ordersmodel.cpp | 15 ------- models/ordersmodel.h | 17 -------- qml/Views/SettingsView.qml | 26 +++++++----- services/modelsregister.cpp | 23 +++++++++++ services/modelsregister.h | 28 +++++++++++++ viewmodels/ordersviewmodel.cpp | 20 +++++----- viewmodels/ordersviewmodel.h | 11 +++--- viewmodels/productsviewmodel.cpp | 16 ++++---- viewmodels/productsviewmodel.h | 5 ++- viewmodels/settingsviewmodel.cpp | 68 ++++++++++++++++++++++++++++---- viewmodels/settingsviewmodel.h | 12 ++++-- viewmodels/storesviewmodel.cpp | 9 +++-- viewmodels/storesviewmodel.h | 4 +- viewmodels/usersviewmodel.cpp | 9 +++-- viewmodels/usersviewmodel.h | 4 +- 17 files changed, 183 insertions(+), 91 deletions(-) delete mode 100644 models/ordersmodel.cpp delete mode 100644 models/ordersmodel.h create mode 100644 services/modelsregister.cpp create mode 100644 services/modelsregister.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ead4efc..a795345 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,6 @@ set(PROJECT_SOURCES main.cpp qml/qml.qrc 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 @@ -27,6 +26,7 @@ set(PROJECT_SOURCES viewmodels/settingsviewmodel.h viewmodels/settingsviewmodel.cpp services/beerservice.h services/beerservice.cpp services/settingsservice.h services/settingsservice.cpp + services/modelsregister.h services/modelsregister.cpp ${TS_FILES} ) diff --git a/main.cpp b/main.cpp index 1e2b52e..e576729 100644 --- a/main.cpp +++ b/main.cpp @@ -5,6 +5,8 @@ #include #include +#include "models/usersmodel.h" + #include "viewmodels/usersviewmodel.h" #include "viewmodels/productsviewmodel.h" #include "viewmodels/ordersviewmodel.h" @@ -13,6 +15,7 @@ #include "services/beerservice.h" #include "services/settingsservice.h" +#include "services/modelsregister.h" int main(int argc, char *argv[]) { @@ -41,6 +44,8 @@ int main(int argc, char *argv[]) engine.addImportPath("qrc:/"); + ModelsRegister::registerModel(new UsersModel()); + engine.rootContext()->setContextProperty("beerService", BeerService::instance()); engine.rootContext()->setContextProperty("settingsService", SettingsService::instance()); diff --git a/models/ordersmodel.cpp b/models/ordersmodel.cpp deleted file mode 100644 index aa51830..0000000 --- a/models/ordersmodel.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#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); -} diff --git a/models/ordersmodel.h b/models/ordersmodel.h deleted file mode 100644 index 84f26ae..0000000 --- a/models/ordersmodel.h +++ /dev/null @@ -1,17 +0,0 @@ -#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 diff --git a/qml/Views/SettingsView.qml b/qml/Views/SettingsView.qml index 629ea37..19d9855 100644 --- a/qml/Views/SettingsView.qml +++ b/qml/Views/SettingsView.qml @@ -26,13 +26,23 @@ Page { width: parent.width text: model.title - subtitle: settingsService[model.name] + subtitle: model.subtitle || "" + + function valueAccepted() { + model.value = editor.value + } + + function disconnectDialog() { + inputDialog.accepted.disconnect(valueAccepted) + } onClicked: { inputDialog.title = model.title - inputDialog.name = model.name inputDialog.control = controls[model.control] + inputDialog.initialValue = model.value inputDialog.choiceModel = model.choiceModel + inputDialog.accepted.connect(valueAccepted) + inputDialog.closed.connect(disconnectDialog) inputDialog.open() } } @@ -41,8 +51,8 @@ Page { Dialog { id: inputDialog - property string name: "" property var choiceModel: undefined + property var initialValue: undefined property alias control: editor.sourceComponent width: root.width * 0.8 @@ -60,10 +70,6 @@ Page { anchors.fill: parent } - - onAccepted: { - settingsService[inputDialog.name] = editor.value - } } Component { @@ -72,10 +78,10 @@ Page { TextField { id: textField - property alias value: textField.text + property string value: text inputMethodHints: Qt.ImhNoAutoUppercase - text: settingsService[inputDialog.name] || "" + text: inputDialog.initialValue || "" } } @@ -97,7 +103,7 @@ Page { property var valueId: modelData.id text: modelData.name width: parent.width - checked: settingsService[inputDialog.name] === valueId + checked: inputDialog.initialValue === valueId ButtonGroup.group: group } } diff --git a/services/modelsregister.cpp b/services/modelsregister.cpp new file mode 100644 index 0000000..414fb7f --- /dev/null +++ b/services/modelsregister.cpp @@ -0,0 +1,23 @@ +#include "modelsregister.h" + +#include "models/basemodel.h" + +void ModelsRegister::registerModel(BaseModel *model) +{ + Q_ASSERT(model != nullptr); + + model->setParent(&instance()->m_parent); + + instance()->m_models[model->entity()] = model; +} + +BaseModel *ModelsRegister::model(const QString &name) +{ + Q_ASSERT(!name.isEmpty()); + + if (!instance()->m_models.contains(name)) { + registerModel(new BaseModel(name, &instance()->m_parent)); + } + + return instance()->m_models.value(name); +} diff --git a/services/modelsregister.h b/services/modelsregister.h new file mode 100644 index 0000000..3c23dcc --- /dev/null +++ b/services/modelsregister.h @@ -0,0 +1,28 @@ +#ifndef MODELSREGISTER_H +#define MODELSREGISTER_H + +#include +#include + +class BaseModel; +class ModelsRegister +{ +public: + static ModelsRegister *instance() + { + static ModelsRegister i; + return &i; + } + + static void registerModel(BaseModel *model); + static BaseModel *model(const QString &name); + +private: + ModelsRegister() = default; + ~ModelsRegister() = default; + + QObject m_parent; + QMap m_models; +}; + +#endif // MODELSREGISTER_H diff --git a/viewmodels/ordersviewmodel.cpp b/viewmodels/ordersviewmodel.cpp index aa100bd..1d30fde 100644 --- a/viewmodels/ordersviewmodel.cpp +++ b/viewmodels/ordersviewmodel.cpp @@ -2,13 +2,15 @@ #include +#include "models/basemodel.h" + 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); + 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(); } @@ -45,18 +47,18 @@ void OrdersViewModel::reload() m_model.clear(); - for (const QVariant &vOrder : m_ordersModel.orders()) { + for (const QVariant &vOrder : m_ordersModel->items()) { 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(); + 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"); + product["product"] = m_productsModel->itemProperty(product.value("productId").toString(), "name"); prodModel << product; } order["products"] = prodModel; @@ -64,7 +66,7 @@ void OrdersViewModel::reload() m_model << order; } - std::sort(m_model.begin(), m_model.end(), [](const QVariant &l, const QVariant &r) { + std::sort(m_model.begin(), m_model.end(), [](const QVariant &l, const QVariant &r) -> bool { return l.toMap().value("ts").toDouble() < r.toMap().value("ts").toDouble(); }); diff --git a/viewmodels/ordersviewmodel.h b/viewmodels/ordersviewmodel.h index 0d666ba..e8c9456 100644 --- a/viewmodels/ordersviewmodel.h +++ b/viewmodels/ordersviewmodel.h @@ -3,8 +3,7 @@ #include -#include "models/ordersmodel.h" -#include "models/usersmodel.h" +#include "services/modelsregister.h" class OrdersViewModel : public QAbstractListModel { @@ -32,10 +31,10 @@ private: void reload(); - OrdersModel m_ordersModel; - UsersModel m_usersModel; - BaseModel m_productsModel = BaseModel("products", this); - BaseModel m_storesModel = BaseModel("stores", this); + BaseModel *m_ordersModel = ModelsRegister::model("orders"); + BaseModel *m_usersModel = ModelsRegister::model("users"); + BaseModel *m_productsModel = ModelsRegister::model("products"); + BaseModel *m_storesModel = ModelsRegister::model("stores"); QVariantList m_model; }; diff --git a/viewmodels/productsviewmodel.cpp b/viewmodels/productsviewmodel.cpp index f1c6336..cfb291c 100644 --- a/viewmodels/productsviewmodel.cpp +++ b/viewmodels/productsviewmodel.cpp @@ -1,17 +1,17 @@ #include "productsviewmodel.h" +#include "models/basemodel.h" #include "services/settingsservice.h" -#include "models/ordersmodel.h" ProductsViewModel::ProductsViewModel(QObject *parent) : QObject{parent} { - connect(&m_productsModel, &BaseModel::dataChanged, this, &ProductsViewModel::productsChanged); + connect(m_productsModel, &BaseModel::dataChanged, this, &ProductsViewModel::productsChanged); } QVariantList ProductsViewModel::products() const { - return m_productsModel.items(); + return m_productsModel->items(); } QVariantList ProductsViewModel::order() const @@ -19,7 +19,7 @@ QVariantList ProductsViewModel::order() const QVariantList res; for (auto it = m_order.constBegin(); it != m_order.constEnd(); ++it) { - QVariantMap product = m_productsModel.item(it.key()); + QVariantMap product = m_productsModel->item(it.key()); product["count"] = it.value().toMap().value("quantity").toDouble(); res << product; } @@ -32,7 +32,7 @@ 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()); + 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; @@ -44,7 +44,7 @@ float ProductsViewModel::orderSum() const void ProductsViewModel::setOrderValue(const QString &productId, float value) { if (value) { - float price = m_productsModel.itemProperty(productId, "price", 0.0).toFloat(); + float price = m_productsModel->itemProperty(productId, "price", 0.0).toFloat(); m_order[productId] = QVariantMap { { "productId", productId }, { "quantity", value}, @@ -59,8 +59,8 @@ void ProductsViewModel::setOrderValue(const QString &productId, float value) void ProductsViewModel::submitOrder() { - OrdersModel model; - model.submitOrder(QVariantMap { + BaseModel *ordersModel = ModelsRegister::model("orders"); + ordersModel->addItem({ { "userId", settings()->selectedUserId() }, { "storeId", settings()->selectedStoreId() }, { "products", m_order.values() }, diff --git a/viewmodels/productsviewmodel.h b/viewmodels/productsviewmodel.h index 4e92fbf..b0f8dcb 100644 --- a/viewmodels/productsviewmodel.h +++ b/viewmodels/productsviewmodel.h @@ -2,8 +2,9 @@ #define PRODUCTSVIEWMODEL_H #include +#include -#include "models/basemodel.h" +#include "services/modelsregister.h" class SettingsService; class ProductsViewModel : public QObject @@ -31,7 +32,7 @@ signals: private: SettingsService *settings() const; - BaseModel m_productsModel = BaseModel("products", this); + BaseModel *m_productsModel = ModelsRegister::model("products"); QVariantMap m_order; }; diff --git a/viewmodels/settingsviewmodel.cpp b/viewmodels/settingsviewmodel.cpp index 443f6e4..9fbc7d8 100644 --- a/viewmodels/settingsviewmodel.cpp +++ b/viewmodels/settingsviewmodel.cpp @@ -1,5 +1,10 @@ #include "settingsviewmodel.h" +#include "services/modelsregister.h" +#include "services/settingsservice.h" + +#include "models/basemodel.h" + SettingsViewModel::SettingsViewModel(QObject *parent) : QAbstractListModel{parent} { @@ -7,10 +12,16 @@ SettingsViewModel::SettingsViewModel(QObject *parent) << 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); -} + QModelIndex selectedUserIdIndex = index(1); + QModelIndex selectedStoreIdIndex = index(2); + connect(settings(), &SettingsService::selectedUserIdChanged, this, [this, selectedUserIdIndex]() { + emit dataChanged(selectedUserIdIndex, selectedUserIdIndex); + }); + connect(settings(), &SettingsService::selectedStoreIdChanged, this, [this, selectedStoreIdIndex]() { + emit dataChanged(selectedStoreIdIndex, selectedStoreIdIndex); + }); +} int SettingsViewModel::rowCount(const QModelIndex &) const { @@ -27,7 +38,8 @@ QVariant SettingsViewModel::data(const QModelIndex &index, int role) const switch (role) { case Roles::Title: return item.title; - case Roles::PropertyName: return item.propertyName; + case Roles::Subtitle: return subtitle(item.propertyName, item.modelName); + case Roles::Value: return settings()->property(item.propertyName.toLocal8Bit()); case Roles::ControlType: return item.controlType; case Roles::Model: return model(item.modelName); default: @@ -41,17 +53,59 @@ QHash SettingsViewModel::roleNames() const { return QHash { { Roles::Title, "title" }, - { Roles::PropertyName, "name" }, + { Roles::Subtitle, "subtitle" }, + { Roles::Value, "value" }, { Roles::ControlType, "control" }, { Roles::Model, "choiceModel" } }; } +bool SettingsViewModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid()) { + return false; + } + + if (Roles::Value != role) { + return false; + } + + SettingItem item = m_items.at(index.row()); + bool res = settings()->setProperty(item.propertyName.toLocal8Bit(), value); + if (res) { + emit dataChanged(index, index); + } + + return res; +} + +Qt::ItemFlags SettingsViewModel::flags(const QModelIndex &index) const +{ + return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; +} + +SettingsService *SettingsViewModel::settings() const +{ + return SettingsService::instance(); +} + QVariant SettingsViewModel::model(const QString &modelName) const { - if (!m_models.contains(modelName)) { + BaseModel *model = modelName.isEmpty() ? nullptr : ModelsRegister::model(modelName); + if (!model) { return {}; } - return m_models[modelName]->items(); + return model->items(); +} + +QVariant SettingsViewModel::subtitle(const QString &propertyName, const QString &modelName) const +{ + BaseModel *model = modelName.isEmpty() ? nullptr : ModelsRegister::model(modelName); + QVariant propertyValue = settings()->property(propertyName.toLocal8Bit()); + if (model) { + return model->itemProperty(propertyValue.toString(), "name"); + } + + return propertyValue; } diff --git a/viewmodels/settingsviewmodel.h b/viewmodels/settingsviewmodel.h index c35cf24..b9808c5 100644 --- a/viewmodels/settingsviewmodel.h +++ b/viewmodels/settingsviewmodel.h @@ -3,8 +3,7 @@ #include -#include "models/basemodel.h" - +class SettingsService; class SettingsViewModel : public QAbstractListModel { Q_OBJECT @@ -16,10 +15,14 @@ public: QVariant data(const QModelIndex &index, int role) const override; QHash roleNames() const override; + bool setData(const QModelIndex &index, const QVariant &value, int role) override; + Qt::ItemFlags flags(const QModelIndex &index) const override; + private: enum Roles { Title = Qt::UserRole + 1, - PropertyName, + Subtitle, + Value, ControlType, Model }; @@ -38,10 +41,11 @@ private: modelName(modelName) {} }; + SettingsService *settings() const; QVariant model(const QString &modelName) const; + QVariant subtitle(const QString &propertyName, const QString &modelName) const; QList m_items; - QMap m_models; }; #endif // SETTINGSVIEWMODEL_H diff --git a/viewmodels/storesviewmodel.cpp b/viewmodels/storesviewmodel.cpp index 6d1b23c..4936fb2 100644 --- a/viewmodels/storesviewmodel.cpp +++ b/viewmodels/storesviewmodel.cpp @@ -1,12 +1,13 @@ #include "storesviewmodel.h" +#include "models/basemodel.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(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); @@ -14,7 +15,7 @@ StoresViewModel::StoresViewModel(QObject *parent) QVariantList StoresViewModel::stores() const { - return m_storesModel.items(); + return m_storesModel->items(); } QString StoresViewModel::selectedStore() const @@ -29,7 +30,7 @@ void StoresViewModel::setSelectedStore(const QString &newSelectedStore) QString StoresViewModel::selectedStoreName() const { - return m_storesModel.itemProperty(selectedStore(), "name").toString(); + return m_storesModel->itemProperty(selectedStore(), "name").toString(); } SettingsService *StoresViewModel::settings() const diff --git a/viewmodels/storesviewmodel.h b/viewmodels/storesviewmodel.h index ea77794..db3a3a4 100644 --- a/viewmodels/storesviewmodel.h +++ b/viewmodels/storesviewmodel.h @@ -3,7 +3,7 @@ #include -#include "models/basemodel.h" +#include "services/modelsregister.h" class SettingsService; class StoresViewModel : public QObject @@ -30,7 +30,7 @@ signals: private: SettingsService *settings() const; - BaseModel m_storesModel = BaseModel("stores", this); + BaseModel *m_storesModel = ModelsRegister::model("stores"); }; #endif // STORESVIEWMODEL_H diff --git a/viewmodels/usersviewmodel.cpp b/viewmodels/usersviewmodel.cpp index e26c528..af3547e 100644 --- a/viewmodels/usersviewmodel.cpp +++ b/viewmodels/usersviewmodel.cpp @@ -1,12 +1,13 @@ #include "usersviewmodel.h" +#include "models/basemodel.h" #include "services/settingsservice.h" UsersViewModel::UsersViewModel(QObject *parent) : QObject{parent} { - connect(&m_usersModel, &BaseModel::dataChanged, this, &UsersViewModel::usersChanged); - connect(&m_usersModel, &BaseModel::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); @@ -14,7 +15,7 @@ UsersViewModel::UsersViewModel(QObject *parent) QVariantList UsersViewModel::users() const { - return m_usersModel.users(); + return m_usersModel->items(); } QString UsersViewModel::selectedUser() const @@ -29,7 +30,7 @@ void UsersViewModel::setSelectedUser(const QString &newSelectedUser) QString UsersViewModel::selectedUserName() const { - return m_usersModel.itemProperty(selectedUser(), "name").toString(); + return m_usersModel->itemProperty(selectedUser(), "name").toString(); } SettingsService *UsersViewModel::settings() const diff --git a/viewmodels/usersviewmodel.h b/viewmodels/usersviewmodel.h index d6edded..e1d70e4 100644 --- a/viewmodels/usersviewmodel.h +++ b/viewmodels/usersviewmodel.h @@ -3,7 +3,7 @@ #include -#include "models/usersmodel.h" +#include "services/modelsregister.h" class SettingsService; class UsersViewModel : public QObject @@ -30,7 +30,7 @@ signals: private: SettingsService *settings() const; - UsersModel m_usersModel; + BaseModel *m_usersModel = ModelsRegister::model("users"); }; #endif // USERSVIEWMODEL_H