diff options
author | Minijackson <minijackson@riseup.net> | 2018-04-16 10:09:30 +0200 |
---|---|---|
committer | Minijackson <minijackson@riseup.net> | 2018-04-16 10:18:33 +0200 |
commit | 6a9ff4ac53f7c60902b851f4635ee4bf6ff2d024 (patch) | |
tree | 2619c6c3460e60929062d33d4e57099cf5e3182d /framework/src/domain/perioddayeventmodel.cpp | |
parent | cabc867b3e7cbf56ac2d8f646c52deb59a3197f4 (diff) | |
download | kube-6a9ff4ac53f7c60902b851f4635ee4bf6ff2d024.tar.gz kube-6a9ff4ac53f7c60902b851f4635ee4bf6ff2d024.zip |
Rename EventTreeModel -> PeriodDayEventModel + doc the model architecture
Diffstat (limited to 'framework/src/domain/perioddayeventmodel.cpp')
-rw-r--r-- | framework/src/domain/perioddayeventmodel.cpp | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/framework/src/domain/perioddayeventmodel.cpp b/framework/src/domain/perioddayeventmodel.cpp new file mode 100644 index 00000000..0b374d5c --- /dev/null +++ b/framework/src/domain/perioddayeventmodel.cpp | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | Copyright (c) 2018 Michael Bohlender <michael.bohlender@kdemail.net> | ||
3 | Copyright (c) 2018 Christian Mollekopf <mollekopf@kolabsys.com> | ||
4 | Copyright (c) 2018 Rémi Nicole <minijackson@riseup.net> | ||
5 | |||
6 | This library is free software; you can redistribute it and/or modify it | ||
7 | under the terms of the GNU Library General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or (at your | ||
9 | option) any later version. | ||
10 | |||
11 | This library is distributed in the hope that it will be useful, but WITHOUT | ||
12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public | ||
14 | License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU Library General Public License | ||
17 | along with this library; see the file COPYING.LIB. If not, write to the | ||
18 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
19 | 02110-1301, USA. | ||
20 | */ | ||
21 | |||
22 | #include "perioddayeventmodel.h" | ||
23 | |||
24 | #include <sink/log.h> | ||
25 | #include <sink/query.h> | ||
26 | #include <sink/store.h> | ||
27 | |||
28 | #include <QJsonArray> | ||
29 | #include <QJsonObject> | ||
30 | #include <QMetaEnum> | ||
31 | |||
32 | PeriodDayEventModel::PeriodDayEventModel(QObject *parent) : QAbstractItemModel(parent), partitionedEvents(7) | ||
33 | { | ||
34 | Sink::Query query; | ||
35 | query.setFlags(Sink::Query::LiveQuery); | ||
36 | query.request<Event::Summary>(); | ||
37 | query.request<Event::Description>(); | ||
38 | query.request<Event::StartTime>(); | ||
39 | query.request<Event::EndTime>(); | ||
40 | |||
41 | eventModel = Sink::Store::loadModel<Event>(query); | ||
42 | |||
43 | QObject::connect(eventModel.data(), &QAbstractItemModel::dataChanged, this, &PeriodDayEventModel::partitionData); | ||
44 | QObject::connect(eventModel.data(), &QAbstractItemModel::layoutChanged, this, &PeriodDayEventModel::partitionData); | ||
45 | QObject::connect(eventModel.data(), &QAbstractItemModel::modelReset, this, &PeriodDayEventModel::partitionData); | ||
46 | QObject::connect(eventModel.data(), &QAbstractItemModel::rowsInserted, this, &PeriodDayEventModel::partitionData); | ||
47 | QObject::connect(eventModel.data(), &QAbstractItemModel::rowsMoved, this, &PeriodDayEventModel::partitionData); | ||
48 | QObject::connect(eventModel.data(), &QAbstractItemModel::rowsRemoved, this, &PeriodDayEventModel::partitionData); | ||
49 | |||
50 | partitionData(); | ||
51 | } | ||
52 | |||
53 | void PeriodDayEventModel::partitionData() | ||
54 | { | ||
55 | SinkLog() << "Partitioning event data"; | ||
56 | |||
57 | beginResetModel(); | ||
58 | |||
59 | partitionedEvents = QVector<QList<QSharedPointer<Event>>>(mViewLength); | ||
60 | |||
61 | for (int i = 0; i < eventModel->rowCount(); ++i) { | ||
62 | auto event = eventModel->index(i, 0).data(Sink::Store::DomainObjectRole).value<Event::Ptr>(); | ||
63 | QDate eventDate = event->getStartTime().date(); | ||
64 | |||
65 | if(!eventDate.isValid()) { | ||
66 | SinkWarning() << "Invalid date in the eventModel, ignoring..."; | ||
67 | continue; | ||
68 | } | ||
69 | |||
70 | int bucket = bucketOf(eventDate); | ||
71 | |||
72 | if(bucket >= 0) { | ||
73 | SinkTrace() << "Adding event:" << event->getSummary() << "in bucket #" << bucket; | ||
74 | partitionedEvents[bucket].append(event); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | endResetModel(); | ||
79 | } | ||
80 | |||
81 | int PeriodDayEventModel::bucketOf(QDate const &candidate) const | ||
82 | { | ||
83 | int bucket = mViewStart.daysTo(candidate); | ||
84 | if(bucket >= mViewLength || bucket < 0) { | ||
85 | return -1; | ||
86 | } | ||
87 | |||
88 | return bucket; | ||
89 | } | ||
90 | |||
91 | QModelIndex PeriodDayEventModel::index(int row, int column, const QModelIndex &parent) const | ||
92 | { | ||
93 | if (!hasIndex(row, column, parent)) { | ||
94 | return {}; | ||
95 | } | ||
96 | |||
97 | if (!parent.isValid()) { | ||
98 | // Asking for a day | ||
99 | |||
100 | if (!(0 <= row && row < mViewLength)) { | ||
101 | return {}; | ||
102 | } | ||
103 | |||
104 | return createIndex(row, column, DAY_ID); | ||
105 | } | ||
106 | |||
107 | // Asking for an Event | ||
108 | auto day = static_cast<int>(parent.row()); | ||
109 | |||
110 | Q_ASSERT(0 <= day && day <= mViewLength); | ||
111 | if (row >= partitionedEvents[day].size()) { | ||
112 | return {}; | ||
113 | } | ||
114 | |||
115 | return createIndex(row, column, day); | ||
116 | } | ||
117 | |||
118 | QModelIndex PeriodDayEventModel::parent(const QModelIndex &index) const | ||
119 | { | ||
120 | if (!index.isValid()) { | ||
121 | return {}; | ||
122 | } | ||
123 | |||
124 | if (index.internalId() == DAY_ID) { | ||
125 | return {}; | ||
126 | } | ||
127 | |||
128 | auto day = index.internalId(); | ||
129 | |||
130 | return this->index(day, 0); | ||
131 | } | ||
132 | |||
133 | int PeriodDayEventModel::rowCount(const QModelIndex &parent) const | ||
134 | { | ||
135 | if (!parent.isValid()) { | ||
136 | return mViewLength; | ||
137 | } | ||
138 | |||
139 | auto day = parent.row(); | ||
140 | |||
141 | return partitionedEvents[day].size(); | ||
142 | } | ||
143 | |||
144 | int PeriodDayEventModel::columnCount(const QModelIndex &parent) const | ||
145 | { | ||
146 | if (!parent.isValid()) { | ||
147 | return 1; | ||
148 | } | ||
149 | |||
150 | return eventModel->columnCount(); | ||
151 | } | ||
152 | |||
153 | QVariant PeriodDayEventModel::data(const QModelIndex &id, int role) const | ||
154 | { | ||
155 | if (id.internalId() == DAY_ID) { | ||
156 | auto day = id.row(); | ||
157 | |||
158 | SinkTrace() << "Fetching data for day" << day << "with role" | ||
159 | << QMetaEnum::fromType<Roles>().valueToKey(role); | ||
160 | |||
161 | switch (role) { | ||
162 | case Qt::DisplayRole: | ||
163 | return mViewStart.addDays(day).toString(); | ||
164 | case Events: { | ||
165 | auto result = QVariantList{}; | ||
166 | |||
167 | for (int i = 0; i < partitionedEvents[day].size(); ++i) { | ||
168 | auto eventId = index(i, 0, id); | ||
169 | SinkTrace() << "Appending event:" << data(eventId, Summary); | ||
170 | |||
171 | auto startTime = data(eventId, StartTime).toDateTime().time(); | ||
172 | |||
173 | result.append(QVariantMap{ | ||
174 | {"text", data(eventId, Summary)}, | ||
175 | {"description", data(eventId, Description)}, | ||
176 | {"starts", startTime.hour() + startTime.minute() / 60.}, | ||
177 | {"duration", data(eventId, Duration)}, | ||
178 | {"color", "#134bab"}, | ||
179 | {"indention", 0}, | ||
180 | }); | ||
181 | } | ||
182 | |||
183 | return result; | ||
184 | } | ||
185 | default: | ||
186 | SinkWarning() << "Unknown role for day:" << QMetaEnum::fromType<Roles>().valueToKey(role); | ||
187 | return {}; | ||
188 | } | ||
189 | } else { | ||
190 | auto day = id.internalId(); | ||
191 | SinkTrace() << "Fetching data for event on day" << day << "with role" | ||
192 | << QMetaEnum::fromType<Roles>().valueToKey(role); | ||
193 | auto event = partitionedEvents[day].at(id.row()); | ||
194 | |||
195 | switch (role) { | ||
196 | case Summary: | ||
197 | return event->getSummary(); | ||
198 | case Description: | ||
199 | return event->getDescription(); | ||
200 | case StartTime: | ||
201 | return event->getStartTime(); | ||
202 | case Duration: { | ||
203 | auto start = event->getStartTime(); | ||
204 | auto end = event->getEndTime(); | ||
205 | return start.secsTo(end) / 3600; | ||
206 | } | ||
207 | default: | ||
208 | SinkWarning() << "Unknown role for event:" << QMetaEnum::fromType<Roles>().valueToKey(role); | ||
209 | return {}; | ||
210 | } | ||
211 | } | ||
212 | } | ||
213 | |||
214 | QHash<int, QByteArray> PeriodDayEventModel::roleNames() const | ||
215 | { | ||
216 | QHash<int, QByteArray> roles; | ||
217 | |||
218 | roles[Events] = "events"; | ||
219 | roles[Summary] = "summary"; | ||
220 | roles[Description] = "description"; | ||
221 | roles[StartTime] = "starts"; | ||
222 | roles[Duration] = "duration"; | ||
223 | |||
224 | return roles; | ||
225 | } | ||
226 | |||
227 | QDate PeriodDayEventModel::viewStart() const | ||
228 | { | ||
229 | return mViewStart; | ||
230 | } | ||
231 | |||
232 | void PeriodDayEventModel::setViewStart(QDate start) | ||
233 | { | ||
234 | if (!start.isValid()) { | ||
235 | SinkWarning() << "Passed an invalid starting date in setViewStart, ignoring..."; | ||
236 | return; | ||
237 | } | ||
238 | |||
239 | mViewStart = std::move(start); | ||
240 | partitionData(); | ||
241 | } | ||
242 | |||
243 | void PeriodDayEventModel::setViewStart(QVariant start) | ||
244 | { | ||
245 | setViewStart(start.toDate()); | ||
246 | } | ||
247 | |||
248 | int PeriodDayEventModel::viewLength() const | ||
249 | { | ||
250 | return mViewLength; | ||
251 | } | ||
252 | |||
253 | void PeriodDayEventModel::setViewLength(int length) | ||
254 | { | ||
255 | mViewLength = std::move(length); | ||
256 | partitionData(); | ||
257 | } | ||