##// END OF EJS Templates
Fix display of tstart & tend when an event has no event products
trabillard -
r1161:05dadb964647
parent child
Show More
@@ -1,381 +1,387
1 1 #include "Catalogue/CatalogueEventsModel.h"
2 2
3 3 #include <Common/DateUtils.h>
4 4 #include <Common/MimeTypesDef.h>
5 5 #include <DBEvent.h>
6 6 #include <DBEventProduct.h>
7 7 #include <DBTag.h>
8 8 #include <Data/SqpRange.h>
9 9 #include <SqpApplication.h>
10 10 #include <Time/TimeController.h>
11 11
12 12 #include <list>
13 13 #include <unordered_map>
14 14
15 15 #include <QHash>
16 16 #include <QMimeData>
17 17
18 18 const auto EVENT_ITEM_TYPE = 1;
19 19 const auto EVENT_PRODUCT_ITEM_TYPE = 2;
20 20
21 21 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
22 22 QVector<std::shared_ptr<DBEvent> > m_Events;
23 23 std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
24 24
25 25 enum class Column { Name, TStart, TEnd, Tags, Product, NbColumn };
26 26 QStringList columnNames()
27 27 {
28 28 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"), tr("Tags"), tr("Product")};
29 29 }
30 30
31 31 QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
32 32 {
33 33 switch (static_cast<Column>(col)) {
34 34 case Column::Name:
35 35 return event->getName();
36 36 case Column::TStart:
37 return DateUtils::dateTime(event->getTStart());
37 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart())
38 : QVariant{};
38 39 case Column::TEnd:
39 return DateUtils::dateTime(event->getTEnd());
40 case Column::Product: {
41 auto eventProductsIt = m_EventProducts.find(event.get());
42 if (eventProductsIt != m_EventProducts.cend()) {
43 return QString::number(m_EventProducts.at(event.get()).count()) + " product(s)";
44 }
45 else {
46 return "0 product";
47 }
48 }
40 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd())
41 : QVariant{};
42 case Column::Product:
43 return QString::number(nbEventProducts(event)) + " product(s)";
49 44 case Column::Tags: {
50 45 QString tagList;
51 46 auto tags = event->getTags();
52 47 for (auto tag : tags) {
53 48 tagList += tag.getName();
54 49 tagList += ' ';
55 50 }
56 51
57 52 return tagList;
58 53 }
59 54 default:
60 55 break;
61 56 }
62 57
63 58 Q_ASSERT(false);
64 59 return QStringLiteral("Unknown Data");
65 60 }
66 61
67 62 void parseEventProduct(const std::shared_ptr<DBEvent> &event)
68 63 {
69 64 for (auto product : event->getEventProducts()) {
70 65 m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product));
71 66 }
72 67 }
73 68
69 int nbEventProducts(const std::shared_ptr<DBEvent> &event) const
70 {
71 auto eventProductsIt = m_EventProducts.find(event.get());
72 if (eventProductsIt != m_EventProducts.cend()) {
73 return m_EventProducts.at(event.get()).count();
74 }
75 else {
76 return 0;
77 }
78 }
79
74 80 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
75 81 {
76 82 switch (static_cast<Column>(col)) {
77 83 case Column::Name:
78 84 return eventProduct->getProductId();
79 85 case Column::TStart:
80 86 return DateUtils::dateTime(eventProduct->getTStart());
81 87 case Column::TEnd:
82 88 return DateUtils::dateTime(eventProduct->getTEnd());
83 89 case Column::Product:
84 90 return eventProduct->getProductId();
85 91 case Column::Tags: {
86 92 return QString();
87 93 }
88 94 default:
89 95 break;
90 96 }
91 97
92 98 Q_ASSERT(false);
93 99 return QStringLiteral("Unknown Data");
94 100 }
95 101 };
96 102
97 103 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
98 104 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
99 105 {
100 106 }
101 107
102 108 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
103 109 {
104 110 beginResetModel();
105 111
106 112 impl->m_Events = events;
107 113 impl->m_EventProducts.clear();
108 114 for (auto event : events) {
109 115 impl->parseEventProduct(event);
110 116 }
111 117
112 118 endResetModel();
113 119 }
114 120
115 121 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
116 122 {
117 123 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
118 124 return impl->m_Events.value(index.row());
119 125 }
120 126 else {
121 127 return nullptr;
122 128 }
123 129 }
124 130
125 131 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
126 132 {
127 133 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
128 134 return getEvent(index.parent());
129 135 }
130 136 else {
131 137 return nullptr;
132 138 }
133 139 }
134 140
135 141 std::shared_ptr<DBEventProduct>
136 142 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
137 143 {
138 144 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
139 145 auto event = static_cast<DBEvent *>(index.internalPointer());
140 146 return impl->m_EventProducts.at(event).value(index.row());
141 147 }
142 148 else {
143 149 return nullptr;
144 150 }
145 151 }
146 152
147 153 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
148 154 {
149 155 beginInsertRows(QModelIndex(), impl->m_Events.count() - 1, impl->m_Events.count() - 1);
150 156 impl->m_Events.append(event);
151 157 impl->parseEventProduct(event);
152 158 endInsertRows();
153 159 }
154 160
155 161 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
156 162 {
157 163 auto index = impl->m_Events.indexOf(event);
158 164 if (index >= 0) {
159 165 beginRemoveRows(QModelIndex(), index, index);
160 166 impl->m_Events.removeAt(index);
161 167 impl->m_EventProducts.erase(event.get());
162 168 endRemoveRows();
163 169 }
164 170 }
165 171
166 172 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event)
167 173 {
168 174 auto i = impl->m_Events.indexOf(event);
169 175 if (i >= 0) {
170 176 auto eventIndex = index(i, 0);
171 177 auto colCount = columnCount();
172 178 emit dataChanged(eventIndex, index(i, colCount));
173 179
174 180 auto childCount = rowCount(eventIndex);
175 181 emit dataChanged(index(0, 0, eventIndex), index(childCount, colCount, eventIndex));
176 182 }
177 183 }
178 184
179 185 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
180 186 {
181 187 if (!hasIndex(row, column, parent)) {
182 188 return QModelIndex();
183 189 }
184 190
185 191 switch (itemTypeOf(parent)) {
186 192 case CatalogueEventsModel::ItemType::Root:
187 193 return createIndex(row, column);
188 194 case CatalogueEventsModel::ItemType::Event: {
189 195 auto event = getEvent(parent);
190 196 return createIndex(row, column, event.get());
191 197 }
192 198 case CatalogueEventsModel::ItemType::EventProduct:
193 199 break;
194 200 default:
195 201 break;
196 202 }
197 203
198 204 return QModelIndex();
199 205 }
200 206
201 207 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
202 208 {
203 209 switch (itemTypeOf(index)) {
204 210 case CatalogueEventsModel::ItemType::EventProduct: {
205 211 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
206 212 auto it
207 213 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
208 214 [parentEvent](auto event) { return event.get() == parentEvent; });
209 215
210 216 if (it != impl->m_Events.cend()) {
211 217 return createIndex(it - impl->m_Events.cbegin(), 0);
212 218 }
213 219 else {
214 220 return QModelIndex();
215 221 }
216 222 }
217 223 case CatalogueEventsModel::ItemType::Root:
218 224 break;
219 225 case CatalogueEventsModel::ItemType::Event:
220 226 break;
221 227 default:
222 228 break;
223 229 }
224 230
225 231 return QModelIndex();
226 232 }
227 233
228 234 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
229 235 {
230 236 if (parent.column() > 0) {
231 237 return 0;
232 238 }
233 239
234 240 switch (itemTypeOf(parent)) {
235 241 case CatalogueEventsModel::ItemType::Root:
236 242 return impl->m_Events.count();
237 243 case CatalogueEventsModel::ItemType::Event: {
238 244 auto event = getEvent(parent);
239 245 return impl->m_EventProducts[event.get()].count();
240 246 }
241 247 case CatalogueEventsModel::ItemType::EventProduct:
242 248 break;
243 249 default:
244 250 break;
245 251 }
246 252
247 253 return 0;
248 254 }
249 255
250 256 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
251 257 {
252 258 return static_cast<int>(CatalogueEventsModelPrivate::Column::NbColumn);
253 259 }
254 260
255 261 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
256 262 {
257 263 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
258 264 }
259 265
260 266 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
261 267 {
262 268 if (index.isValid()) {
263 269
264 270 auto type = itemTypeOf(index);
265 271 if (type == CatalogueEventsModel::ItemType::Event) {
266 272 auto event = getEvent(index);
267 273 switch (role) {
268 274 case Qt::DisplayRole:
269 275 return impl->eventData(index.column(), event);
270 276 break;
271 277 }
272 278 }
273 279 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
274 280 auto product = getEventProduct(index);
275 281 switch (role) {
276 282 case Qt::DisplayRole:
277 283 return impl->eventProductData(index.column(), product);
278 284 break;
279 285 }
280 286 }
281 287 }
282 288
283 289 return QVariant{};
284 290 }
285 291
286 292 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
287 293 {
288 294 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
289 295 return impl->columnNames().value(section);
290 296 }
291 297
292 298 return QVariant();
293 299 }
294 300
295 301 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
296 302 {
297 303 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
298 304 [this, column, order](auto e1, auto e2) {
299 305 auto data1 = impl->eventData(column, e1);
300 306 auto data2 = impl->eventData(column, e2);
301 307
302 308 auto result = data1.toString() < data2.toString();
303 309
304 310 return order == Qt::AscendingOrder ? result : !result;
305 311 });
306 312
307 313 emit dataChanged(QModelIndex(), QModelIndex());
308 314 }
309 315
310 316 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
311 317 {
312 318 return Qt::CopyAction | Qt::MoveAction;
313 319 }
314 320
315 321 QStringList CatalogueEventsModel::mimeTypes() const
316 322 {
317 323 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_TIME_RANGE};
318 324 }
319 325
320 326 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
321 327 {
322 328 auto mimeData = new QMimeData;
323 329
324 330 bool isFirst = true;
325 331
326 332 QVector<std::shared_ptr<DBEvent> > eventList;
327 333 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
328 334
329 335 SqpRange firstTimeRange;
330 336 for (const auto &index : indexes) {
331 337 if (index.column() == 0) { // only the first column
332 338
333 339 auto type = itemTypeOf(index);
334 340 if (type == ItemType::Event) {
335 341 auto event = getEvent(index);
336 342 eventList << event;
337 343
338 344 if (isFirst) {
339 345 isFirst = false;
340 346 firstTimeRange.m_TStart = event->getTStart();
341 347 firstTimeRange.m_TEnd = event->getTEnd();
342 348 }
343 349 }
344 350 else if (type == ItemType::EventProduct) {
345 351 auto product = getEventProduct(index);
346 352 eventProductList << product;
347 353
348 354 if (isFirst) {
349 355 isFirst = false;
350 356 firstTimeRange.m_TStart = product->getTStart();
351 357 firstTimeRange.m_TEnd = product->getTEnd();
352 358 }
353 359 }
354 360 }
355 361 }
356 362
357 363 auto eventsEncodedData
358 364 = QByteArray{}; // sqpApp->catalogueController().->mimeDataForEvents(eventList); //TODO
359 365 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
360 366
361 367 if (eventList.count() + eventProductList.count() == 1) {
362 368 // No time range MIME data if multiple events are dragged
363 369 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
364 370 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
365 371 }
366 372
367 373 return mimeData;
368 374 }
369 375
370 376 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
371 377 {
372 378 if (!index.isValid()) {
373 379 return ItemType::Root;
374 380 }
375 381 else if (index.internalPointer() == nullptr) {
376 382 return ItemType::Event;
377 383 }
378 384 else {
379 385 return ItemType::EventProduct;
380 386 }
381 387 }
General Comments 0
You need to be logged in to leave comments. Login now