diff options
author | Rémi Nicole <nicole@kolabsystems.com> | 2018-04-17 14:30:27 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2018-04-17 14:32:29 +0200 |
commit | b8d76329bced92d712185e5588dfd6061e8fe0f6 (patch) | |
tree | af37569d19c112549ab1e6ba0b94fe9c2d83c4fc /framework/src/domain/perioddayeventmodel.cpp | |
parent | afaaeb6dc16315c78091653a2662be41781ddfd3 (diff) | |
download | kube-b8d76329bced92d712185e5588dfd6061e8fe0f6.tar.gz kube-b8d76329bced92d712185e5588dfd6061e8fe0f6.zip |
Implement PeriodDayEventModel
Summary:
Implements a model to load events.
When finished, should fix T8225
TODO:
- Use the parent / children model in qml, instead of relying on the ".events" attribute (using DelegateModel I think)
Reviewers: cmollekopf
Tags: #kube
Maniphest Tasks: T8225
Differential Revision: https://phabricator.kde.org/D12089
Diffstat (limited to 'framework/src/domain/perioddayeventmodel.cpp')
-rw-r--r-- | framework/src/domain/perioddayeventmodel.cpp | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/framework/src/domain/perioddayeventmodel.cpp b/framework/src/domain/perioddayeventmodel.cpp new file mode 100644 index 00000000..637e5584 --- /dev/null +++ b/framework/src/domain/perioddayeventmodel.cpp | |||
@@ -0,0 +1,256 @@ | |||
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) | ||
33 | : QAbstractItemModel(parent), partitionedEvents(7) | ||
34 | { | ||
35 | Sink::Query query; | ||
36 | query.setFlags(Sink::Query::LiveQuery); | ||
37 | query.request<Event::Summary>(); | ||
38 | query.request<Event::Description>(); | ||
39 | query.request<Event::StartTime>(); | ||
40 | query.request<Event::EndTime>(); | ||
41 | |||
42 | eventModel = Sink::Store::loadModel<Event>(query); | ||
43 | |||
44 | QObject::connect(eventModel.data(), &QAbstractItemModel::dataChanged, this, &PeriodDayEventModel::partitionData); | ||
45 | QObject::connect(eventModel.data(), &QAbstractItemModel::layoutChanged, this, &PeriodDayEventModel::partitionData); | ||
46 | QObject::connect(eventModel.data(), &QAbstractItemModel::modelReset, this, &PeriodDayEventModel::partitionData); | ||
47 | QObject::connect(eventModel.data(), &QAbstractItemModel::rowsInserted, this, &PeriodDayEventModel::partitionData); | ||
48 | QObject::connect(eventModel.data(), &QAbstractItemModel::rowsMoved, this, &PeriodDayEventModel::partitionData); | ||
49 | QObject::connect(eventModel.data(), &QAbstractItemModel::rowsRemoved, this, &PeriodDayEventModel::partitionData); | ||
50 | |||
51 | partitionData(); | ||
52 | } | ||
53 | |||
54 | void PeriodDayEventModel::partitionData() | ||
55 | { | ||
56 | SinkLog() << "Partitioning event data"; | ||
57 | |||
58 | beginResetModel(); | ||
59 | |||
60 | partitionedEvents = QVector<QList<QSharedPointer<Event>>>(mPeriodLength); | ||
61 | |||
62 | for (int i = 0; i < eventModel->rowCount(); ++i) { | ||
63 | auto event = eventModel->index(i, 0).data(Sink::Store::DomainObjectRole).value<Event::Ptr>(); | ||
64 | QDate eventDate = event->getStartTime().date(); | ||
65 | |||
66 | if (!eventDate.isValid()) { | ||
67 | SinkWarning() << "Invalid date in the eventModel, ignoring..."; | ||
68 | continue; | ||
69 | } | ||
70 | |||
71 | int bucket = bucketOf(eventDate); | ||
72 | |||
73 | if (bucket >= 0) { | ||
74 | SinkTrace() << "Adding event:" << event->getSummary() << "in bucket #" << bucket; | ||
75 | partitionedEvents[bucket].append(event); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | endResetModel(); | ||
80 | } | ||
81 | |||
82 | int PeriodDayEventModel::bucketOf(const QDate &candidate) const | ||
83 | { | ||
84 | int bucket = mPeriodStart.daysTo(candidate); | ||
85 | if (bucket >= mPeriodLength || bucket < 0) { | ||
86 | return -1; | ||
87 | } | ||
88 | |||
89 | return bucket; | ||
90 | } | ||
91 | |||
92 | QModelIndex PeriodDayEventModel::index(int row, int column, const QModelIndex &parent) const | ||
93 | { | ||
94 | if (!hasIndex(row, column, parent)) { | ||
95 | return {}; | ||
96 | } | ||
97 | |||
98 | if (!parent.isValid()) { | ||
99 | // Asking for a day | ||
100 | |||
101 | if (!(0 <= row && row < mPeriodLength)) { | ||
102 | return {}; | ||
103 | } | ||
104 | |||
105 | return createIndex(row, column, DAY_ID); | ||
106 | } | ||
107 | |||
108 | // Asking for an Event | ||
109 | auto day = static_cast<int>(parent.row()); | ||
110 | |||
111 | Q_ASSERT(0 <= day && day <= mPeriodLength); | ||
112 | if (row >= partitionedEvents[day].size()) { | ||
113 | return {}; | ||
114 | } | ||
115 | |||
116 | return createIndex(row, column, day); | ||
117 | } | ||
118 | |||
119 | QModelIndex PeriodDayEventModel::parent(const QModelIndex &index) const | ||
120 | { | ||
121 | if (!index.isValid()) { | ||
122 | return {}; | ||
123 | } | ||
124 | |||
125 | if (index.internalId() == DAY_ID) { | ||
126 | return {}; | ||
127 | } | ||
128 | |||
129 | auto day = index.internalId(); | ||
130 | |||
131 | return this->index(day, 0); | ||
132 | } | ||
133 | |||
134 | int PeriodDayEventModel::rowCount(const QModelIndex &parent) const | ||
135 | { | ||
136 | if (!parent.isValid()) { | ||
137 | return mPeriodLength; | ||
138 | } | ||
139 | |||
140 | auto day = parent.row(); | ||
141 | |||
142 | return partitionedEvents[day].size(); | ||
143 | } | ||
144 | |||
145 | int PeriodDayEventModel::columnCount(const QModelIndex &parent) const | ||
146 | { | ||
147 | if (!parent.isValid()) { | ||
148 | return 1; | ||
149 | } | ||
150 | |||
151 | return eventModel->columnCount(); | ||
152 | } | ||
153 | |||
154 | QVariant PeriodDayEventModel::data(const QModelIndex &id, int role) const | ||
155 | { | ||
156 | if (id.internalId() == DAY_ID) { | ||
157 | auto day = id.row(); | ||
158 | |||
159 | SinkTrace() << "Fetching data for day" << day << "with role" | ||
160 | << QMetaEnum::fromType<Roles>().valueToKey(role); | ||
161 | |||
162 | switch (role) { | ||
163 | case Qt::DisplayRole: | ||
164 | return mPeriodStart.addDays(day).toString(); | ||
165 | case Events: { | ||
166 | auto result = QVariantList{}; | ||
167 | |||
168 | for (int i = 0; i < partitionedEvents[day].size(); ++i) { | ||
169 | auto eventId = index(i, 0, id); | ||
170 | SinkTrace() << "Appending event:" << data(eventId, Summary); | ||
171 | |||
172 | auto startTime = data(eventId, StartTime).toDateTime().time(); | ||
173 | |||
174 | result.append(QVariantMap{ | ||
175 | {"text", data(eventId, Summary)}, | ||
176 | {"description", data(eventId, Description)}, | ||
177 | {"starts", startTime.hour() + startTime.minute() / 60.}, | ||
178 | {"duration", data(eventId, Duration)}, | ||
179 | {"color", "#134bab"}, | ||
180 | {"indention", 0}, | ||
181 | }); | ||
182 | } | ||
183 | |||
184 | return result; | ||
185 | } | ||
186 | default: | ||
187 | SinkWarning() << "Unknown role for day:" << QMetaEnum::fromType<Roles>().valueToKey(role); | ||
188 | return {}; | ||
189 | } | ||
190 | } else { | ||
191 | auto day = id.internalId(); | ||
192 | SinkTrace() << "Fetching data for event on day" << day << "with role" | ||
193 | << QMetaEnum::fromType<Roles>().valueToKey(role); | ||
194 | auto event = partitionedEvents[day].at(id.row()); | ||
195 | |||
196 | switch (role) { | ||
197 | case Summary: | ||
198 | return event->getSummary(); | ||
199 | case Description: | ||
200 | return event->getDescription(); | ||
201 | case StartTime: | ||
202 | return event->getStartTime(); | ||
203 | case Duration: { | ||
204 | auto start = event->getStartTime(); | ||
205 | auto end = event->getEndTime(); | ||
206 | return start.secsTo(end) / 3600; | ||
207 | } | ||
208 | default: | ||
209 | SinkWarning() << "Unknown role for event:" << QMetaEnum::fromType<Roles>().valueToKey(role); | ||
210 | return {}; | ||
211 | } | ||
212 | } | ||
213 | } | ||
214 | |||
215 | QHash<int, QByteArray> PeriodDayEventModel::roleNames() const | ||
216 | { | ||
217 | return { | ||
218 | {Events, "events"}, | ||
219 | {Summary, "summary"}, | ||
220 | {Description, "description"}, | ||
221 | {StartTime, "starts"}, | ||
222 | {Duration, "duration"}, | ||
223 | }; | ||
224 | } | ||
225 | |||
226 | QDate PeriodDayEventModel::periodStart() const | ||
227 | { | ||
228 | return mPeriodStart; | ||
229 | } | ||
230 | |||
231 | void PeriodDayEventModel::setPeriodStart(const QDate &start) | ||
232 | { | ||
233 | if (!start.isValid()) { | ||
234 | SinkWarning() << "Passed an invalid starting date in setPeriodStart, ignoring..."; | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | mPeriodStart = start; | ||
239 | partitionData(); | ||
240 | } | ||
241 | |||
242 | void PeriodDayEventModel::setPeriodStart(const QVariant &start) | ||
243 | { | ||
244 | setPeriodStart(start.toDate()); | ||
245 | } | ||
246 | |||
247 | int PeriodDayEventModel::periodLength() const | ||
248 | { | ||
249 | return mPeriodLength; | ||
250 | } | ||
251 | |||
252 | void PeriodDayEventModel::setPeriodLength(int length) | ||
253 | { | ||
254 | mPeriodLength = length; | ||
255 | partitionData(); | ||
256 | } | ||