diff --git a/ui/StatusQ/CMakeLists.txt b/ui/StatusQ/CMakeLists.txt index afd3d50599..15765a76e4 100644 --- a/ui/StatusQ/CMakeLists.txt +++ b/ui/StatusQ/CMakeLists.txt @@ -102,6 +102,7 @@ add_library(StatusQ SHARED include/StatusQ/functionaggregator.h include/StatusQ/groupingmodel.h include/StatusQ/leftjoinmodel.h + include/StatusQ/modelcount.h include/StatusQ/modelentry.h include/StatusQ/modelsyncedcontainer.h include/StatusQ/modelutilsinternal.h @@ -130,6 +131,7 @@ add_library(StatusQ SHARED src/functionaggregator.cpp src/groupingmodel.cpp src/leftjoinmodel.cpp + src/modelcount.cpp src/modelentry.cpp src/modelutilsinternal.cpp src/movablemodel.cpp diff --git a/ui/StatusQ/include/StatusQ/modelcount.h b/ui/StatusQ/include/StatusQ/modelcount.h new file mode 100644 index 0000000000..8f0e719e27 --- /dev/null +++ b/ui/StatusQ/include/StatusQ/modelcount.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +class QAbstractItemModel; + +class ModelCount : public QObject { + Q_OBJECT + Q_PROPERTY(int count READ count NOTIFY countChanged) + +public: + explicit ModelCount(QObject* parent = nullptr); + + static ModelCount* qmlAttachedProperties(QObject* object); + + int count() const; + +signals: + void countChanged(); + +private: + int m_intermediateCount = 0; +}; + +QML_DECLARE_TYPEINFO(ModelCount, QML_HAS_ATTACHED_PROPERTIES) diff --git a/ui/StatusQ/src/modelcount.cpp b/ui/StatusQ/src/modelcount.cpp new file mode 100644 index 0000000000..fcb16dd083 --- /dev/null +++ b/ui/StatusQ/src/modelcount.cpp @@ -0,0 +1,44 @@ +#include "StatusQ/modelcount.h" + +#include + +ModelCount::ModelCount(QObject* parent) : QObject(parent) +{ + auto model = qobject_cast(parent); + + if (model == nullptr) + return; + + connect(model, &QAbstractItemModel::rowsInserted, + this, &ModelCount::countChanged); + connect(model, &QAbstractItemModel::rowsRemoved, + this, &ModelCount::countChanged); + + auto storeIntermediateCount = [this, model] { + this->m_intermediateCount = model->rowCount(); + }; + + auto emitIfChanged = [this, model] { + if (this->m_intermediateCount != model->rowCount()) + emit this->countChanged(); + }; + + connect(model, &QAbstractItemModel::modelAboutToBeReset, this, storeIntermediateCount); + connect(model, &QAbstractItemModel::layoutAboutToBeChanged, storeIntermediateCount); + + connect(model, &QAbstractItemModel::modelReset, this, emitIfChanged); + connect(model, &QAbstractItemModel::layoutChanged, this, emitIfChanged); +} + +ModelCount* ModelCount::qmlAttachedProperties(QObject* object) +{ + return new ModelCount(object); +} + +int ModelCount::count() const +{ + if (auto model = qobject_cast(parent())) + return model->rowCount(); + + return 0; +} diff --git a/ui/StatusQ/src/plugin.cpp b/ui/StatusQ/src/plugin.cpp index cf7b7c08af..d6d314fe08 100644 --- a/ui/StatusQ/src/plugin.cpp +++ b/ui/StatusQ/src/plugin.cpp @@ -12,6 +12,7 @@ #include "StatusQ/functionaggregator.h" #include "StatusQ/groupingmodel.h" #include "StatusQ/leftjoinmodel.h" +#include "StatusQ/modelcount.h" #include "StatusQ/modelentry.h" #include "StatusQ/modelutilsinternal.h" #include "StatusQ/movablemodel.h" @@ -71,6 +72,9 @@ public: qmlRegisterType("StatusQ", 0, 1, "ModelEntry"); qmlRegisterType("StatusQ", 0, 1, "SnapshotObject"); + qmlRegisterUncreatableType("StatusQ", 0, 1, + "ModelCount", "This is attached type, cannot be created directly."); + qmlRegisterSingletonType( "StatusQ.Internal", 0, 1, "ModelUtils", &ModelUtilsInternal::qmlInstance); diff --git a/ui/StatusQ/tests/CMakeLists.txt b/ui/StatusQ/tests/CMakeLists.txt index 9c246597d7..2fadd9da63 100644 --- a/ui/StatusQ/tests/CMakeLists.txt +++ b/ui/StatusQ/tests/CMakeLists.txt @@ -115,3 +115,7 @@ add_test(NAME SnapshotObjectTest COMMAND SnapshotObjectTest) add_executable(GroupingModelTest tst_GroupingModel.cpp) target_link_libraries(GroupingModelTest PRIVATE Qt5::Qml StatusQ StatusQTestLib) add_test(NAME GroupingModelTest COMMAND GroupingModelTest) + +add_executable(ModelCountTest tst_ModelCount.cpp) +target_link_libraries(ModelCountTest PRIVATE StatusQ StatusQTestLib) +add_test(NAME ModelCountTest COMMAND ModelCountTest) diff --git a/ui/StatusQ/tests/tst_ModelCount.cpp b/ui/StatusQ/tests/tst_ModelCount.cpp new file mode 100644 index 0000000000..b3e09b8740 --- /dev/null +++ b/ui/StatusQ/tests/tst_ModelCount.cpp @@ -0,0 +1,63 @@ +#include + +#include + +#include + + +class TestModelCount : public QObject +{ + Q_OBJECT + +private slots: + void modelCountTest() + { + TestModel model({ + { "name", { "a", "b", "c", "d" }} + }); + + ModelCount modelCount(&model); + + QCOMPARE(modelCount.count(), 4); + + QSignalSpy spy(&modelCount, &ModelCount::countChanged); + + model.insert(1, { "e" }); + + QCOMPARE(spy.count(), 1); + QCOMPARE(modelCount.count(), 5); + + model.remove(0); + + QCOMPARE(spy.count(), 2); + QCOMPARE(modelCount.count(), 4); + + model.update(0, 0, "aa"); + + QCOMPARE(spy.count(), 2); + QCOMPARE(modelCount.count(), 4); + + model.invert(); + + QCOMPARE(spy.count(), 2); + QCOMPARE(modelCount.count(), 4); + + model.removeEverySecond(); + + QCOMPARE(spy.count(), 3); + QCOMPARE(modelCount.count(), 2); + + model.reset(); + + QCOMPARE(spy.count(), 3); + QCOMPARE(modelCount.count(), 2); + + model.resetAndClear(); + + QCOMPARE(spy.count(), 4); + QCOMPARE(modelCount.count(), 0); + } +}; + +QTEST_MAIN(TestModelCount) +#include "tst_ModelCount.moc"