1 /**************************************************************************
2 ** This file is part of LiteIDE
3 **
4 ** Copyright (c) 2011-2017 LiteIDE. All rights reserved.
5 **
6 ** This library is free software; you can redistribute it and/or
7 ** modify it under the terms of the GNU Lesser General Public
8 ** License as published by the Free Software Foundation; either
9 ** version 2.1 of the License, or (at your option) any later version.
10 **
11 ** This library is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** Lesser General Public License for more details.
15 **
16 ** In addition, as a special exception,  that plugins developed for LiteIDE,
17 ** are allowed to remain closed sourced and can be distributed under any license .
18 ** These rights are included in the file LGPL_EXCEPTION.txt in this package.
19 **
20 **************************************************************************/
21 // Module: multiindexmodel.cpp
22 // Creator: visualfc <visualfc@gmail.com>
23 
24 #include "multiindexmodel.h"
25 
26 /****************************************************************************
27 **
28 ** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
29 ** Contact: http://www.qt-project.org/legal
30 **
31 ** This file is part of the QtGui module of the Qt Toolkit.
32 **
33 ** $QT_BEGIN_LICENSE:LGPL$
34 ** Commercial License Usage
35 ** Licensees holding valid commercial Qt licenses may use this file in
36 ** accordance with the commercial license agreement provided with the
37 ** Software or, alternatively, in accordance with the terms contained in
38 ** a written agreement between you and Digia.  For licensing terms and
39 ** conditions see http://qt.digia.com/licensing.  For further information
40 ** use the contact form at http://qt.digia.com/contact-us.
41 **
42 ** GNU Lesser General Public License Usage
43 ** Alternatively, this file may be used under the terms of the GNU Lesser
44 ** General Public License version 2.1 as published by the Free Software
45 ** Foundation and appearing in the file LICENSE.LGPL included in the
46 ** packaging of this file.  Please review the following information to
47 ** ensure the GNU Lesser General Public License version 2.1 requirements
48 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
49 **
50 ** In addition, as a special exception, Digia gives you certain additional
51 ** rights.  These rights are described in the Digia Qt LGPL Exception
52 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
53 **
54 ** GNU General Public License Usage
55 ** Alternatively, this file may be used under the terms of the GNU
56 ** General Public License version 3.0 as published by the Free Software
57 ** Foundation and appearing in the file LICENSE.GPL included in the
58 ** packaging of this file.  Please review the following information to
59 ** ensure the GNU General Public License version 3.0 requirements will be
60 ** met: http://www.gnu.org/copyleft/gpl.html.
61 **
62 **
63 ** $QT_END_LICENSE$
64 **
65 ****************************************************************************/
66 
67 #include "multiindexmodel_p.h"
68 
69 #include <QTime>
70 #include <QDebug>
71 
72 
73 class MultiIndexModelLessThan
74 {
75 public:
MultiIndexModelLessThan(int column,const QModelIndex & parent,const QAbstractItemModel * source,const MultiIndexModel * proxy)76     inline MultiIndexModelLessThan(int column, const QModelIndex &parent,
77                                        const QAbstractItemModel *source,
78                                        const MultiIndexModel *proxy)
79         : sort_column(column), source_parent(parent), source_model(source), proxy_model(proxy) {}
80 
operator ()(int r1,int r2) const81     inline bool operator()(int r1, int r2) const
82     {
83         QModelIndex i1 = source_model->index(r1, sort_column, source_parent);
84         QModelIndex i2 = source_model->index(r2, sort_column, source_parent);
85         return proxy_model->lessThan(source_model,i1, i2);
86     }
87 
88 private:
89     int sort_column;
90     QModelIndex source_parent;
91     const QAbstractItemModel *source_model;
92     const MultiIndexModel *proxy_model;
93 };
94 
95 class MultiIndexModelGreaterThan
96 {
97 public:
MultiIndexModelGreaterThan(int column,const QModelIndex & parent,const QAbstractItemModel * source,const MultiIndexModel * proxy)98     inline MultiIndexModelGreaterThan(int column, const QModelIndex &parent,
99                                           const QAbstractItemModel *source,
100                                           const MultiIndexModel *proxy)
101         : sort_column(column), source_parent(parent),
102           source_model(source), proxy_model(proxy) {}
103 
operator ()(int r1,int r2) const104     inline bool operator()(int r1, int r2) const
105     {
106         QModelIndex i1 = source_model->index(r1, sort_column, source_parent);
107         QModelIndex i2 = source_model->index(r2, sort_column, source_parent);
108         return proxy_model->lessThan(source_model,i2, i1);
109     }
110 
111 private:
112     int sort_column;
113     QModelIndex source_parent;
114     const QAbstractItemModel *source_model;
115     const MultiIndexModel *proxy_model;
116 };
117 
store_persistent_indexes(const QModelIndexList & persistentList)118 QModelIndexPairList MultiIndexModelPrivate::store_persistent_indexes(const QModelIndexList &persistentList)
119 {
120     Q_Q(MultiIndexModel);
121     QModelIndexPairList source_indexes;
122     foreach (QModelIndex proxy_index, persistentList) {
123         SourceModelIndex index = q->mapToSourceEx(proxy_index);
124         source_indexes.append(qMakePair(proxy_index, QPersistentModelIndex(index.index)));
125     }
126     return source_indexes;
127 }
128 
update_persistent_indexes(const QModelIndexPairList & source_indexes)129 void MultiIndexModelPrivate::update_persistent_indexes(const QModelIndexPairList &source_indexes)
130 {
131     Q_Q(MultiIndexModel);
132     QModelIndexList from, to;
133     for (int i = 0; i < source_indexes.count(); ++i) {
134         QModelIndex source_index = source_indexes.at(i).second;
135         QModelIndex old_proxy_index = source_indexes.at(i).first;
136         if (source_index.isValid()) {
137             QAbstractItemModel *model = (QAbstractItemModel *)source_index.model();
138             createMapping(model,source_index.parent(),false);
139             //createMapping(model,source_index,true);
140             QModelIndex proxy_index = q->mapFromSourceEx(model,source_index);
141             from << old_proxy_index;
142             to << proxy_index;
143         } else {
144             from << old_proxy_index;
145             to << QModelIndex();
146         }
147     }
148     q->changePersistentIndexList(from, to);
149 }
150 
151 
sort_source_rows(QAbstractItemModel * model,QVector<int> & source_rows,const QModelIndex & source_parent) const152 void MultiIndexModelPrivate::sort_source_rows(QAbstractItemModel *model,
153     QVector<int> &source_rows, const QModelIndex &source_parent) const
154 {
155     Q_Q(const MultiIndexModel);
156     if (source_sort_column >= 0) {
157         if (sort_order == Qt::AscendingOrder) {
158             MultiIndexModelLessThan lt(source_sort_column, source_parent, model, q);
159             qStableSort(source_rows.begin(), source_rows.end(), lt);
160         } else {
161             MultiIndexModelGreaterThan gt(source_sort_column, source_parent, model, q);
162             qStableSort(source_rows.begin(), source_rows.end(), gt);
163         }
164     } else { // restore the source model order
165         qStableSort(source_rows.begin(), source_rows.end());
166     }
167 }
168 
169 
170 /*!
171     \since 4.8
172     \class MultiIndexModel
173     \brief The MultiIndexModel class proxies its source model unmodified
174 
175     \ingroup model-view
176 
177     MultiIndexModel can be used to forward the structure of a source model exactly, with no sorting, filtering or other transformation.
178     This is similar in concept to an identity matrix where A.I = A.
179 
180     Because it does no sorting or filtering, this class is most suitable to proxy models which transform the data() of the source model.
181     For example, a proxy model could be created to define the font used, or the background colour, or the tooltip etc. This removes the
182     need to implement all data handling in the same class that creates the structure of the model, and can also be used to create
183     re-usable components.
184 
185     This also provides a way to change the data in the case where a source model is supplied by a third party which can not be modified.
186 
187     \snippet doc/src/snippets/code/src_gui_itemviews_MultiIndexModel.cpp 0
188 
189     \sa QAbstractProxyModel, {Model/View Programming}, QAbstractItemModel
190 
191 */
192 
193 /*!
194     Constructs an identity model with the given \a parent.
195 */
MultiIndexModel(QObject * parent)196 MultiIndexModel::MultiIndexModel(QObject* parent)
197   : AbstractMultiProxyModel(*new MultiIndexModelPrivate, parent)
198 {
199 
200 }
201 
202 /*! \internal
203  */
MultiIndexModel(MultiIndexModelPrivate & dd,QObject * parent)204 MultiIndexModel::MultiIndexModel(MultiIndexModelPrivate &dd, QObject* parent)
205   : AbstractMultiProxyModel(dd, parent)
206 {
207 
208 }
209 
lessThan(const QAbstractItemModel *,const QModelIndex & left,const QModelIndex & right) const210 bool MultiIndexModel::lessThan(const QAbstractItemModel */*sourceModel*/, const QModelIndex &left, const QModelIndex &right) const
211 {
212     Q_D(const MultiIndexModel);
213     QVariant l = (left.model() ? left.model()->data(left, d->sort_role) : QVariant());
214     QVariant r = (right.model() ? right.model()->data(right, d->sort_role) : QVariant());
215     switch (l.userType()) {
216     case QVariant::Invalid:
217         return (r.type() != QVariant::Invalid);
218     case QVariant::Int:
219         return l.toInt() < r.toInt();
220     case QVariant::UInt:
221         return l.toUInt() < r.toUInt();
222     case QVariant::LongLong:
223         return l.toLongLong() < r.toLongLong();
224     case QVariant::ULongLong:
225         return l.toULongLong() < r.toULongLong();
226     case QMetaType::Float:
227         return l.toFloat() < r.toFloat();
228     case QVariant::Double:
229         return l.toDouble() < r.toDouble();
230     case QVariant::Char:
231         return l.toChar() < r.toChar();
232     case QVariant::Date:
233         return l.toDate() < r.toDate();
234     case QVariant::Time:
235         return l.toTime() < r.toTime();
236     case QVariant::DateTime:
237         return l.toDateTime() < r.toDateTime();
238     case QVariant::String:
239     default:
240         if (d->sort_localeaware)
241             return l.toString().localeAwareCompare(r.toString()) < 0;
242         else
243             return l.toString().compare(r.toString(), d->sort_casesensitivity) < 0;
244     }
245     return false;
246 }
247 
filterAcceptsRow(const QAbstractItemModel *,int,const QModelIndex &) const248 bool MultiIndexModel::filterAcceptsRow(const QAbstractItemModel */*sourceModel*/, int /*source_row*/, const QModelIndex &/*source_parent*/) const
249 {
250     return true;
251 }
252 
253 /*!
254     Destroys this identity model.
255 */
~MultiIndexModel()256 MultiIndexModel::~MultiIndexModel()
257 {
258     Q_D(MultiIndexModel);
259     d->clearMapping();
260 }
261 
262 /*!
263     \reimp
264  */
columnCount(const QModelIndex & parent) const265 int MultiIndexModel::columnCount(const QModelIndex& parent) const
266 {
267     Q_ASSERT(parent.isValid() ? parent.model() == this : true);
268     Q_D(const MultiIndexModel);
269     if (d->indexList.isEmpty()) {
270         return 0;
271     }
272     SourceModelIndex source = mapToSourceEx(parent);
273     if (source.model == 0) {
274         return d->indexList[0].model->columnCount();
275     }
276     return source.model->columnCount(source.index);
277 }
278 
279 /*!
280     \reimp
281  */
dropMimeData(const QMimeData * data,Qt::DropAction action,int row,int column,const QModelIndex & parent)282 bool MultiIndexModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
283 {
284     //Q_ASSERT(parent.isValid() ? parent.model() == this : true);
285    // Q_D(MultiIndexModel);
286     SourceModelIndex source = mapToSourceEx(parent);
287     return source.model->dropMimeData(data, action, row, column,source.index);
288 }
289 
createMapping(QAbstractItemModel * model,const QModelIndex & parent,bool forceUpdate,const QString &) const290 QMap<QModelIndex,Mapping*>::iterator MultiIndexModelPrivate::createMapping(QAbstractItemModel *model, const QModelIndex &parent, bool forceUpdate, const QString &/*context*/) const
291 {
292     Q_Q(const MultiIndexModel);
293     QMap<QModelIndex,Mapping*>::iterator it = modelMapping[model].find(parent);
294     if (it == modelMapping[model].end()) {
295         Mapping *m = new Mapping;
296         m->rowCount = 0;
297         m->sourceParent = parent;
298         m->sourceModel = model;
299         it = modelMapping[model].insert(parent,m);
300         forceUpdate = true;
301     }
302     if (forceUpdate) {
303         Mapping *m = it.value();
304         int rowCount = model->rowCount(parent);
305 
306         //qDebug() << context << parent.data() << rowCount;
307         QVector<int> rows;
308         rows.reserve(rowCount);
309         for (int i = 0; i < rowCount; ++i) {
310             if (q->filterAcceptsRow(model,i, parent))
311                 rows.append(i);
312         }
313 //        for (int i = 0; i < rowCount; i++) {
314 //            rows[i] = i;
315 //        }
316         sort_source_rows(model,rows,parent);
317         m->rowCount = rowCount;
318         m->source_rows.swap(rows);
319         m->proxy_rows.resize(rowCount);
320         this->build_source_to_proxy_mapping(m->source_rows,m->proxy_rows);
321     }
322     return it;
323 }
324 
build_source_to_proxy_mapping(const QVector<int> & proxy_to_source,QVector<int> & source_to_proxy) const325 void MultiIndexModelPrivate::build_source_to_proxy_mapping(
326     const QVector<int> &proxy_to_source, QVector<int> &source_to_proxy) const
327 {
328     source_to_proxy.fill(-1);
329     int proxy_count = proxy_to_source.size();
330     for (int i = 0; i < proxy_count; ++i)
331         source_to_proxy[proxy_to_source.at(i)] = i;
332 }
333 
findOrCreateMapping(QAbstractItemModel * model,const QModelIndex & parent) const334 QMap<QModelIndex,Mapping*>::iterator MultiIndexModelPrivate::findOrCreateMapping(QAbstractItemModel *model, const QModelIndex &parent) const
335 {
336     QMap<QModelIndex,Mapping*>::iterator it = modelMapping[model].find(parent);
337     if (it == modelMapping[model].end()) {
338         it = createMapping(model,parent,true);
339     }
340     if (parent.isValid()) {
341         QModelIndex source_grand_parent = parent.parent();
342         findOrCreateMapping(model,source_grand_parent);
343     }
344     return it;
345 }
346 
clearMapping()347 void MultiIndexModelPrivate::clearMapping()
348 {
349     //Q_Q(MultiIndexModel);
350     QMutableMapIterator<QAbstractItemModel*, QMap<QModelIndex,Mapping*> > i(modelMapping);
351     while (i.hasNext()) {
352         i.next();
353         qDeleteAll(i.value());
354     }
355     modelMapping.clear();
356 }
357 
deleteMapping(QAbstractItemModel * model)358 void MultiIndexModelPrivate::deleteMapping(QAbstractItemModel *model)
359 {
360     QMutableMapIterator<QAbstractItemModel*, QMap<QModelIndex,Mapping*> > i(modelMapping);
361     while (i.hasNext()) {
362         i.next();
363         if (i.key() == model) {
364             qDeleteAll(i.value());
365             i.remove();
366             break;
367         }
368     }
369 }
370 
371 /*!
372     \reimp
373  */
index(int row,int column,const QModelIndex & parent) const374 QModelIndex MultiIndexModel::index(int row, int column, const QModelIndex& parent) const
375 {
376     Q_ASSERT(parent.isValid() ? parent.model() == this : true);
377     if (!hasIndex(row,column,parent)) {
378         return QModelIndex();
379     }
380     Q_D(const MultiIndexModel);
381     if (!parent.isValid()) {
382         if (row < d->indexList.size()) {
383             return createIndex(row,column);
384         }
385         return QModelIndex();
386     }
387     SourceModelIndex sourceParent = mapToSourceEx(parent);
388 
389     QMap<QModelIndex,Mapping*>::iterator it = d->createMapping(sourceParent.model,sourceParent.index,false,"index");
390 //    static int check = 1;
391 //    if (sourceParent.index.data() == "DataBase" && check) {
392 //        check = 0;
393 //        qDebug() << "index" << it.value()->source_rows << it.value()->proxy_rows;
394 //    }
395 //    QMap<QModelIndex,Mapping*>::iterator it = d->modelMapping[sourceParent.model].find(sourceParent.index);
396 //    if (it == d->modelMapping[sourceParent.model].end())  {
397 //        it = d->createMapping(sourceParent.model,sourceParent.index);
398 //    } else {
399 //        qDebug() << it.value()->proxy_rows;
400 //    }
401 
402     return createIndex(row,column,it.value());
403 }
404 
405 /*!
406     \reimp
407  */
insertColumns(int column,int count,const QModelIndex & parent)408 bool MultiIndexModel::insertColumns(int column, int count, const QModelIndex& parent)
409 {
410     //Q_ASSERT(parent.isValid() ? parent.model() == this : true);
411     //Q_D(MultiIndexModel);
412     SourceModelIndex source = mapToSourceEx(parent);
413     return source.model->insertColumns(column, count, source.index);
414 }
415 
416 /*!
417     \reimp
418  */
insertRows(int row,int count,const QModelIndex & parent)419 bool MultiIndexModel::insertRows(int row, int count, const QModelIndex& parent)
420 {
421     //Q_ASSERT(parent.isValid() ? parent.model() == this : true);
422     //Q_D(MultiIndexModel);
423     SourceModelIndex source = mapToSourceEx(parent);
424     return source.model->insertRows(row, count, source.index);
425 }
426 
427 
428 
429 /*!
430     \reimp
431  */
mapSelectionFromSource(const QItemSelection & selection) const432 QItemSelection MultiIndexModel::mapSelectionFromSource(const QItemSelection& selection) const
433 {
434     Q_D(const MultiIndexModel);
435     QItemSelection proxySelection;
436 
437     qDebug() << "mapSelectionFromSource";
438 
439     if (d->indexList.isEmpty())
440         return proxySelection;
441 
442     QItemSelection::const_iterator it = selection.constBegin();
443     const QItemSelection::const_iterator end = selection.constEnd();
444     for ( ; it != end; ++it) {
445         const QItemSelectionRange range(mapFromSource(it->topLeft()), mapFromSource(it->bottomRight()));
446         proxySelection.append(range);
447     }
448 
449     return proxySelection;
450 }
451 
452 /*!
453     \reimp
454  */
mapSelectionToSource(const QItemSelection & selection) const455 QItemSelection MultiIndexModel::mapSelectionToSource(const QItemSelection& selection) const
456 {
457     Q_D(const MultiIndexModel);
458     QItemSelection sourceSelection;
459 
460     qDebug() << "mapSelectionToSource";
461 
462     if (d->indexList.isEmpty())
463         return sourceSelection;
464 
465     QItemSelection::const_iterator it = selection.constBegin();
466     const QItemSelection::const_iterator end = selection.constEnd();
467     for ( ; it != end; ++it) {
468         //Q_ASSERT(it->model() == this);
469         const QItemSelectionRange range(mapToSource(it->topLeft()), mapToSource(it->bottomRight()));
470         sourceSelection.append(range);
471     }
472 
473     return sourceSelection;
474 }
475 
476 class MyModel : public QAbstractProxyModel
477 {
478     friend class MultiIndexModel;
479 };
480 
481 
482 /*!
483     \reimp
484  */
mapToSource(const QModelIndex & proxyIndex) const485 QModelIndex MultiIndexModel::mapToSource(const QModelIndex& proxyIndex) const
486 {
487     return mapToSourceEx(proxyIndex).index;
488 }
489 
mapToSourceEx(const QModelIndex & proxyIndex) const490 SourceModelIndex MultiIndexModel::mapToSourceEx(const QModelIndex &proxyIndex) const
491 {
492     Q_D(const MultiIndexModel);
493     if (!proxyIndex.isValid())
494         return SourceModelIndex();
495 
496     Q_ASSERT(proxyIndex.model() == this);
497 
498     Mapping *m = (Mapping*)proxyIndex.internalPointer();
499     if (m == 0) {
500         SourceModelIndex si = d->indexList[proxyIndex.row()];
501         si.index = si.index.sibling(si.index.row(),proxyIndex.column());
502         return si;
503     }
504     if (m->source_rows.size() <= proxyIndex.row()) {
505         return SourceModelIndex();
506     }
507 
508     int source_row = m->source_rows.at(proxyIndex.row());
509     //qDebug() << source_row;
510     QModelIndex index = m->sourceModel->index(source_row,proxyIndex.column(),m->sourceParent);
511     return SourceModelIndex(m->sourceModel,index);
512 }
513 
514 /*!
515     \reimp
516  */
mapFromSource(const QModelIndex & sourceIndex) const517 QModelIndex MultiIndexModel::mapFromSource(const QModelIndex& sourceIndex) const
518 {
519     //Q_D(const MultiIndexModel);
520     if (!sourceIndex.isValid())
521         return QModelIndex();
522     QAbstractItemModel *model = (QAbstractItemModel *)sourceIndex.model();
523     return mapFromSourceEx(model,sourceIndex);
524 }
525 
mapFromSourceEx(QAbstractItemModel * sourceModel,const QModelIndex & sourceIndex) const526 QModelIndex MultiIndexModel::mapFromSourceEx(QAbstractItemModel *sourceModel, const QModelIndex &sourceIndex) const
527 {
528     Q_D(const MultiIndexModel);
529     if (sourceModel == 0) {
530         return QModelIndex();
531     }
532     int row = d->isRootIndexRow(sourceModel,sourceIndex);
533     if (row >= 0) {
534         int column = sourceIndex.column();
535         if (column < 0) {
536             column = 0;
537         }
538         //d->createMapping(sourceModel,d->indexList[row].index);
539         return createIndex(row,column);
540     }
541 
542     if (!sourceIndex.isValid()) {
543         return QModelIndex();
544     }
545 
546     QModelIndex parent = sourceModel->parent(sourceIndex);
547 
548     QMap<QModelIndex,Mapping*>::iterator it = d->createMapping(sourceModel,parent,false,"map");// d->modelMapping[sourceModel].find(parent);
549 //    if (it == d->modelMapping[sourceModel].end()) {
550 //        it = d->createMapping(sourceModel,parent);
551 //    }
552     Mapping *m = it.value();
553 
554     if (m->proxy_rows.size() <= sourceIndex.row()) {
555         return QModelIndex();
556     }
557 
558     int proxy_row = m->proxy_rows.at(sourceIndex.row());
559    // qDebug() << sourceIndex.data() << proxy_row;
560     return createIndex(proxy_row,sourceIndex.column(),m);
561     //return QModelIndex();
562 }
563 
hasChildren(const QModelIndex & parent) const564 bool MultiIndexModel::hasChildren(const QModelIndex &parent) const
565 {
566     Q_D(const MultiIndexModel);
567     if (!parent.isValid()) {
568         return !d->indexList.isEmpty();
569     }
570 
571     SourceModelIndex source = mapToSourceEx(parent);
572     if (source.model == 0) {
573         return false;
574     }
575 //    //if (parent.isValid() && !source.index.isValid())
576 //    //    return false;
577     if (!source.model->hasChildren(source.index))
578         return false;
579 
580     if (source.model->canFetchMore(source.index))
581         return true; //we assume we might have children that can be fetched
582 
583     return true;
584    // Mapping *m = d->createMapping(source.model,source.index,false,"hasChildren").value();
585    // return m->source_rows.count() != 0;
586 }
587 
buddy(const QModelIndex & index) const588 QModelIndex MultiIndexModel::buddy(const QModelIndex &index) const
589 {
590     Q_D(const MultiIndexModel);
591     if (!d->indexValid(index))
592         return QModelIndex();
593 
594     SourceModelIndex source = mapToSourceEx(index);
595     QModelIndex source_buddy = source.model->buddy(source.index);
596     if (source.index == source_buddy)
597         return index;
598     return mapFromSourceEx(source.model,source_buddy);
599 }
600 
601 
602 /*!
603     \reimp
604  */
match(const QModelIndex & start,int role,const QVariant & value,int hits,Qt::MatchFlags flags) const605 QModelIndexList MultiIndexModel::match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const
606 {
607     Q_D(const MultiIndexModel);
608     Q_ASSERT(start.isValid() ? start.model() == this : true);
609     if (d->indexList.isEmpty())
610         return QModelIndexList();
611 
612     SourceModelIndex source = mapToSourceEx(start);
613     const QModelIndexList sourceList = source.model->match(source.index, role, value, hits, flags);
614     QModelIndexList::const_iterator it = sourceList.constBegin();
615     const QModelIndexList::const_iterator end = sourceList.constEnd();
616     QModelIndexList proxyList;
617     for ( ; it != end; ++it)
618         proxyList.append(mapFromSourceEx(source.model,*it));
619     return proxyList;
620 }
621 
622 /*!
623     \reimp
624  */
parent(const QModelIndex & child) const625 QModelIndex MultiIndexModel::parent(const QModelIndex& child) const
626 {
627     Q_ASSERT(child.isValid() ? child.model() == this : true);
628     //Q_D(const MultiIndexModel);
629     if (!child.isValid()) {
630         return QModelIndex();
631     }
632 //    SourceModelIndex index = this->mapToSourceEx(child);
633 //    if (index.model == 0) {
634 //        return QModelIndex();
635 //    }
636 //    return mapFromSourceEx(index.model,index.index.parent());
637     Mapping *m = (Mapping*)child.internalPointer();
638     if (m == 0) {
639         return QModelIndex();
640     }
641 //    if (m->sourceModel != child.model()) {
642 //        qDebug() << "error parent" << child;
643 //    }
644     //qDebug() << m->sourceParent.data().toString();
645     return mapFromSourceEx(m->sourceModel,m->sourceParent);
646 //    const QModelIndex sourceIndex = mapToSource(child);
647 //    foreach (QModelIndex index, d->indexList) {
648 //        if (index == sourceIndex) {
649 //            return QModelIndex();
650 //        }
651 //    }
652 //    const QModelIndex sourceParent = sourceIndex.parent();
653 //    return mapFromSource(sourceParent);
654 }
655 
656 /*
657 QModelIndex MultiProxyModel::parent(const QModelIndex &child) const
658 {
659     Q_D(const MultiProxyModel);
660     if (!d->indexValid(child))
661         return QModelIndex();
662     IndexMap::const_iterator it = d->index_to_iterator(child);
663     Q_ASSERT(it != d->source_index_mapping.constEnd());
664     QModelIndex source_parent = it.key();
665     QModelIndex proxy_parent = mapFromSource(source_parent);
666     return proxy_parent;
667 }
668 */
669 
670 /*!
671     \reimp
672  */
removeColumns(int column,int count,const QModelIndex & parent)673 bool MultiIndexModel::removeColumns(int column, int count, const QModelIndex& parent)
674 {
675     //Q_ASSERT(parent.isValid() ? parent.model() == this : true);
676     //Q_D(MultiIndexModel);
677     SourceModelIndex source = mapToSourceEx(parent);
678     return source.model->removeColumns(column, count, source.index);
679 }
680 
681 /*!
682     \reimp
683  */
removeRows(int row,int count,const QModelIndex & parent)684 bool MultiIndexModel::removeRows(int row, int count, const QModelIndex& parent)
685 {
686    // Q_ASSERT(parent.isValid() ? parent.model() == this : true);
687     //Q_D(MultiIndexModel);
688     SourceModelIndex source = mapToSourceEx(parent);
689     return source.model->removeRows(row, count, source.index);
690 }
691 
692 /*!
693     \reimp
694  */
rowCount(const QModelIndex & parent) const695 int MultiIndexModel::rowCount(const QModelIndex& parent) const
696 {
697     Q_D(const MultiIndexModel);
698     if (!parent.isValid()) {
699         return d->indexList.size();
700     }
701     //qDebug() << parent.isValid() << parent.data().toString();
702     //Q_ASSERT(parent.isValid() ? parent.model() == this : true);
703      SourceModelIndex source = mapToSourceEx(parent);
704      //return source.model->rowCount(source.index);
705      QMap<QModelIndex,Mapping*>::iterator it = d->createMapping(source.model,source.index,false,"rowCount");
706      return it.value()->source_rows.count();
707      //qDebug() << source.model->rowCount(source.index);
708 //     return source.model->rowCount(source.index);
709 //     QMap<QModelIndex,Mapping*>::iterator it = d->createMapping(source.model,source.index);
710 //     qDebug() << parent.column() << parent << source.index << source.index.data() <<  it.value()->source_rows;
711 //     return it.value()->source_rows.count();
712     //qDebug() << source_parent.isValid();
713 //     int rows = d->model->rowCount(source_parent);
714 //     qDebug() << "rowCount" << rows << source_parent.data().toString();
715 //     return rows;
716 //    QModelIndex source_parent = mapToSource(parent);
717 //    qDebug() << source_parent.isValid();
718 //    if (parent.isValid() && !source_parent.isValid())
719 //        return 0;
720 //    QMap<QModelIndex,Mapping*>::iterator it = d->findOrCreateMapping(source_parent);
721 //    return it.value()->source_rows.count();
722 }
723 
724 /*!
725     \reimp
726  */
addSourceModel(QAbstractItemModel * sourceModel,const QModelIndex & sourceIndex)727 bool MultiIndexModel::addSourceModel(QAbstractItemModel* sourceModel, const QModelIndex &sourceIndex)
728 {
729     Q_D(MultiIndexModel);
730     if (!sourceModel || d->containsModel(sourceModel) ) {
731         return false;
732     }
733 
734     int n = d->indexList.size();
735 
736     this->beginInsertRows(QModelIndex(),n,n);
737 
738     AbstractMultiProxyModel::addSourceModel(sourceModel,sourceIndex);
739 
740     //beginResetModel();
741 
742     connect(sourceModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
743             d_func(),SLOT(_q_sourceRowsAboutToBeInserted(const QModelIndex &, int, int)));
744     connect(sourceModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
745             d_func(),SLOT(_q_sourceRowsInserted(const QModelIndex &, int, int)));
746     connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
747             d_func(),SLOT(_q_sourceRowsAboutToBeRemoved(const QModelIndex &, int, int)));
748     connect(sourceModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
749             d_func(),SLOT(_q_sourceRowsRemoved(const QModelIndex &, int, int)));
750     connect(sourceModel, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
751             d_func(),SLOT(_q_sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
752     connect(sourceModel, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
753             d_func(),SLOT(_q_sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
754     connect(sourceModel, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)),
755             d_func(),SLOT(_q_sourceColumnsAboutToBeInserted(const QModelIndex &, int, int)));
756     connect(sourceModel, SIGNAL(columnsInserted(const QModelIndex &, int, int)),
757             d_func(),SLOT(_q_sourceColumnsInserted(const QModelIndex &, int, int)));
758     connect(sourceModel, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
759             d_func(),SLOT(_q_sourceColumnsAboutToBeRemoved(const QModelIndex &, int, int)));
760     connect(sourceModel, SIGNAL(columnsRemoved(const QModelIndex &, int, int)),
761             d_func(),SLOT(_q_sourceColumnsRemoved(const QModelIndex &, int, int)));
762     connect(sourceModel, SIGNAL(columnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
763             d_func(),SLOT(_q_sourceColumnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
764     connect(sourceModel, SIGNAL(columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
765             d_func(),SLOT(_q_sourceColumnsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
766     connect(sourceModel, SIGNAL(modelAboutToBeReset()),
767             d_func(),SLOT(_q_sourceModelAboutToBeReset()));
768     connect(sourceModel, SIGNAL(modelReset()),
769             d_func(),SLOT(_q_sourceModelReset()));
770     connect(sourceModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
771             d_func(),SLOT(_q_sourceDataChanged(const QModelIndex &, const QModelIndex &)));
772     connect(sourceModel, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
773             d_func(),SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int)));
774     connect(sourceModel, SIGNAL(layoutAboutToBeChanged()),
775             d_func(),SLOT(_q_sourceLayoutAboutToBeChanged()));
776     connect(sourceModel, SIGNAL(layoutChanged()),
777             d_func(),SLOT(_q_sourceLayoutChanged()));
778 
779     //endResetModel();
780     this->endInsertRows();
781 
782     return true;
783 }
784 
removeSourceModel(QAbstractItemModel * sourceModel)785 bool MultiIndexModel::removeSourceModel(QAbstractItemModel *sourceModel)
786 {
787     Q_D(MultiIndexModel);
788     bool b = AbstractMultiProxyModel::removeSourceModel(sourceModel);
789     if (b) {
790         d->deleteMapping(sourceModel);
791     }
792     return b;
793 }
794 
removeAllSourceModel()795 void MultiIndexModel::removeAllSourceModel()
796 {
797     Q_D(MultiIndexModel);
798     AbstractMultiProxyModel::removeAllSourceModel();
799     d->clearMapping();
800 }
801 
sort(int column,Qt::SortOrder order)802 void MultiIndexModel::sort(int column, Qt::SortOrder order)
803 {
804     Q_D(MultiIndexModel);
805     d->sort_order = order;
806     d->source_sort_column = column;
807 }
808 
setSortRole(int role)809 void MultiIndexModel::setSortRole(int role)
810 {
811     Q_D(MultiIndexModel);
812     d->sort_role = role;
813 }
814 
sortCaseSensitivity() const815 Qt::CaseSensitivity MultiIndexModel::sortCaseSensitivity() const
816 {
817     Q_D(const MultiIndexModel);
818     return d->sort_casesensitivity;
819 }
820 
setSortCaseSensitivity(Qt::CaseSensitivity cs)821 void MultiIndexModel::setSortCaseSensitivity(Qt::CaseSensitivity cs)
822 {
823     Q_D(MultiIndexModel);
824     d->sort_casesensitivity = cs;
825 }
826 
isSortLocaleAware() const827 bool MultiIndexModel::isSortLocaleAware() const
828 {
829     Q_D(const MultiIndexModel);
830     return d->sort_localeaware;
831 }
832 
setSortLocaleAware(bool on)833 void MultiIndexModel::setSortLocaleAware(bool on)
834 {
835     Q_D(MultiIndexModel);
836     d->sort_localeaware = on;
837 }
838 
sortRole() const839 int MultiIndexModel::sortRole() const
840 {
841     Q_D(const MultiIndexModel);
842     return d->sort_role;
843 }
844 
_q_sourceColumnsAboutToBeInserted(const QModelIndex & parent,int start,int end)845 void MultiIndexModelPrivate::_q_sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end)
846 {
847     //Q_ASSERT(parent.isValid() ? parent.model() == model : true);
848     Q_Q(MultiIndexModel);
849     QAbstractItemModel *model = (QAbstractItemModel*)sender();
850     q->beginInsertColumns(q->mapFromSourceEx(model,parent), start, end);
851 }
852 
_q_sourceColumnsAboutToBeMoved(const QModelIndex & sourceParent,int sourceStart,int sourceEnd,const QModelIndex & destParent,int dest)853 void MultiIndexModelPrivate::_q_sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
854 {
855     //Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true);
856     //Q_ASSERT(destParent.isValid() ? destParent.model() == model : true);
857     Q_Q(MultiIndexModel);
858     QAbstractItemModel *model = (QAbstractItemModel*)sender();
859     q->beginMoveColumns(q->mapFromSourceEx(model,sourceParent), sourceStart, sourceEnd, q->mapFromSourceEx(model,destParent), dest);
860 }
861 
_q_sourceColumnsAboutToBeRemoved(const QModelIndex & parent,int start,int end)862 void MultiIndexModelPrivate::_q_sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
863 {
864     //Q_ASSERT(parent.isValid() ? parent.model() == model : true);
865     Q_Q(MultiIndexModel);
866     QAbstractItemModel *model = (QAbstractItemModel*)sender();
867     q->beginRemoveColumns(q->mapFromSourceEx(model,parent), start, end);
868 }
869 
_q_sourceColumnsInserted(const QModelIndex & parent,int start,int end)870 void MultiIndexModelPrivate::_q_sourceColumnsInserted(const QModelIndex &parent, int start, int end)
871 {
872     //Q_ASSERT(parent.isValid() ? parent.model() == model : true);
873     Q_Q(MultiIndexModel);
874     Q_UNUSED(parent)
875     Q_UNUSED(start)
876     Q_UNUSED(end)
877     q->endInsertColumns();
878 }
879 
_q_sourceColumnsMoved(const QModelIndex & sourceParent,int sourceStart,int sourceEnd,const QModelIndex & destParent,int dest)880 void MultiIndexModelPrivate::_q_sourceColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
881 {
882     //Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true);
883     //Q_ASSERT(destParent.isValid() ? destParent.model() == model : true);
884     Q_Q(MultiIndexModel);
885     Q_UNUSED(sourceParent)
886     Q_UNUSED(sourceStart)
887     Q_UNUSED(sourceEnd)
888     Q_UNUSED(destParent)
889     Q_UNUSED(dest)
890 
891     q->endMoveColumns();
892 }
893 
_q_sourceColumnsRemoved(const QModelIndex & parent,int start,int end)894 void MultiIndexModelPrivate::_q_sourceColumnsRemoved(const QModelIndex &parent, int start, int end)
895 {
896     //Q_ASSERT(parent.isValid() ? parent.model() == model : true);
897     Q_Q(MultiIndexModel);
898     Q_UNUSED(parent)
899     Q_UNUSED(start)
900     Q_UNUSED(end)
901     q->endRemoveColumns();
902 }
903 
_q_sourceDataChanged(const QModelIndex & topLeft,const QModelIndex & bottomRight)904 void MultiIndexModelPrivate::_q_sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
905 {
906     //Q_ASSERT(topLeft.isValid() ? topLeft.model() == model : true);
907     //Q_ASSERT(bottomRight.isValid() ? bottomRight.model() == model : true);
908     Q_Q(MultiIndexModel);
909 
910     QAbstractItemModel *model = (QAbstractItemModel*)sender();
911     q->dataChanged(q->mapFromSourceEx(model,topLeft), q->mapFromSourceEx(model,bottomRight));
912 }
913 
_q_sourceHeaderDataChanged(Qt::Orientation orientation,int first,int last)914 void MultiIndexModelPrivate::_q_sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last)
915 {
916     Q_Q(MultiIndexModel);
917     q->headerDataChanged(orientation, first, last);
918 }
919 
_q_sourceLayoutAboutToBeChanged()920 void MultiIndexModelPrivate::_q_sourceLayoutAboutToBeChanged()
921 {
922 //    if (ignoreNextLayoutAboutToBeChanged)
923 //        return;
924 
925 //    Q_Q(MultiIndexModel);
926 
927 //    foreach(const QPersistentModelIndex &proxyPersistentIndex, q->persistentIndexList()) {
928 //        proxyIndexes << proxyPersistentIndex;
929 //        Q_ASSERT(proxyPersistentIndex.isValid());
930 //        const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
931 //        Q_ASSERT(srcPersistentIndex.isValid());
932 //        layoutChangePersistentIndexes << srcPersistentIndex;
933 //    }
934 
935 //    q->layoutAboutToBeChanged();
936     Q_Q(MultiIndexModel);
937     saved_persistent_indexes.clear();
938     emit q->layoutAboutToBeChanged();
939     QModelIndexList persistentList = q->persistentIndexList();
940     if (persistentList.isEmpty())
941         return;
942 
943 //    QAbstractItemModel *model = (QAbstractItemModel*)sender();
944 //    qDebug() << "begin changed" << model;
945     saved_persistent_indexes = store_persistent_indexes(persistentList);
946 }
947 
_q_sourceLayoutChanged()948 void MultiIndexModelPrivate::_q_sourceLayoutChanged()
949 {
950     Q_Q(MultiIndexModel);
951 
952 
953     QAbstractItemModel *model = (QAbstractItemModel*)sender();
954 
955  //   qDebug() << "changed" << model;
956 
957     qDeleteAll(modelMapping[model]);
958     modelMapping[model].clear();
959     //modelMapping.remove(model);
960     update_persistent_indexes(saved_persistent_indexes);
961     saved_persistent_indexes.clear();
962 ////    if (dynamic_sortfilter && update_source_sort_column()) {
963 ////        //update_source_sort_column might have created wrong mapping so we have to clear it again
964 // //       qDeleteAll(sourceMapping);
965 ////        sourceMapping.clear();
966 ////    }
967 
968 //    emit q->layoutChanged();
969 //    if (ignoreNextLayoutChanged)
970 //        return;
971 
972  //   Q_Q(MultiIndexModel);
973 
974 //    for (int i = 0; i < proxyIndexes.size(); ++i) {
975 //        q->changePersistentIndex(proxyIndexes.at(i), q->mapFromSource(layoutChangePersistentIndexes.at(i)));
976 //    }
977 
978 //    layoutChangePersistentIndexes.clear();
979 //    proxyIndexes.clear();
980 
981     q->layoutChanged();
982 }
983 
_q_sourceModelAboutToBeReset()984 void MultiIndexModelPrivate::_q_sourceModelAboutToBeReset()
985 {
986     Q_Q(MultiIndexModel);
987     q->beginResetModel();
988 }
989 
_q_sourceModelReset()990 void MultiIndexModelPrivate::_q_sourceModelReset()
991 {
992     Q_Q(MultiIndexModel);
993 
994     q->endResetModel();
995 }
996 
sort(QAbstractItemModel * sourceModel)997 void MultiIndexModelPrivate::sort(QAbstractItemModel *sourceModel )
998 {
999     Q_Q(MultiIndexModel);
1000     emit q->layoutAboutToBeChanged();
1001     QModelIndexPairList source_indexes = store_persistent_indexes(q->persistentIndexList());
1002     QMap<QModelIndex,Mapping*>::const_iterator it = modelMapping[sourceModel].constBegin();
1003     for (; it != modelMapping[sourceModel].constEnd(); ++it) {
1004         QModelIndex source_parent = it.key();
1005         Mapping *m = it.value();
1006         sort_source_rows(m->sourceModel, m->source_rows, source_parent);
1007         build_source_to_proxy_mapping(m->source_rows, m->proxy_rows);
1008     }
1009     update_persistent_indexes(source_indexes);
1010     emit q->layoutChanged();
1011 }
1012 
_q_sourceRowsAboutToBeInserted(const QModelIndex & parent,int,int)1013 void MultiIndexModelPrivate::_q_sourceRowsAboutToBeInserted(const QModelIndex &parent, int /*start*/, int /*end*/)
1014 {
1015     //Q_ASSERT(parent.isValid() ? parent.model() == model : true);
1016     //Q_Q(MultiIndexModel);
1017     QAbstractItemModel *model = (QAbstractItemModel *)sender();
1018     QMap<QModelIndex,Mapping*>::iterator it = modelMapping[model].find(parent);
1019     if (it == modelMapping[model].end()) {
1020         //this->createMapping(model,parent,false,"insert");
1021     }
1022 }
1023 
_q_sourceRowsAboutToBeMoved(const QModelIndex & sourceParent,int sourceStart,int sourceEnd,const QModelIndex & destParent,int dest)1024 void MultiIndexModelPrivate::_q_sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
1025 {
1026     //Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true);
1027     //Q_ASSERT(destParent.isValid() ? destParent.model() == model : true);
1028     Q_Q(MultiIndexModel);
1029     QAbstractItemModel *model = (QAbstractItemModel *)sender();
1030 
1031     q->beginMoveRows(q->mapFromSourceEx(model,sourceParent), sourceStart, sourceEnd, q->mapFromSourceEx(model,destParent), dest);
1032 }
1033 
_q_sourceRowsInserted(const QModelIndex & parent,int start,int end)1034 void MultiIndexModelPrivate::_q_sourceRowsInserted(const QModelIndex &parent, int start, int end)
1035 {
1036     //Q_ASSERT(parent.isValid() ? parent.model() == model : true);
1037     Q_Q(MultiIndexModel);
1038     Q_UNUSED(parent)
1039     Q_UNUSED(start)
1040     Q_UNUSED(end)
1041 
1042     QAbstractItemModel *model = (QAbstractItemModel *)sender();
1043     QMap<QModelIndex,Mapping*>::iterator it = modelMapping[model].find(parent);
1044     if (it != modelMapping[model].end()) {
1045         this->createMapping(model,parent,true,"insert");
1046         Mapping *m = it.value();
1047         QModelIndex proxyIndex = q->mapFromSourceEx(model,parent);
1048         QVector<int> all(end-start+1);
1049         for (int i = start; i <= end; i++) {
1050             all[i-start] = m->proxy_rows.at(i);
1051             //qDebug() << m->sourceModel->index(i,0,parent).data();
1052         }
1053         qStableSort(all);
1054 
1055         if (all.last()-all.first()+1 == all.size()) {
1056             q->beginInsertRows(proxyIndex,all.first(),all.last());
1057             q->endInsertRows();
1058         } else {
1059             foreach (int n, all) {
1060                 q->beginInsertRows(proxyIndex, n, n);
1061                 q->endInsertRows();
1062             }
1063         }
1064     }
1065 }
1066 
_q_sourceRowsMoved(const QModelIndex & sourceParent,int sourceStart,int sourceEnd,const QModelIndex & destParent,int dest)1067 void MultiIndexModelPrivate::_q_sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
1068 {
1069     //Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true);
1070     //Q_ASSERT(destParent.isValid() ? destParent.model() == model : true);
1071     Q_Q(MultiIndexModel);
1072     Q_UNUSED(sourceParent)
1073     Q_UNUSED(sourceStart)
1074     Q_UNUSED(sourceEnd)
1075     Q_UNUSED(destParent)
1076     Q_UNUSED(dest)
1077 
1078     //todo
1079     q->endMoveRows();
1080 }
1081 
_q_sourceRowsAboutToBeRemoved(const QModelIndex & parent,int start,int end)1082 void MultiIndexModelPrivate::_q_sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
1083 {
1084     //Q_ASSERT(parent.isValid() ? parent.model() == model : true);
1085     Q_Q(MultiIndexModel);
1086 
1087     QAbstractItemModel *model = (QAbstractItemModel *)sender();
1088     QMap<QModelIndex,Mapping*>::iterator it = modelMapping[model].find(parent);
1089     if (it != modelMapping[model].end()) {
1090         Mapping *m = it.value();
1091 
1092         int n1 = m->proxy_rows.at(start);
1093         int n2 = m->proxy_rows.at(end);
1094         if (n1 > n2) {
1095             qSwap(n1,n2);
1096         }
1097         for (int i = start; i < end+1; i++) {
1098             QModelIndex child = m->sourceModel->index(i,0,m->sourceParent);
1099             QMap<QModelIndex,Mapping*>::iterator childIt = modelMapping[model].find(child);
1100             if (childIt != modelMapping[model].end()) {
1101                 Mapping *cm = childIt.value();
1102                 cm->sourceParent = QModelIndex();
1103                 modelMapping[model].remove(child);
1104                 removeMappingList.append(cm);
1105             }
1106         }
1107         q->beginRemoveRows(q->mapFromSourceEx(model,parent), n1,n2);
1108     }
1109 }
1110 
_q_sourceRowsRemoved(const QModelIndex & parent,int start,int end)1111 void MultiIndexModelPrivate::_q_sourceRowsRemoved(const QModelIndex &parent, int start, int end)
1112 {
1113     //Q_ASSERT(parent.isValid() ? parent.model() == model : true);
1114     Q_Q(MultiIndexModel);
1115     Q_UNUSED(parent)
1116     Q_UNUSED(start)
1117     Q_UNUSED(end)
1118 
1119     //update
1120     QAbstractItemModel *model = (QAbstractItemModel *)sender();
1121     QMap<QModelIndex,Mapping*>::iterator it = modelMapping[model].find(parent);
1122     if (it != modelMapping[model].end()) {
1123         this->createMapping(model,parent,true);
1124         q->endRemoveRows();
1125     }
1126 }
1127 
1128 
1129 #include "moc_multiindexmodel.cpp"
1130 //lite_memory_check_begin
1131 #if defined(WIN32) && defined(_MSC_VER) &&  defined(_DEBUG)
1132      #define _CRTDBG_MAP_ALLOC
1133      #include <stdlib.h>
1134      #include <crtdbg.h>
1135      #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
1136      #define new DEBUG_NEW
1137 #endif
1138 //lite_memory_check_end
1139 
1140