summaryrefslogtreecommitdiffstats
path: root/common/modelresult.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/modelresult.cpp')
-rw-r--r--common/modelresult.cpp119
1 files changed, 107 insertions, 12 deletions
diff --git a/common/modelresult.cpp b/common/modelresult.cpp
index f935419..b12216b 100644
--- a/common/modelresult.cpp
+++ b/common/modelresult.cpp
@@ -24,12 +24,20 @@
24#include <QPointer> 24#include <QPointer>
25 25
26#include "log.h" 26#include "log.h"
27#include "notifier.h"
28#include "notification.h"
29
30using namespace Sink;
31
32static uint getInternalIdentifer(const QByteArray &resourceId, const QByteArray &entityId)
33{
34 return qHash(resourceId + entityId);
35}
27 36
28static uint qHash(const Sink::ApplicationDomain::ApplicationDomainType &type) 37static uint qHash(const Sink::ApplicationDomain::ApplicationDomainType &type)
29{ 38{
30 // Q_ASSERT(!type.resourceInstanceIdentifier().isEmpty());
31 Q_ASSERT(!type.identifier().isEmpty()); 39 Q_ASSERT(!type.identifier().isEmpty());
32 return qHash(type.resourceInstanceIdentifier() + type.identifier()); 40 return getInternalIdentifer(type.resourceInstanceIdentifier(), type.identifier());
33} 41}
34 42
35static qint64 getIdentifier(const QModelIndex &idx) 43static qint64 getIdentifier(const QModelIndex &idx)
@@ -44,6 +52,86 @@ template <class T, class Ptr>
44ModelResult<T, Ptr>::ModelResult(const Sink::Query &query, const QList<QByteArray> &propertyColumns, const Sink::Log::Context &ctx) 52ModelResult<T, Ptr>::ModelResult(const Sink::Query &query, const QList<QByteArray> &propertyColumns, const Sink::Log::Context &ctx)
45 : QAbstractItemModel(), mLogCtx(ctx.subContext("modelresult")), mPropertyColumns(propertyColumns), mQuery(query) 53 : QAbstractItemModel(), mLogCtx(ctx.subContext("modelresult")), mPropertyColumns(propertyColumns), mQuery(query)
46{ 54{
55 if (query.flags().testFlag(Sink::Query::UpdateStatus)) {
56 Sink::Query resourceQuery;
57 resourceQuery.setFilter(query.getResourceFilter());
58 mNotifier.reset(new Sink::Notifier{resourceQuery});
59 mNotifier->registerHandler([this](const Notification &notification) {
60 switch (notification.type) {
61 case Notification::Status:
62 case Notification::Warning:
63 case Notification::Error:
64 case Notification::Info:
65 case Notification::Progress:
66 //These are the notifications we care about
67 break;
68 default:
69 //We're not interested
70 return;
71 };
72 if (notification.resource.isEmpty() || notification.entities.isEmpty()) {
73 return;
74 }
75
76 QVector<qint64> idList;
77 for (const auto &entity : notification.entities) {
78 auto id = getInternalIdentifer(notification.resource, entity);
79 if (mEntities.contains(id)) {
80 idList << id;
81 }
82 }
83
84 if (idList.isEmpty()) {
85 //We don't have this entity in our model
86 return;
87 }
88 const int newStatus = [&] {
89 if (notification.type == Notification::Warning || notification.type == Notification::Error) {
90 return ApplicationDomain::SyncStatus::SyncError;
91 }
92 if (notification.type == Notification::Info) {
93 switch (notification.code) {
94 case ApplicationDomain::SyncInProgress:
95 return ApplicationDomain::SyncInProgress;
96 case ApplicationDomain::SyncSuccess:
97 return ApplicationDomain::SyncSuccess;
98 case ApplicationDomain::SyncError:
99 return ApplicationDomain::SyncError;
100 case ApplicationDomain::NoSyncStatus:
101 break;
102 }
103 return ApplicationDomain::NoSyncStatus;
104 }
105 if (notification.type == Notification::Progress) {
106 return ApplicationDomain::SyncStatus::SyncInProgress;
107 }
108 return ApplicationDomain::NoSyncStatus;
109 }();
110
111 for (const auto id : idList) {
112 const auto oldStatus = mEntityStatus.value(id);
113 QVector<int> changedRoles;
114 if (oldStatus != newStatus) {
115 SinkTraceCtx(mLogCtx) << "Status changed for entity:" << newStatus << ", id: " << id;
116 mEntityStatus.insert(id, newStatus);
117 changedRoles << StatusRole;
118 }
119
120 if (notification.type == Notification::Progress) {
121 changedRoles << ProgressRole;
122 } else if (notification.type == Notification::Warning || notification.type == Notification::Error) {
123 changedRoles << WarningRole;
124 }
125
126 if (!changedRoles.isEmpty()) {
127 const auto idx = createIndexFromId(id);
128 SinkTraceCtx(mLogCtx) << "Index changed:" << idx << changedRoles;
129 //We don't emit the changedRoles because the consuming model likely remaps the role anyways and would then need to translate dataChanged signals as well.
130 emit dataChanged(idx, idx);
131 }
132 }
133 });
134 }
47} 135}
48 136
49template <class T, class Ptr> 137template <class T, class Ptr>
@@ -60,7 +148,7 @@ qint64 ModelResult<T, Ptr>::parentId(const Ptr &value)
60 if (!mQuery.parentProperty().isEmpty()) { 148 if (!mQuery.parentProperty().isEmpty()) {
61 const auto identifier = value->getProperty(mQuery.parentProperty()).toByteArray(); 149 const auto identifier = value->getProperty(mQuery.parentProperty()).toByteArray();
62 if (!identifier.isEmpty()) { 150 if (!identifier.isEmpty()) {
63 return qHash(T(value->resourceInstanceIdentifier(), identifier, 0, QSharedPointer<Sink::ApplicationDomain::BufferAdaptor>())); 151 return getInternalIdentifer(value->resourceInstanceIdentifier(), identifier);
64 } 152 }
65 } 153 }
66 return 0; 154 return 0;
@@ -106,6 +194,13 @@ QVariant ModelResult<T, Ptr>::data(const QModelIndex &index, int role) const
106 if (role == ChildrenFetchedRole) { 194 if (role == ChildrenFetchedRole) {
107 return childrenFetched(index); 195 return childrenFetched(index);
108 } 196 }
197 if (role == StatusRole) {
198 auto it = mEntityStatus.constFind(index.internalId());
199 if (it != mEntityStatus.constEnd()) {
200 return *it;
201 }
202 return {};
203 }
109 if (role == Qt::DisplayRole && index.isValid()) { 204 if (role == Qt::DisplayRole && index.isValid()) {
110 if (index.column() < mPropertyColumns.size()) { 205 if (index.column() < mPropertyColumns.size()) {
111 Q_ASSERT(mEntities.contains(index.internalId())); 206 Q_ASSERT(mEntities.contains(index.internalId()));
@@ -296,15 +391,15 @@ void ModelResult<T, Ptr>::setEmitter(const typename Sink::ResultEmitter<Ptr>::Pt
296 emitter->onInitialResultSetComplete([this, guard](const Ptr &parent, bool fetchedAll) { 391 emitter->onInitialResultSetComplete([this, guard](const Ptr &parent, bool fetchedAll) {
297 SinkTraceCtx(mLogCtx) << "Initial result set complete. Fetched all: " << fetchedAll; 392 SinkTraceCtx(mLogCtx) << "Initial result set complete. Fetched all: " << fetchedAll;
298 Q_ASSERT(guard); 393 Q_ASSERT(guard);
299 threadBoundary.callInMainThread([=]() { 394 Q_ASSERT(QThread::currentThread() == this->thread());
300 const qint64 parentId = parent ? qHash(*parent) : 0; 395
301 const auto parentIndex = createIndexFromId(parentId); 396 const qint64 parentId = parent ? qHash(*parent) : 0;
302 mEntityChildrenFetchComplete.insert(parentId); 397 const auto parentIndex = createIndexFromId(parentId);
303 if (fetchedAll) { 398 mEntityChildrenFetchComplete.insert(parentId);
304 mEntityAllChildrenFetched.insert(parentId); 399 if (fetchedAll) {
305 } 400 mEntityAllChildrenFetched.insert(parentId);
306 emit dataChanged(parentIndex, parentIndex, QVector<int>() << ChildrenFetchedRole); 401 }
307 }); 402 emit dataChanged(parentIndex, parentIndex, QVector<int>() << ChildrenFetchedRole);
308 }); 403 });
309 mEmitter = emitter; 404 mEmitter = emitter;
310} 405}