diff options
Diffstat (limited to 'common/modelresult.cpp')
-rw-r--r-- | common/modelresult.cpp | 119 |
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 | |||
30 | using namespace Sink; | ||
31 | |||
32 | static uint getInternalIdentifer(const QByteArray &resourceId, const QByteArray &entityId) | ||
33 | { | ||
34 | return qHash(resourceId + entityId); | ||
35 | } | ||
27 | 36 | ||
28 | static uint qHash(const Sink::ApplicationDomain::ApplicationDomainType &type) | 37 | static 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 | ||
35 | static qint64 getIdentifier(const QModelIndex &idx) | 43 | static qint64 getIdentifier(const QModelIndex &idx) |
@@ -44,6 +52,86 @@ template <class T, class Ptr> | |||
44 | ModelResult<T, Ptr>::ModelResult(const Sink::Query &query, const QList<QByteArray> &propertyColumns, const Sink::Log::Context &ctx) | 52 | ModelResult<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 ¬ification) { | ||
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 | ||
49 | template <class T, class Ptr> | 137 | template <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 | } |