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