1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2010-05-12
7 * Description : A model to hold information about image tags.
8 *
9 * Copyright (C) 2010 by Michael G. Hansen <mike at mghansen dot de>
10 * Copyright (C) 2010 by Gabriel Voicu <ping dot gabi at gmail dot com>
11 *
12 * This program is free software; you can redistribute it
13 * and/or modify it under the terms of the GNU General
14 * Public License as published by the Free Software Foundation;
15 * either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * ============================================================ */
24
25 #include "rgtagmodel.h"
26
27 // Qt includes
28
29 #include <QColor>
30
31 // KDE includes
32
33 #include <klocalizedstring.h>
34
35 namespace Digikam
36 {
37
38 class Q_DECL_HIDDEN RGTagModel::Private
39 {
40 public:
41
Private()42 explicit Private()
43 : tagModel (nullptr),
44 rootTag (nullptr),
45 startInsert (-1),
46 endInsert (-1)
47 {
48 }
49
50 public:
51
52 QAbstractItemModel* tagModel;
53 TreeBranch* rootTag;
54
55 QModelIndex parent;
56 int startInsert;
57 int endInsert;
58
59 QList<QList<TagData> > newTags;
60
61 QStringList auxTagList;
62 QList<Type> auxTagTypeList;
63 QList<QPersistentModelIndex> auxIndexList;
64
65 QList<QList<TagData> > savedSpacerList;
66
67 QString textState;
68 QString textLau1;
69 QString textLau2;
70 };
71
RGTagModel(QAbstractItemModel * const externalTagModel,QObject * const parent)72 RGTagModel::RGTagModel(QAbstractItemModel* const externalTagModel, QObject* const parent)
73 : QAbstractItemModel(parent),
74 d (new Private)
75 {
76 d->tagModel = externalTagModel;
77 d->rootTag = new TreeBranch();
78 d->rootTag->type = TypeChild;
79
80 i18n("{Country}");
81 d->textState = i18nc("Part of a country", "{State}");
82 i18n("{State district}");
83 i18n("{County}");
84 i18n("{City}");
85 i18n("{City district}");
86 i18n("{Suburb}");
87 i18n("{Town}");
88 i18n("{Village}");
89 i18n("{Hamlet}");
90 i18n("{Street}");
91 i18n("{House number}");
92 i18n("{Place}");
93 d->textLau1 = i18nc("Local administrative area 1", "{LAU1}");
94 d->textLau2 = i18nc("Local administrative area 2", "{LAU2}");
95
96 connect(d->tagModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
97 this, SLOT(slotSourceDataChanged(QModelIndex,QModelIndex)));
98
99 connect(d->tagModel, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
100 this, SLOT(slotSourceHeaderDataChanged(Qt::Orientation,int,int)));
101
102 connect(d->tagModel, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
103 this, SLOT(slotColumnsAboutToBeInserted(QModelIndex,int,int)));
104
105 connect(d->tagModel, SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
106 this, SLOT(slotColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
107
108 connect(d->tagModel, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
109 this, SLOT(slotColumnsAboutToBeRemoved(QModelIndex,int,int)));
110
111 connect(d->tagModel, SIGNAL(columnsInserted(QModelIndex,int,int)),
112 this, SLOT(slotColumnsInserted()));
113
114 connect(d->tagModel, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
115 this, SLOT(slotColumnsMoved()));
116
117 connect(d->tagModel, SIGNAL(columnsRemoved(QModelIndex,int,int)),
118 this, SLOT(slotColumnsRemoved()));
119
120 connect(d->tagModel, SIGNAL(layoutAboutToBeChanged()),
121 this, SLOT(slotLayoutAboutToBeChanged()));
122
123 connect(d->tagModel, SIGNAL(layoutChanged()),
124 this, SLOT(slotLayoutChanged()));
125
126 connect(d->tagModel, SIGNAL(modelAboutToBeReset()),
127 this, SLOT(slotModelAboutToBeReset()));
128
129 connect(d->tagModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
130 this, SLOT(slotRowsAboutToBeInserted(QModelIndex,int,int)));
131
132 connect(d->tagModel, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
133 this, SLOT(slotRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
134
135 connect(d->tagModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
136 this, SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int)));
137
138 connect(d->tagModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
139 this, SLOT(slotRowsInserted()));
140
141 connect(d->tagModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
142 this, SLOT(slotRowsMoved()));
143
144 connect(d->tagModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
145 this, SLOT(slotRowsRemoved()));
146 }
147
~RGTagModel()148 RGTagModel::~RGTagModel()
149 {
150 delete d->rootTag;
151 delete d;
152 }
153
branchFromIndex(const QModelIndex & index) const154 TreeBranch* RGTagModel::branchFromIndex(const QModelIndex& index) const
155 {
156 return (index.isValid() ? static_cast<TreeBranch*>(index.internalPointer()) : d->rootTag);
157 }
158
checkTree(TreeBranch * const checkBranch,int level)159 void checkTree(TreeBranch* const checkBranch, int level)
160 {
161 if (!checkBranch->sourceIndex.isValid())
162 {
163 return;
164 }
165
166 for (int j = 0 ; j < checkBranch->oldChildren.count() ; ++j)
167 {
168 checkTree(checkBranch->oldChildren[j], level+1);
169 }
170
171 for (int j = 0 ; j < checkBranch->spacerChildren.count() ; ++j)
172 {
173 checkTree(checkBranch->spacerChildren[j], level+1);
174 }
175 }
176
fromSourceIndex(const QModelIndex & externalTagModelIndex) const177 QModelIndex RGTagModel::fromSourceIndex(const QModelIndex& externalTagModelIndex) const
178 {
179 if (!externalTagModelIndex.isValid())
180 {
181 return QModelIndex();
182 }
183
184 Q_ASSERT(externalTagModelIndex.model() == d->tagModel);
185
186 QList<QModelIndex> parents;
187 QModelIndex myIndex = externalTagModelIndex;
188 parents << myIndex;
189
190 while (myIndex.parent().isValid())
191 {
192 myIndex = myIndex.parent();
193 parents.prepend(myIndex);
194 }
195
196 TreeBranch* subModelBranch = d->rootTag;
197 int level = 0;
198
199 while (level <= parents.count())
200 {
201 if (subModelBranch->sourceIndex == externalTagModelIndex)
202 {
203 return createIndex(subModelBranch->sourceIndex.row() +
204 subModelBranch->parent->spacerChildren.count() +
205 subModelBranch->parent->newChildren.count(),
206 subModelBranch->sourceIndex.column(), subModelBranch);
207 }
208
209 int where = -1;
210
211 for (int i = 0 ; i < subModelBranch->oldChildren.count() ; ++i)
212 {
213 if ((level < parents.size()) &&
214 (subModelBranch->oldChildren[i]->sourceIndex == parents[level]))
215 {
216 where = i;
217 break;
218 }
219 }
220
221 if (where >= 0)
222 {
223 subModelBranch = subModelBranch->oldChildren[where];
224 }
225 else
226 {
227 if (level>=parents.count())
228 {
229 return QModelIndex();
230 }
231
232 // TODO: check when rows are different
233
234 TreeBranch* const newTreeBranch = new TreeBranch();
235 newTreeBranch->sourceIndex = parents[level];
236 newTreeBranch->data = d->tagModel->data(externalTagModelIndex, Qt::DisplayRole).toString();
237 newTreeBranch->parent = subModelBranch;
238 newTreeBranch->type = TypeChild;
239
240 subModelBranch->oldChildren.append(newTreeBranch);
241 subModelBranch = newTreeBranch;
242 }
243
244 level++;
245 }
246
247 // no index is found
248
249 return QModelIndex();
250 }
251
toSourceIndex(const QModelIndex & tagModelIndex) const252 QModelIndex RGTagModel::toSourceIndex(const QModelIndex& tagModelIndex) const
253 {
254 if (!tagModelIndex.isValid())
255 {
256 return QModelIndex();
257 }
258
259 Q_ASSERT(tagModelIndex.model() == this);
260 /*
261 static_cast<TreeBranch*>(tagModelIndex.internalPointer());
262 */
263 TreeBranch* const treeBranch = branchFromIndex(tagModelIndex);
264
265 if (!treeBranch)
266 {
267 return QModelIndex();
268 }
269
270 return treeBranch->sourceIndex;
271 }
272
addSpacerTag(const QModelIndex & parent,const QString & spacerName)273 void RGTagModel::addSpacerTag(const QModelIndex& parent, const QString& spacerName)
274 {
275 /*
276 TreeBranch* const parentBranch = parent.isValid() ? static_cast<TreeBranch*>(parent.internalPointer()) : d->rootTag;
277 */
278 TreeBranch* const parentBranch = branchFromIndex(parent);
279 bool found = false;
280
281 if (!parentBranch->spacerChildren.isEmpty())
282 {
283 for (int i = 0 ; i < parentBranch->spacerChildren.count() ; ++i)
284 {
285 if (parentBranch->spacerChildren[i]->data == spacerName)
286 {
287 found = true;
288 break;
289 }
290 }
291 }
292
293 if (!found)
294 {
295 TreeBranch* const newSpacer = new TreeBranch();
296 newSpacer->parent = parentBranch;
297 newSpacer->data = spacerName;
298 newSpacer->type = TypeSpacer;
299
300 beginInsertRows(parent, parentBranch->spacerChildren.count(), parentBranch->spacerChildren.count());
301 parentBranch->spacerChildren.append(newSpacer);
302 endInsertRows();
303 }
304 }
305
addNewTag(const QModelIndex & parent,const QString & newTagName,const QString & newElement)306 QPersistentModelIndex RGTagModel::addNewTag(const QModelIndex& parent, const QString& newTagName, const QString& newElement)
307 {
308 TreeBranch* const parentBranch = branchFromIndex(parent);
309 /*
310 parent.isValid() ? static_cast<TreeBranch*>(parent.internalPointer()) : d->rootTag;
311 */
312 bool found = false;
313 QPersistentModelIndex retIndex;
314
315 if (!parentBranch->newChildren.isEmpty())
316 {
317 for ( int i = 0 ; i < parentBranch->newChildren.count() ; ++i)
318 {
319 if (parentBranch->newChildren[i]->data == newTagName)
320 {
321 found = true;
322 retIndex = createIndex(parentBranch->spacerChildren.count() + i, 0, parentBranch->newChildren[i]);
323 break;
324 }
325 }
326 }
327
328 if (!found)
329 {
330 TreeBranch* const newTagChild = new TreeBranch();
331 newTagChild->parent = parentBranch;
332 newTagChild->data = newTagName;
333 newTagChild->help = newElement;
334 newTagChild->type = TypeNewChild;
335
336 beginInsertRows(parent, parentBranch->spacerChildren.count() + parentBranch->newChildren.count(),
337 parentBranch->spacerChildren.count() + parentBranch->newChildren.count());
338 parentBranch->newChildren.append(newTagChild);
339 endInsertRows();
340
341 retIndex = createIndex(parentBranch->spacerChildren.count() + parentBranch->newChildren.count() - 1, 0,
342 parentBranch->newChildren.last());
343 }
344
345 return retIndex;
346 }
347
getTagAddress()348 QList<TagData> RGTagModel::getTagAddress()
349 {
350 QList<TagData> tagAddress;
351
352 for (int i = 0 ; i < d->auxTagList.count() ; ++i)
353 {
354 TagData tagData;
355 tagData.tagName = d->auxTagList[i];
356 tagData.tagType = d->auxTagTypeList[i];
357 tagAddress.append(tagData);
358 }
359
360 return tagAddress;
361 }
362
addDataInTree(TreeBranch * currentBranch,int currentRow,const QStringList & addressElements,const QStringList & elementsData)363 void RGTagModel::addDataInTree(TreeBranch* currentBranch,
364 int currentRow,
365 const QStringList& addressElements,
366 const QStringList& elementsData)
367 {
368 for (int i = 0 ; i < currentBranch->spacerChildren.count() ; ++i)
369 {
370 bool newDataAdded = false;
371
372 // this spacer is not an address element
373
374 if (currentBranch->spacerChildren[i]->data.indexOf(QLatin1String("{")) != 0)
375 {
376 d->auxTagList.append(currentBranch->spacerChildren[i]->data);
377 d->auxTagTypeList.append(TypeSpacer);
378 addDataInTree(currentBranch->spacerChildren[i], i, addressElements, elementsData);
379 d->auxTagList.removeLast();
380 d->auxTagTypeList.removeLast();
381 }
382 else
383 {
384 for (int j = 0 ; j < addressElements.count() ; ++j)
385 {
386 if (currentBranch->spacerChildren[i]->data == addressElements[j])
387 {
388 newDataAdded = true;
389 QModelIndex currentIndex;
390
391 if (currentBranch == d->rootTag)
392 {
393 currentIndex = QModelIndex();
394 }
395 else
396 {
397 currentIndex = createIndex(currentRow, 0, currentBranch);
398 }
399
400 // checks if adds the new tag as a sibling to a spacer, or as a child of a new tag
401
402 QPersistentModelIndex auxIndex;
403
404 if (((currentBranch->type != TypeSpacer) || (currentBranch->data.indexOf(QLatin1String("{")) != 0)) ||
405 (d->auxIndexList.isEmpty()))
406 {
407 auxIndex = addNewTag(currentIndex, elementsData[j], addressElements[j]);
408 }
409 else
410 {
411 auxIndex = addNewTag(d->auxIndexList.last(), elementsData[j], addressElements[j]);
412 }
413
414 d->auxTagList.append(elementsData[j]);
415 d->auxTagTypeList.append(TypeNewChild);
416 d->auxIndexList.append(auxIndex);
417
418 QList<TagData> newTag = getTagAddress();
419 newTag.last().tipName = addressElements[j];
420 d->newTags.append(newTag);
421 }
422 }
423
424 if (currentBranch->spacerChildren.at(i))
425 {
426 addDataInTree(currentBranch->spacerChildren[i], i, addressElements, elementsData);
427 }
428
429 if (newDataAdded)
430 {
431 d->auxTagList.removeLast();
432 d->auxTagTypeList.removeLast();
433 d->auxIndexList.removeLast();
434 }
435 }
436 }
437
438 for (int i = 0 ; i < currentBranch->newChildren.count() ; ++i)
439 {
440 d->auxTagList.append(currentBranch->newChildren[i]->data);
441 d->auxTagTypeList.append(TypeNewChild);
442 addDataInTree(currentBranch->newChildren.at(i), i + currentBranch->spacerChildren.count(), addressElements, elementsData);
443 d->auxTagList.removeLast();
444 d->auxTagTypeList.removeLast();
445 }
446
447 for (int i = 0 ; i < currentBranch->oldChildren.count() ; ++i)
448 {
449 d->auxTagList.append(currentBranch->oldChildren.at(i)->data);
450 d->auxTagTypeList.append(TypeChild);
451 addDataInTree(currentBranch->oldChildren.at(i),
452 i + currentBranch->spacerChildren.count() + currentBranch->newChildren.count(),
453 addressElements,
454 elementsData);
455 d->auxTagList.removeLast();
456 d->auxTagTypeList.removeLast();
457 }
458 }
459
addNewData(const QStringList & elements,const QStringList & resultedData)460 QList<QList<TagData> > RGTagModel::addNewData(const QStringList& elements, const QStringList& resultedData)
461 {
462 d->newTags.clear();
463
464 // elements contains address elements {Country}, {City}, ...
465 // resultedData contains RG data (example Spain,Barcelona)
466
467 addDataInTree(d->rootTag, 0, elements, resultedData);
468
469 return d->newTags;
470 }
471
columnCount(const QModelIndex & parent) const472 int RGTagModel::columnCount(const QModelIndex& parent) const
473 {
474 TreeBranch* const parentBranch = branchFromIndex(parent); //static_cast<TreeBranch*>(parent.internalPointer());
475
476 if (!parentBranch)
477 {
478 return 1;
479 }
480
481 if (parentBranch->type == TypeSpacer)
482 {
483 return 1;
484 }
485 else if (parentBranch->type == TypeNewChild)
486 {
487 return 1;
488 }
489
490 return d->tagModel->columnCount(toSourceIndex(parent));
491 }
492
setData(const QModelIndex &,const QVariant &,int)493 bool RGTagModel::setData(const QModelIndex& /*index*/, const QVariant& /*value*/, int /*role*/)
494 {
495 return false;
496 }
497
data(const QModelIndex & index,int role) const498 QVariant RGTagModel::data(const QModelIndex& index, int role) const
499 {
500 if (!index.isValid())
501 {
502 return QVariant();
503 }
504
505 /*
506 static_cast<TreeBranch*>(index.internalPointer());
507 */
508 TreeBranch* const treeBranch = branchFromIndex(index);
509
510 if ((!treeBranch) || (treeBranch->type == TypeChild))
511 {
512 return d->tagModel->data(toSourceIndex(index), role);
513 }
514 else if ((treeBranch->type == TypeSpacer) && (role == Qt::DisplayRole))
515 {
516 return translateSpacer(treeBranch->data);
517 }
518 else if ((treeBranch->type == TypeSpacer) && (role == Qt::ForegroundRole))
519 {
520 return QColor(Qt::red);
521 }
522 else if ((treeBranch->type == TypeNewChild) && (role == Qt::DisplayRole))
523 {
524 return treeBranch->data;
525 }
526 else if ((treeBranch->type == TypeNewChild) && (role == Qt::ForegroundRole))
527 {
528 return QColor(Qt::green);
529 }
530 else if ((treeBranch->type == TypeNewChild) && (role == Qt::ToolTipRole))
531 {
532 return translateSpacer(treeBranch->help);
533 }
534
535 return QVariant();
536 }
537
index(int row,int column,const QModelIndex & parent) const538 QModelIndex RGTagModel::index(int row, int column, const QModelIndex& parent) const
539 {
540 if ((column != 0) || (row < 0))
541 {
542 return QModelIndex();
543 }
544 /*
545 if (parent.isValid())
546 {
547 parentBranch = static_cast<TreeBranch*>(parent.internalPointer());
548 }
549 */
550 TreeBranch* const parentBranch = branchFromIndex(parent);//d->rootTag;
551
552 // this should not happen!
553
554 if (!parentBranch)
555 {
556 return QModelIndex();
557 }
558
559 if (row < parentBranch->spacerChildren.count())
560 {
561 return createIndex(row, column, parentBranch->spacerChildren[row]);
562 }
563 else if ((row >= parentBranch->spacerChildren.count()) &&
564 (row < (parentBranch->newChildren.count() + parentBranch->spacerChildren.count())))
565 {
566 return createIndex(row, column, parentBranch->newChildren[row-parentBranch->spacerChildren.count()]);
567 }
568
569 return fromSourceIndex(d->tagModel->index(row - parentBranch->spacerChildren.count() - parentBranch->newChildren.count(),
570 column, toSourceIndex(parent)));
571 }
572
parent(const QModelIndex & index) const573 QModelIndex RGTagModel::parent(const QModelIndex& index) const
574 {
575 TreeBranch* const currentBranch = branchFromIndex(index); // static_cast<TreeBranch*>(index.internalPointer());
576
577 if (!currentBranch)
578 {
579 return QModelIndex();
580 }
581
582 if ((currentBranch->type == TypeSpacer) || (currentBranch->type == TypeNewChild))
583 {
584 TreeBranch* const parentBranch = currentBranch->parent;
585
586 if (!parentBranch)
587 {
588 return QModelIndex();
589 }
590
591 TreeBranch* const gParentBranch = parentBranch->parent;
592
593 if (!gParentBranch)
594 {
595 return QModelIndex();
596 }
597
598 if (parentBranch->type == TypeSpacer)
599 {
600 for (int parentRow = 0 ; parentRow < gParentBranch->spacerChildren.count() ; ++parentRow)
601 {
602 if (gParentBranch->spacerChildren[parentRow] == parentBranch)
603 {
604 return createIndex(parentRow, 0, parentBranch);
605 }
606 }
607
608 return QModelIndex();
609 }
610 else if (parentBranch->type == TypeNewChild)
611 {
612 for (int parentRow = 0 ; parentRow < gParentBranch->newChildren.count() ; ++parentRow)
613 {
614 if (gParentBranch->newChildren[parentRow] == parentBranch)
615 {
616 return createIndex(parentRow+gParentBranch->spacerChildren.count(), 0, parentBranch);
617 }
618 }
619 }
620 else if (parentBranch->type == TypeChild)
621 {
622 // TODO: don't we have a function for this?
623
624 for (int parentRow = 0 ; parentRow < gParentBranch->oldChildren.count() ; ++parentRow)
625 {
626 if (gParentBranch->oldChildren[parentRow] == parentBranch)
627 {
628 return createIndex(parentRow + gParentBranch->spacerChildren.count() + gParentBranch->newChildren.count(),
629 0, parentBranch);
630 }
631 }
632
633 return QModelIndex();
634 }
635 }
636
637 return fromSourceIndex(d->tagModel->parent(toSourceIndex(index)));
638 }
639
rowCount(const QModelIndex & parent) const640 int RGTagModel::rowCount(const QModelIndex& parent) const
641 {
642 /*
643 parent.isValid() ? static_cast<TreeBranch*>(parent.internalPointer()) : d->rootTag;
644 */
645 TreeBranch* const parentBranch = branchFromIndex(parent);
646 int myRowCount = parentBranch->spacerChildren.count() + parentBranch->newChildren.count();
647
648 // TODO: we don't know whether the oldChildren have been set up, therefore query the source model
649
650 if (parentBranch->type == TypeChild)
651 {
652 const QModelIndex sourceIndex = toSourceIndex(parent);
653 myRowCount += d->tagModel->rowCount(sourceIndex);
654 }
655
656 return myRowCount;
657 }
658
setHeaderData(int,Qt::Orientation,const QVariant &,int)659 bool RGTagModel::setHeaderData(int /*section*/,
660 Qt::Orientation /*orientation*/,
661 const QVariant& /*value*/,
662 int /*role*/)
663 {
664 return false;
665 }
666
headerData(int section,Qt::Orientation orientation,int role) const667 QVariant RGTagModel::headerData(int section, Qt::Orientation orientation, int role) const
668 {
669 return d->tagModel->headerData(section, orientation, role);
670 }
671
flags(const QModelIndex & index) const672 Qt::ItemFlags RGTagModel::flags(const QModelIndex& index) const
673 {
674 TreeBranch* const currentBranch = branchFromIndex(index);
675
676 if (currentBranch && ((currentBranch->type == TypeSpacer) || (currentBranch->type == TypeNewChild)))
677 {
678 return QAbstractItemModel::flags(index);
679 }
680
681 return d->tagModel->flags(toSourceIndex(index));
682 }
683
slotSourceDataChanged(const QModelIndex & topLeft,const QModelIndex & bottomRight)684 void RGTagModel::slotSourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)
685 {
686 emit dataChanged(fromSourceIndex(topLeft),fromSourceIndex(bottomRight));
687 }
688
slotSourceHeaderDataChanged(const Qt::Orientation orientation,int first,int last)689 void RGTagModel::slotSourceHeaderDataChanged(const Qt::Orientation orientation, int first, int last)
690 {
691 emit headerDataChanged(orientation, first, last);
692 }
693
slotColumnsAboutToBeInserted(const QModelIndex & parent,int start,int end)694 void RGTagModel::slotColumnsAboutToBeInserted(const QModelIndex& parent, int start, int end)
695 {
696 // TODO: Should we do something here?
697
698 beginInsertColumns(fromSourceIndex(parent), start, end);
699 }
700
slotColumnsAboutToBeMoved(const QModelIndex & sourceParent,int sourceStart,int sourceEnd,const QModelIndex & destinationParent,int destinationColumn)701 void RGTagModel::slotColumnsAboutToBeMoved(const QModelIndex& sourceParent,
702 int sourceStart,
703 int sourceEnd,
704 const QModelIndex& destinationParent,
705 int destinationColumn)
706 {
707 beginMoveColumns(fromSourceIndex(sourceParent), sourceStart, sourceEnd, fromSourceIndex(destinationParent), destinationColumn);
708 }
709
slotColumnsAboutToBeRemoved(const QModelIndex & parent,int start,int end)710 void RGTagModel::slotColumnsAboutToBeRemoved(const QModelIndex& parent, int start, int end )
711 {
712 beginRemoveColumns(fromSourceIndex(parent), start, end);
713 }
714
slotColumnsInserted()715 void RGTagModel::slotColumnsInserted()
716 {
717 endInsertColumns();
718 }
719
slotColumnsMoved()720 void RGTagModel::slotColumnsMoved()
721 {
722 endMoveColumns();
723 }
724
slotColumnsRemoved()725 void RGTagModel::slotColumnsRemoved()
726 {
727 endRemoveColumns();
728 }
729
slotLayoutAboutToBeChanged()730 void RGTagModel::slotLayoutAboutToBeChanged()
731 {
732 emit layoutAboutToBeChanged();
733 }
734
slotLayoutChanged()735 void RGTagModel::slotLayoutChanged()
736 {
737 emit layoutChanged();
738 }
739
slotModelAboutToBeReset()740 void RGTagModel::slotModelAboutToBeReset()
741 {
742 beginResetModel();
743 }
744
slotModelReset()745 void RGTagModel::slotModelReset()
746 {
747 beginResetModel();
748 endResetModel();
749 }
750
slotRowsAboutToBeInserted(const QModelIndex & parent,int start,int end)751 void RGTagModel::slotRowsAboutToBeInserted(const QModelIndex& parent, int start, int end)
752 {
753 TreeBranch* const parentBranch = parent.isValid() ? static_cast<TreeBranch*>(fromSourceIndex(parent).internalPointer()) : d->rootTag;
754 d->parent = fromSourceIndex(parent);
755 d->startInsert = start;
756 d->endInsert = end;
757
758 beginInsertRows(d->parent,
759 start + parentBranch->newChildren.count() + parentBranch->spacerChildren.count(),
760 end + parentBranch->newChildren.count() + parentBranch->spacerChildren.count());
761 }
762
slotRowsAboutToBeMoved(const QModelIndex & sourceParent,int sourceStart,int sourceEnd,const QModelIndex & destinationParent,int destinationRow)763 void RGTagModel::slotRowsAboutToBeMoved(const QModelIndex& sourceParent, int sourceStart, int sourceEnd,
764 const QModelIndex& destinationParent, int destinationRow)
765 {
766 beginMoveRows(fromSourceIndex(sourceParent), sourceStart, sourceEnd, fromSourceIndex(destinationParent), destinationRow );
767 }
768
slotRowsAboutToBeRemoved(const QModelIndex & parent,int start,int end)769 void RGTagModel::slotRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end)
770 {
771 Q_UNUSED(parent);
772 Q_UNUSED(start);
773 Q_UNUSED(end);
774 }
775
slotRowsInserted()776 void RGTagModel::slotRowsInserted()
777 {
778 TreeBranch* const parentBranch = d->parent.isValid() ? static_cast<TreeBranch*>(d->parent.internalPointer()) : d->rootTag;
779
780 for (int i = d->startInsert ; i < d->endInsert ; ++i)
781 {
782 TreeBranch* const newBranch = new TreeBranch();
783 newBranch->parent = parentBranch;
784 newBranch->sourceIndex = d->tagModel->index(i, 0, d->parent);
785 newBranch->type = TypeChild;
786
787 parentBranch->oldChildren.insert(i, newBranch);
788 }
789
790 endInsertRows();
791
792 d->parent = QModelIndex();
793 d->startInsert = -1;
794 d->endInsert = -1;
795 }
796
slotRowsMoved()797 void RGTagModel::slotRowsMoved()
798 {
799 endMoveRows();
800 }
801
slotRowsRemoved()802 void RGTagModel::slotRowsRemoved()
803 {
804 }
805
deleteTag(const QModelIndex & currentIndex)806 void RGTagModel::deleteTag(const QModelIndex& currentIndex)
807 {
808 if (!currentIndex.isValid())
809 {
810 return;
811 }
812
813 QModelIndex parentIndex = currentIndex.parent();
814 int currentRow = currentIndex.row();
815 TreeBranch* const parentBranch = branchFromIndex(parentIndex);
816 TreeBranch* const currentChildBranch = branchFromIndex(currentIndex);
817
818 if (currentChildBranch->type == TypeChild)
819 {
820 return;
821 }
822
823 if ((currentChildBranch->spacerChildren.count() > 0) || (currentChildBranch->newChildren.count() > 0))
824 {
825 beginMoveRows(currentIndex, 0, currentChildBranch->spacerChildren.count() - 1,
826 parentIndex, parentBranch->spacerChildren.count());
827
828 for (int j = 0 ; j < currentChildBranch->spacerChildren.count() ; ++j)
829 {
830 parentBranch->spacerChildren.append(currentChildBranch->spacerChildren[j]);
831 parentBranch->spacerChildren.last()->parent = parentBranch;
832 /*
833 QModelIndex testIndex =
834 */
835 createIndex(parentBranch->spacerChildren.count() - 1, 0, parentBranch->spacerChildren.last());
836 }
837
838 currentChildBranch->spacerChildren.clear();
839 endMoveRows();
840
841 beginMoveRows(currentIndex, currentChildBranch->spacerChildren.count(),
842 currentChildBranch->spacerChildren.count() + currentChildBranch->newChildren.count() - 1,
843 parentIndex, parentBranch->spacerChildren.count() + parentBranch->newChildren.count());
844
845 for (int j = currentChildBranch->spacerChildren.count() ;
846 (j < (currentChildBranch->spacerChildren.count() + currentChildBranch->newChildren.count())) ; ++j)
847 {
848 parentBranch->newChildren.append(currentChildBranch->newChildren[j - currentChildBranch->spacerChildren.count()]);
849 parentBranch->newChildren.last()->parent = parentBranch;
850 }
851
852 currentChildBranch->newChildren.clear();
853 endMoveRows();
854 }
855
856 beginRemoveRows(parentIndex, currentRow, currentRow);
857
858 // TODO: is it good here?
859
860 if (currentRow < parentBranch->spacerChildren.count())
861 {
862 parentBranch->spacerChildren.removeAt(currentRow);
863 }
864 else
865 {
866 parentBranch->newChildren.removeAt(currentRow - parentBranch->spacerChildren.count());
867 }
868
869 endRemoveRows();
870 }
871
findAndDeleteSpacersOrNewTags(TreeBranch * currentBranch,int currentRow,Type whatShouldRemove)872 void RGTagModel::findAndDeleteSpacersOrNewTags(TreeBranch* currentBranch, int currentRow, Type whatShouldRemove)
873 {
874 /*
875 QModelIndex currentIndex =
876 */
877 createIndex(currentRow, 0, currentBranch);
878
879 for (int i = 0 ; i < currentBranch->spacerChildren.count() ; ++i)
880 {
881 findAndDeleteSpacersOrNewTags(currentBranch->spacerChildren[i], i, whatShouldRemove);
882
883 if (whatShouldRemove == TypeSpacer)
884 {
885 QModelIndex spacerIndex = createIndex(i, 0, currentBranch->spacerChildren[i]);
886 deleteTag(spacerIndex);
887 i--;
888 }
889 }
890
891 for (int i = 0 ; i < currentBranch->newChildren.count() ; ++i)
892 {
893 findAndDeleteSpacersOrNewTags(currentBranch->newChildren[i], i + currentBranch->spacerChildren.count(), whatShouldRemove);
894
895 if (whatShouldRemove == TypeNewChild)
896 {
897 QModelIndex newTagIndex = createIndex(i+currentBranch->spacerChildren.count(), 0, currentBranch->newChildren[i]);
898 deleteTag(newTagIndex);
899 i--;
900 }
901 }
902
903 for (int i = 0 ; i < currentBranch->oldChildren.count() ; ++i)
904 {
905 findAndDeleteSpacersOrNewTags(currentBranch->oldChildren[i],
906 i + currentBranch->spacerChildren.count() + currentBranch->newChildren.count(),
907 whatShouldRemove);
908 }
909 }
910
deleteAllSpacersOrNewTags(const QModelIndex & currentIndex,Type whatShouldRemove)911 void RGTagModel::deleteAllSpacersOrNewTags(const QModelIndex& currentIndex, Type whatShouldRemove)
912 {
913 if (whatShouldRemove == TypeSpacer)
914 {
915 /*
916 currentIndex.isValid() ? static_cast<TreeBranch*>(currentIndex.internalPointer()) : d->rootTag;
917 */
918 TreeBranch* const currentBranch = branchFromIndex(currentIndex);
919 findAndDeleteSpacersOrNewTags(currentBranch, 0, whatShouldRemove);
920 }
921 else if (whatShouldRemove == TypeNewChild)
922 {
923 findAndDeleteSpacersOrNewTags(d->rootTag, 0, whatShouldRemove);
924 }
925 }
926
readdTag(TreeBranch * & currentBranch,int currentRow,const QList<TagData> & tagAddressElements,int currentAddressElementIndex)927 void RGTagModel::readdTag(TreeBranch*& currentBranch,
928 int currentRow,
929 const QList<TagData>& tagAddressElements,
930 int currentAddressElementIndex)
931 {
932 bool found1 = false;
933 int foundIndex;
934
935 if (currentAddressElementIndex >= tagAddressElements.count())
936 {
937 return;
938 }
939
940 if (tagAddressElements[currentAddressElementIndex].tagType == TypeSpacer)
941 {
942 for (int i = 0 ; i < currentBranch->spacerChildren.count() ; ++i)
943 {
944 if (currentBranch->spacerChildren[i]->data == tagAddressElements[currentAddressElementIndex].tagName)
945 {
946 found1 = true;
947 foundIndex = i;
948 break;
949 }
950 }
951
952 if (found1)
953 {
954 readdTag(currentBranch->spacerChildren[foundIndex], foundIndex, tagAddressElements, currentAddressElementIndex + 1);
955 return;
956 }
957 else
958 {
959 // recreates the spacer
960
961 QModelIndex currentIndex;
962
963 if (currentBranch == d->rootTag)
964 {
965 currentIndex = QModelIndex();
966 }
967 else
968 {
969 currentIndex = createIndex(currentRow, 0, currentBranch);
970 }
971
972 addSpacerTag(currentIndex,tagAddressElements[currentAddressElementIndex].tagName);
973
974 if ((tagAddressElements.count() - 1) > currentAddressElementIndex)
975 {
976 readdTag(currentBranch->spacerChildren[currentBranch->spacerChildren.count() - 1],
977 currentBranch->spacerChildren.count() - 1,
978 tagAddressElements,
979 currentAddressElementIndex + 1);
980 }
981
982 }
983
984 }
985 else if (tagAddressElements[currentAddressElementIndex].tagType == TypeNewChild)
986 {
987 for (int i = 0 ; i < currentBranch->newChildren.count() ; ++i)
988 {
989 if (currentBranch->newChildren[i]->data == tagAddressElements[currentAddressElementIndex].tagName)
990 {
991 found1 = true;
992 foundIndex = i;
993 break;
994 }
995 }
996
997 if (found1)
998 {
999 readdTag(currentBranch->newChildren[foundIndex],
1000 foundIndex + currentBranch->spacerChildren.count(),
1001 tagAddressElements,
1002 currentAddressElementIndex + 1);
1003 return;
1004 }
1005 else
1006 {
1007 QModelIndex currentIndex;
1008
1009 if (currentBranch == d->rootTag)
1010 {
1011 currentIndex = QModelIndex();
1012 }
1013 else
1014 {
1015 currentIndex = createIndex(currentRow, 0, currentBranch);
1016 }
1017
1018 addNewTag(currentIndex, tagAddressElements[currentAddressElementIndex].tagName,
1019 tagAddressElements[currentAddressElementIndex].tipName);
1020
1021 if ((tagAddressElements.count() - 1) > currentAddressElementIndex)
1022 {
1023 readdTag(currentBranch->newChildren[currentBranch->newChildren.count() - 1],
1024 currentBranch->spacerChildren.count() + currentBranch->newChildren.count() - 1,
1025 tagAddressElements,
1026 currentAddressElementIndex + 1);
1027 }
1028 }
1029 }
1030 else if (tagAddressElements[currentAddressElementIndex].tagType == TypeChild)
1031 {
1032 bool found2 = false;
1033
1034 for (int i = 0 ; i < currentBranch->oldChildren.count() ; ++i)
1035 {
1036 if (currentBranch->oldChildren[i]->data == tagAddressElements[currentAddressElementIndex].tagName)
1037 {
1038 found2 = true;
1039 foundIndex = i;
1040 break;
1041 }
1042 }
1043
1044 if (found2)
1045 {
1046 readdTag(currentBranch->oldChildren[foundIndex],
1047 foundIndex+currentBranch->spacerChildren.count() + currentBranch->newChildren.count(),
1048 tagAddressElements, currentAddressElementIndex + 1);
1049 return;
1050 }
1051 else
1052 {
1053 QModelIndex currentIndex;
1054
1055 if (currentBranch == d->rootTag)
1056 {
1057 currentIndex = QModelIndex();
1058 }
1059 else
1060 {
1061 currentIndex = createIndex(currentRow, 0, currentBranch);
1062 }
1063
1064 addSpacerTag(currentIndex,tagAddressElements[currentAddressElementIndex].tagName);
1065
1066 if ((tagAddressElements.count() - 1) > currentAddressElementIndex)
1067 {
1068 readdTag(currentBranch->spacerChildren[currentBranch->spacerChildren.count() - 1],
1069 currentBranch->spacerChildren.count() - 1,
1070 tagAddressElements,
1071 currentAddressElementIndex+1);
1072 }
1073 }
1074 }
1075 }
1076
readdNewTags(const QList<QList<TagData>> & tagAddressList)1077 void RGTagModel::readdNewTags(const QList<QList<TagData> >& tagAddressList)
1078 {
1079 for (int i = 0 ; i < tagAddressList.count() ; ++i)
1080 {
1081 QList<TagData> currentAddressTag = tagAddressList[i];
1082 readdTag(d->rootTag, 0, currentAddressTag, 0);
1083 }
1084 }
1085
getSpacerAddress(TreeBranch * currentBranch)1086 QList<TagData> RGTagModel::getSpacerAddress(TreeBranch* currentBranch)
1087 {
1088 QList<TagData> spacerAddress;
1089
1090 while (currentBranch->parent != nullptr)
1091 {
1092 TagData currentTag;
1093 currentTag.tagName = currentBranch->data;
1094 currentTag.tagType = currentBranch->type;
1095
1096 spacerAddress.prepend(currentTag);
1097 currentBranch = currentBranch->parent;
1098 }
1099
1100 return spacerAddress;
1101 }
1102
climbTreeAndGetSpacers(const TreeBranch * currentBranch)1103 void RGTagModel::climbTreeAndGetSpacers(const TreeBranch* currentBranch)
1104 {
1105 for (int i = 0 ; i < currentBranch->spacerChildren.count() ; ++i)
1106 {
1107 QList<TagData> currentSpacerAddress;
1108 currentSpacerAddress = getSpacerAddress(currentBranch->spacerChildren[i]);
1109 d->savedSpacerList.append(currentSpacerAddress);
1110 climbTreeAndGetSpacers(currentBranch->spacerChildren[i]);
1111 }
1112
1113 for (int i = 0 ; i < currentBranch->newChildren.count() ; ++i)
1114 {
1115 climbTreeAndGetSpacers(currentBranch->newChildren[i]);
1116 }
1117
1118 for (int i = 0 ; i < currentBranch->oldChildren.count() ; ++i)
1119 {
1120 climbTreeAndGetSpacers(currentBranch->oldChildren[i]);
1121 }
1122 }
1123
getSpacers()1124 QList<QList<TagData> > RGTagModel::getSpacers()
1125 {
1126 d->savedSpacerList.clear();
1127 climbTreeAndGetSpacers(d->rootTag);
1128
1129 return d->savedSpacerList;
1130 }
1131
addExternalTags(TreeBranch * parentBranch,int currentRow)1132 void RGTagModel::addExternalTags(TreeBranch* parentBranch, int currentRow)
1133 {
1134 QModelIndex parentIndex = createIndex(currentRow, 0, parentBranch);
1135 const int howManyRows = rowCount(parentIndex);
1136
1137 for (int i = 0 ; i < howManyRows ; ++i)
1138 {
1139 QModelIndex currentIndex = index(i,0,parentIndex);
1140 TreeBranch* const currentBranch = branchFromIndex(currentIndex); //currentIndex.isValid() ? static_cast<TreeBranch*>(currentIndex.internalPointer()) : d->rootTag;
1141
1142 if (currentBranch == d->rootTag)
1143 {
1144 return;
1145 }
1146
1147 addExternalTags(currentBranch,i);
1148 }
1149 }
1150
addAllExternalTagsToTreeView()1151 void RGTagModel::addAllExternalTagsToTreeView()
1152 {
1153 addExternalTags(d->rootTag, 0);
1154 }
1155
addAllSpacersToTag(const QModelIndex & currentIndex,const QStringList & spacerList,int spacerListIndex)1156 void RGTagModel::addAllSpacersToTag(const QModelIndex& currentIndex, const QStringList& spacerList, int spacerListIndex)
1157 {
1158 if (spacerListIndex >= spacerList.count())
1159 {
1160 return;
1161 }
1162 /*
1163 currentIndex.isValid() ? static_cast<TreeBranch*>(currentIndex.internalPointer()) : d->rootTag;
1164 */
1165 TreeBranch* const currentBranch = branchFromIndex(currentIndex);
1166
1167 for (int i = 0 ; i < currentBranch->spacerChildren.count() ; ++i)
1168 {
1169 if (currentBranch->data == spacerList[spacerListIndex])
1170 {
1171 QModelIndex foundIndex = createIndex(i, 0, currentBranch->spacerChildren[i]);
1172 addAllSpacersToTag(foundIndex, spacerList, spacerListIndex + 1);
1173
1174 return;
1175 }
1176 }
1177
1178 addSpacerTag(currentIndex, spacerList[spacerListIndex]);
1179 QModelIndex newIndex = createIndex(currentBranch->spacerChildren.count() - 1, 0,
1180 currentBranch->spacerChildren[currentBranch->spacerChildren.count() - 1]);
1181 addAllSpacersToTag(newIndex, spacerList, spacerListIndex + 1);
1182 }
1183
getTagType(const QModelIndex & index) const1184 Type RGTagModel::getTagType(const QModelIndex& index) const
1185 {
1186 /*
1187 index.isValid() ? static_cast<TreeBranch*>(index.internalPointer()) : d->rootTag;
1188 */
1189 const TreeBranch* const treeBranch = branchFromIndex(index);
1190
1191 return treeBranch->type;
1192 }
1193
translateSpacer(const QString & text) const1194 QString RGTagModel::translateSpacer(const QString& text) const
1195 {
1196 if (text == QLatin1String("{State}"))
1197 {
1198 return d->textState;
1199 }
1200 else if (text == QLatin1String("{LAU1}"))
1201 {
1202 return d->textLau1;
1203 }
1204 else if (text == QLatin1String("{LAU2}"))
1205 {
1206 return d->textLau2;
1207 }
1208
1209 return i18n(text.toUtf8().constData());
1210 }
1211
1212 } // namespace Digikam
1213