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