1 /**************************************************************************
2 ** This file is part of LiteIDE
3 **
4 ** Copyright (c) 2011-2019 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: folderlistmodel.cpp
22 // Creator: visualfc <visualfc@gmail.com>
23 
24 #include "folderlistmodel.h"
25 #include "filesystemmodelex.h"
26 #include <QFileSystemWatcher>
27 #include <QDebug>
28 //lite_memory_check_begin
29 #if defined(WIN32) && defined(_MSC_VER) &&  defined(_DEBUG)
30      #define _CRTDBG_MAP_ALLOC
31      #include <stdlib.h>
32      #include <crtdbg.h>
33      #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
34      #define new DEBUG_NEW
35 #endif
36 //lite_memory_check_end
37 
FolderListModel(QObject * parent)38 FolderListModel::FolderListModel(QObject *parent) :
39     QAbstractItemModel(parent)
40 {
41     ignoreNextLayoutAboutToBeChanged = false;
42     ignoreNextLayoutChanged = false;
43     m_filters = QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs;
44     m_resolveSymlinks = false;
45     m_nameFilterDisables = true;
46     m_bWatcherRoot = false;
47 }
48 
~FolderListModel()49 FolderListModel::~FolderListModel()
50 {
51     clear();
52 }
53 
clear()54 void FolderListModel::clear()
55 {
56     if (m_modelList.isEmpty()) {
57         return;
58     }
59     this->beginRemoveRows(QModelIndex(),0,m_modelList.size());
60     this->removeRows(0,m_modelList.size());
61     if (m_bWatcherRoot) {
62         foreach (SourceModel s, m_modelList) {
63             m_watcher->removePath(s.watchPath);
64             delete s.model;
65         }
66     }
67     m_modelList.clear();
68     m_indexMap.clear();
69     this->endRemoveRows();
70 }
71 
addRootPath(const QString & path)72 QModelIndex FolderListModel::addRootPath(const QString &path)
73 {
74     if (!QDir(path).exists()) {
75         return QModelIndex();
76     }
77     FileSystemModelEx *model = new FileSystemModelEx(this);
78     model->setFilter(m_filters);
79     if (!m_nameFilters.isEmpty()) {
80         model->setNameFilters(m_nameFilters);
81     }
82     model->setNameFilterDisables(m_nameFilterDisables);
83     model->setResolveSymlinks(m_resolveSymlinks);
84     QModelIndex sourceIndex = model->setRootPath(path);
85     if (!sourceIndex.isValid()) {
86         return sourceIndex;
87     }
88     SourceModel m;
89     m.model = model;
90     m.rootPath = QDir::cleanPath(QDir::fromNativeSeparators(path));
91     m.watchPath = model->filePath(sourceIndex.parent());
92     if (m_bWatcherRoot) {
93         if (!m_watcher->directories().contains(m.watchPath)) {
94             m_watcher->addPath(m.watchPath);
95         }
96     }
97     m.rootSourceIndex = sourceIndex;
98     m.rootIndex = createIndex(m_modelList.size(),0,sourceIndex.internalPointer());
99     m_indexMap.insert(sourceIndex.internalId(),model);
100     m_modelList.append(m);
101 
102     connect(model, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
103             SLOT(sourceRowsAboutToBeInserted(const QModelIndex &, int, int)));
104     connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
105             SLOT(sourceRowsInserted(const QModelIndex &, int, int)));
106     connect(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
107             SLOT(sourceRowsAboutToBeRemoved(const QModelIndex &, int, int)));
108     connect(model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
109             SLOT(sourceRowsRemoved(const QModelIndex &, int, int)));
110     connect(model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
111             SLOT(sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
112     connect(model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
113             SLOT(sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
114     connect(model, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)),
115             SLOT(sourceColumnsAboutToBeInserted(const QModelIndex &, int, int)));
116     connect(model, SIGNAL(columnsInserted(const QModelIndex &, int, int)),
117             SLOT(sourceColumnsInserted(const QModelIndex &, int, int)));
118     connect(model, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
119             SLOT(sourceColumnsAboutToBeRemoved(const QModelIndex &, int, int)));
120     connect(model, SIGNAL(columnsRemoved(const QModelIndex &, int, int)),
121             SLOT(sourceColumnsRemoved(const QModelIndex &, int, int)));
122     connect(model, SIGNAL(columnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
123             SLOT(sourceColumnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
124     connect(model, SIGNAL(columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
125             SLOT(sourceColumnsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
126     connect(model, SIGNAL(modelAboutToBeReset()),
127             SLOT(sourceModelAboutToBeReset()));
128     connect(model, SIGNAL(modelReset()),
129             SLOT(sourceModelReset()));
130     connect(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
131             SLOT(sourceDataChanged(const QModelIndex &, const QModelIndex &)));
132     connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
133             SLOT(sourceHeaderDataChanged(Qt::Orientation,int,int)));
134     connect(model, SIGNAL(layoutAboutToBeChanged()),
135             SLOT(sourceLayoutAboutToBeChanged()));
136     connect(model, SIGNAL(layoutChanged()),
137             SLOT(sourceLayoutChanged()));
138     return m.rootIndex;
139 }
140 
removeRootPath(const QString & path)141 void FolderListModel::removeRootPath(const QString &path)
142 {
143     QString rootPath = QDir::cleanPath(QDir::fromNativeSeparators(path));
144     QModelIndex index;
145     foreach (SourceModel s, m_modelList) {
146         if (s.rootPath == rootPath) {
147             index = s.rootIndex;
148             break;
149         }
150     }
151     if (index.isValid()) {
152         removeRoot(index);
153     }
154 }
155 
removeRoot(const QModelIndex & index)156 void FolderListModel::removeRoot(const QModelIndex &index)
157 {
158     QMutableListIterator<SourceModel> i(m_modelList);
159     while (i.hasNext()) {
160         SourceModel s = i.next();
161         if (s.rootIndex.internalId() == index.internalId()) {
162             this->beginRemoveRows(QModelIndex(),index.row(),index.row());
163             if (m_bWatcherRoot) {
164                 int n = 0;
165                 foreach (SourceModel m, m_modelList) {
166                     if (m.watchPath == s.watchPath) {
167                         n++;
168                     }
169                 }
170                 if (n <= 1) {
171                     m_watcher->removePath(s.watchPath);
172                 }
173             }
174             this->removeRow(index.row());
175             i.remove();
176             this->endRemoveRows();
177             QMutableHashIterator<qint64,QAbstractItemModel*> i2(m_indexMap);
178             while (i2.hasNext()) {
179                 i2.next();
180                 if (i2.value() == s.model) {
181                     i2.remove();
182                 }
183             }
184             delete s.model;
185             break;
186         }
187     }
188 }
189 
reloadRoot(const QModelIndex & index)190 void FolderListModel::reloadRoot(const QModelIndex &index)
191 {
192     QMutableListIterator<SourceModel> i(m_modelList);
193     int count = 0;
194     while (i.hasNext()) {
195         SourceModel s = i.next();
196         if (s.rootIndex.internalId() == index.internalId()) {
197             QModelIndex sourceIndex = s.model->setRootPath(s.rootPath);
198             s.rootSourceIndex = sourceIndex;
199             s.rootIndex = createIndex(count,0,sourceIndex.internalPointer());
200             m_indexMap.insert(sourceIndex.internalId(),s.model);
201             i.setValue(s);
202             break;
203         }
204         count++;
205     }
206 }
207 
isRootPath(const QString & path)208 bool FolderListModel::isRootPath(const QString &path)
209 {
210     QString rootPath = QDir::cleanPath(QDir::fromNativeSeparators(path));
211     foreach (SourceModel s, m_modelList) {
212         if (s.rootPath == rootPath) {
213             return true;
214         }
215     }
216     return false;
217 }
218 
rootIndexs() const219 QList<QModelIndex> FolderListModel::rootIndexs() const
220 {
221     QList<QModelIndex> indexs;
222     foreach (SourceModel s, m_modelList) {
223         indexs.append(s.rootIndex);
224     }
225     return indexs;
226 }
227 
rootPathList() const228 QStringList FolderListModel::rootPathList() const
229 {
230     QStringList paths;
231     foreach (SourceModel s, m_modelList) {
232         paths.append(s.rootPath);
233     }
234     return paths;
235 }
236 
findSource(const QModelIndex & proxyIndex) const237 QFileSystemModel *FolderListModel::findSource(const QModelIndex &proxyIndex) const
238 {
239     return (QFileSystemModel*)m_indexMap[proxyIndex.internalId()];
240 }
241 
mapSelectionToSource(const QItemSelection & proxySelection) const242 QItemSelection FolderListModel::mapSelectionToSource(const QItemSelection &proxySelection) const
243 {
244     QModelIndexList proxyIndexes = proxySelection.indexes();
245     QItemSelection sourceSelection;
246     for (int i = 0; i < proxyIndexes.size(); ++i) {
247         const QModelIndex proxyIdx = mapToSource(proxyIndexes.at(i));
248         if (!proxyIdx.isValid())
249             continue;
250         sourceSelection << QItemSelectionRange(proxyIdx);
251     }
252     return sourceSelection;
253 }
254 
mapSelectionFromSource(const QItemSelection & sourceSelection) const255 QItemSelection FolderListModel::mapSelectionFromSource(const QItemSelection &sourceSelection) const
256 {
257     QModelIndexList sourceIndexes = sourceSelection.indexes();
258     QItemSelection proxySelection;
259     for (int i = 0; i < sourceIndexes.size(); ++i) {
260         const QModelIndex srcIdx = mapFromSource(sourceIndexes.at(i));
261         if (!srcIdx.isValid())
262             continue;
263         proxySelection << QItemSelectionRange(srcIdx);
264     }
265     return proxySelection;
266 }
267 
268 
mapFromSource(const QModelIndex & sourceIndex) const269 QModelIndex FolderListModel::mapFromSource(const QModelIndex &sourceIndex) const
270 {
271     if (!sourceIndex.isValid())
272         return QModelIndex();
273     int row = sourceIndex.row();
274     for (int i = 0; i < m_modelList.size(); i++) {
275         if (m_modelList[i].rootSourceIndex.internalId() == sourceIndex.internalId()) {
276             row = i;
277             break;
278         }
279     }
280     QModelIndex index = createIndex(row, sourceIndex.column(), sourceIndex.internalPointer());
281     m_indexMap.insert(sourceIndex.internalId(),(QAbstractItemModel*)sourceIndex.model());
282     return index;
283 }
284 
mapToSource(const QModelIndex & proxyIndex) const285 QModelIndex FolderListModel::mapToSource(const QModelIndex &proxyIndex) const
286 {
287     if (!proxyIndex.isValid()) {
288         return QModelIndex();
289     }
290     int row = proxyIndex.row();
291     for (int i = 0; i < m_modelList.size(); i++) {
292         if (m_modelList[i].rootIndex.internalId() == proxyIndex.internalId()) {
293             row = i;
294             break;
295         }
296     }
297     FileSystemModelEx *model = (FileSystemModelEx*)findSource(proxyIndex);
298     return model->createIndex(row, proxyIndex.column(), proxyIndex.internalPointer());
299 }
300 
filePath(const QModelIndex & index) const301 QString FolderListModel::filePath(const QModelIndex &index) const
302 {
303     if (!index.isValid()) {
304         return QString();
305     }
306     QModelIndex sourceIndex = mapToSource(index);
307     return ((FileSystemModelEx*)sourceIndex.model())->filePath(sourceIndex);
308 }
309 
fileName(const QModelIndex & index) const310 QString FolderListModel::fileName(const QModelIndex &index) const
311 {
312     if (!index.isValid()) {
313         return QString();
314     }
315     QModelIndex sourceIndex = mapToSource(index);
316     return ((FileSystemModelEx*)sourceIndex.model())->fileName(sourceIndex);
317 }
318 
fileInfo(const QModelIndex & index) const319 QFileInfo FolderListModel::fileInfo(const QModelIndex &index) const
320 {
321     if (!index.isValid()) {
322         return QFileInfo();
323     }
324     QModelIndex sourceIndex = mapToSource(index);
325     return ((FileSystemModelEx*)sourceIndex.model())->fileInfo(sourceIndex);
326 }
327 
isDir(const QModelIndex & index) const328 bool FolderListModel::isDir(const QModelIndex &index) const
329 {
330     if (!index.isValid()) {
331         return true;
332     }
333     QModelIndex sourceIndex = mapToSource(index);
334     return ((FileSystemModelEx*)sourceIndex.model())->isDir(sourceIndex);
335 }
336 
mkdir(const QModelIndex & parent,const QString & name)337 QModelIndex FolderListModel::mkdir(const QModelIndex &parent, const QString &name)
338 {
339     if (!parent.isValid()) {
340         return QModelIndex();
341     }
342     QModelIndex sourceIndex = mapToSource(parent);
343     return ((FileSystemModelEx*)sourceIndex.model())->mkdir(sourceIndex,name);
344 }
345 
rmdir(const QModelIndex & index)346 bool FolderListModel::rmdir(const QModelIndex &index)
347 {
348     if (!index.isValid()) {
349         return false;
350     }
351     QModelIndex sourceIndex = mapToSource(index);
352     return ((FileSystemModelEx*)sourceIndex.model())->rmdir(sourceIndex);
353 }
354 
remove(const QModelIndex & index)355 bool FolderListModel::remove(const QModelIndex &index)
356 {
357     if (!index.isValid()) {
358         return false;
359     }
360     QModelIndex sourceIndex = mapToSource(index);
361     return ((FileSystemModelEx*)sourceIndex.model())->remove(sourceIndex);
362 }
363 
setFilter(QDir::Filters filters)364 void FolderListModel::setFilter(QDir::Filters filters)
365 {
366     m_filters = filters;
367     foreach (SourceModel s, m_modelList) {
368         s.model->setFilter(filters);
369     }
370 }
371 
filter() const372 QDir::Filters FolderListModel::filter() const
373 {
374     return m_filters;
375 }
376 
setNameFilters(const QStringList & filters)377 void FolderListModel::setNameFilters(const QStringList &filters)
378 {
379     m_nameFilters = filters;
380     foreach (SourceModel s, m_modelList) {
381         s.model->setNameFilters(filters);
382     }
383 }
384 
nameFilters() const385 QStringList FolderListModel::nameFilters() const
386 {
387     return m_nameFilters;
388 }
389 
setNameFilterDisables(bool enable)390 void FolderListModel::setNameFilterDisables(bool enable)
391 {
392     if (m_nameFilterDisables == enable) {
393         return;
394     }
395     m_nameFilterDisables = enable;
396     foreach (SourceModel s, m_modelList) {
397         s.model->setNameFilterDisables(enable);
398     }
399 }
400 
nameFilterDisables() const401 bool FolderListModel::nameFilterDisables() const
402 {
403     return m_nameFilterDisables;
404 }
405 
setResolveSymlinks(bool enable)406 void FolderListModel::setResolveSymlinks(bool enable)
407 {
408     if (m_resolveSymlinks == enable) {
409         return;
410     }
411     m_resolveSymlinks = enable;
412     foreach (SourceModel s, m_modelList) {
413         s.model->setResolveSymlinks(enable);
414     }
415 }
416 
resolveSymlinks() const417 bool FolderListModel::resolveSymlinks() const
418 {
419     return m_resolveSymlinks;
420 }
421 
isRootIndex(const QModelIndex & index) const422 bool FolderListModel::isRootIndex(const QModelIndex &index) const
423 {
424     foreach (SourceModel s, m_modelList) {
425         if (s.rootIndex.internalId() == index.internalId()) {
426             return true;
427         }
428     }
429     return false;
430 }
431 
setWatcherRoot(bool b)432 void FolderListModel::setWatcherRoot(bool b)
433 {
434     if (m_bWatcherRoot == b) {
435         return;
436     }
437     if (m_bWatcherRoot) {
438         if (!m_watcher) {
439             m_watcher = new QFileSystemWatcher(this);
440         }
441         connect(m_watcher,SIGNAL(directoryChanged(QString)),this,SLOT(directoryChanged(QString)));
442         QStringList paths;
443         foreach (SourceModel s, m_modelList) {
444             paths.append(s.watchPath);
445         }
446         paths.removeDuplicates();
447         m_watcher->addPaths(paths);
448     } else {
449         if (m_watcher) {
450             delete m_watcher;
451         }
452         m_watcher = 0;
453     }
454 }
455 
isWatcherRoot() const456 bool FolderListModel::isWatcherRoot() const
457 {
458     return m_bWatcherRoot;
459 }
460 
indexForPath(const QString & path) const461 QList<QModelIndex> FolderListModel::indexForPath(const QString &path) const
462 {
463     QList<QModelIndex> indexs;
464     QString findPath = QDir::cleanPath(QDir::fromNativeSeparators(path));
465     foreach (SourceModel s, m_modelList) {
466         if (!findPath.startsWith(s.rootPath)) {
467             continue;
468         }
469         QModelIndex sourceIndex = s.model->index(path);
470         if (sourceIndex.isValid()) {
471             indexs.append(this->mapFromSource(sourceIndex));
472         }
473     }
474     return indexs;
475 }
476 
supportedDragActions() const477 Qt::DropActions FolderListModel::supportedDragActions() const
478 {
479     return Qt::MoveAction | Qt::CopyAction;
480 }
481 
isRootSourceIndex(const QModelIndex & sourceIndex) const482 bool FolderListModel::isRootSourceIndex(const QModelIndex &sourceIndex) const
483 {
484     foreach (SourceModel s, m_modelList) {
485         if (s.rootSourceIndex.internalId() == sourceIndex.internalId()) {
486             return true;
487         }
488     }
489     return false;
490 }
491 
columnCount(const QModelIndex &) const492 int FolderListModel::columnCount(const QModelIndex &/*parent*/) const
493 {
494     return 1;
495 //    if (!parent.isValid()) {
496 //        if (!m_modelList.isEmpty()) {
497 //            return m_modelList[0].model->columnCount(m_modelList[0].rootSourceIndex);
498 //        }
499 //        return 1;
500 //    }
501 //    QModelIndex sourceIndex = mapToSource(parent);
502 //    return sourceIndex.model()->columnCount(sourceIndex);
503 }
504 
index(int row,int column,const QModelIndex & parent) const505 QModelIndex FolderListModel::index(int row, int column, const QModelIndex &parent) const
506 {
507     if (!hasIndex(row, column, parent))
508         return QModelIndex();
509     if (!parent.isValid()) {
510         QModelIndex sourceIndex = m_modelList[row].rootSourceIndex;
511         if (sourceIndex.column() != column) {
512             sourceIndex = sourceIndex.sibling(sourceIndex.row(),column);
513             m_indexMap.insert(sourceIndex.internalId(),m_modelList[row].model);
514         }
515         return createIndex(row,column,sourceIndex.internalPointer());
516     }
517     const QModelIndex sourceParent = mapToSource(parent);
518     const QModelIndex sourceIndex = sourceParent.model()->index(row, column, sourceParent);
519     Q_ASSERT(sourceIndex.isValid());
520     return mapFromSource(sourceIndex);
521 }
522 
parent(const QModelIndex & child) const523 QModelIndex FolderListModel::parent(const QModelIndex &child) const
524 {
525     Q_ASSERT(child.isValid() ? child.model() == this : true);
526     if (isRootIndex(child)) {
527         return QModelIndex();
528     }
529     const QModelIndex sourceIndex = mapToSource(child);
530     const QModelIndex sourceParent = sourceIndex.parent();
531     return mapFromSource(sourceParent);
532 }
533 
rowCount(const QModelIndex & parent) const534 int FolderListModel::rowCount(const QModelIndex &parent) const
535 {
536     if (!parent.isValid()) {
537         return m_modelList.size();
538     }
539     Q_ASSERT(parent.isValid() ? parent.model() == this : true);
540     QModelIndex sourceIndex = mapToSource(parent);
541     return sourceIndex.model()->rowCount(sourceIndex);
542 }
543 
data(const QModelIndex & proxyIndex,int role) const544 QVariant FolderListModel::data(const QModelIndex &proxyIndex, int role) const
545 {
546     if (!proxyIndex.isValid()) {
547         return QVariant();
548     }
549     QModelIndex sourceIndex = mapToSource(proxyIndex);
550     return sourceIndex.model()->data(sourceIndex,role);
551 }
552 
553 
headerData(int section,Qt::Orientation orientation,int role) const554 QVariant FolderListModel::headerData(int section, Qt::Orientation orientation, int role) const
555 {
556     if (m_modelList.isEmpty()) {
557         return QVariant();
558     }
559     if (orientation == Qt::Horizontal) {
560         const QModelIndex proxyIndex = index(0, section);
561         QModelIndex sourceIndex = mapToSource(proxyIndex);
562         int sourceSection = sourceIndex.column();
563         return sourceIndex.model()->headerData(sourceSection,orientation,role);
564     } else {
565         const QModelIndex proxyIndex = index(section, 0);
566         QModelIndex sourceIndex = mapToSource(proxyIndex);
567         int sourceSection = sourceIndex.row();
568         return sourceIndex.model()->headerData(sourceSection,orientation,role);
569     }
570 }
571 
itemData(const QModelIndex & proxyIndex) const572 QMap<int, QVariant> FolderListModel::itemData(const QModelIndex &proxyIndex) const
573 {
574     return QAbstractItemModel::itemData(proxyIndex);
575 }
576 
flags(const QModelIndex & index) const577 Qt::ItemFlags FolderListModel::flags(const QModelIndex &index) const
578 {
579     QModelIndex sourceIndex = mapToSource(index);
580     if (!sourceIndex.isValid()) {
581         return Qt::NoItemFlags;
582     }
583     return sourceIndex.model()->flags(sourceIndex);
584 }
585 
setData(const QModelIndex & index,const QVariant & value,int role)586 bool FolderListModel::setData(const QModelIndex &index, const QVariant &value, int role)
587 {
588     QModelIndex sourceIndex = mapToSource(index);
589     return ((QAbstractItemModel*)sourceIndex.model())->setData(sourceIndex,value,role);
590 }
591 
setItemData(const QModelIndex & index,const QMap<int,QVariant> & roles)592 bool FolderListModel::setItemData(const QModelIndex &index, const QMap< int, QVariant >& roles)
593 {
594     return QAbstractItemModel::setItemData(index, roles);
595 }
596 
setHeaderData(int section,Qt::Orientation orientation,const QVariant & value,int role)597 bool FolderListModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
598 {
599     if (orientation == Qt::Horizontal) {
600         const QModelIndex proxyIndex = index(0, section);
601         QModelIndex sourceIndex = mapToSource(proxyIndex);
602         int sourceSection = sourceIndex.column();
603         return ((QAbstractItemModel*)sourceIndex.model())->setHeaderData(sourceSection,orientation,value,role);
604     } else {
605         const QModelIndex proxyIndex = index(section, 0);
606         QModelIndex sourceIndex = mapToSource(proxyIndex);
607         int sourceSection = sourceIndex.row();
608         return ((QAbstractItemModel*)sourceIndex.model())->setHeaderData(sourceSection,orientation,value,role);
609     }
610 }
611 
insertColumns(int column,int count,const QModelIndex & parent)612 bool FolderListModel::insertColumns(int column, int count, const QModelIndex& parent)
613 {
614     Q_ASSERT(parent.isValid() ? parent.model() == this : true);
615     QModelIndex sourceIndex = mapToSource(parent);
616     return ((QAbstractItemModel*)sourceIndex.model())->insertColumns(column, count, sourceIndex);
617 }
618 
619 /*!
620     \reimp
621  */
insertRows(int row,int count,const QModelIndex & parent)622 bool FolderListModel::insertRows(int row, int count, const QModelIndex& parent)
623 {
624     Q_ASSERT(parent.isValid() ? parent.model() == this : true);
625     QModelIndex sourceIndex = mapToSource(parent);
626     return ((QAbstractItemModel*)sourceIndex.model())->insertRows(row, count, sourceIndex);
627 }
628 
removeColumns(int column,int count,const QModelIndex & parent)629 bool FolderListModel::removeColumns(int column, int count, const QModelIndex &parent)
630 {
631     Q_ASSERT(parent.isValid() ? parent.model() == this : true);
632     QModelIndex sourceIndex = mapToSource(parent);
633     return ((QAbstractItemModel*)sourceIndex.model())->removeColumns(column, count, sourceIndex);
634 }
635 
removeRows(int row,int count,const QModelIndex & parent)636 bool FolderListModel::removeRows(int row, int count, const QModelIndex &parent)
637 {
638     Q_ASSERT(parent.isValid() ? parent.model() == this : true);
639     if (!parent.isValid()) {
640         return QAbstractItemModel::removeRows(row,count);
641     }
642     QModelIndex sourceIndex = mapToSource(parent);
643     return ((QAbstractItemModel*)sourceIndex.model())->removeRows(row, count, sourceIndex);
644 }
645 
directoryChanged(const QString & path)646 void FolderListModel::directoryChanged(const QString &path)
647 {
648     if (!m_bWatcherRoot) {
649         return;
650     }
651     foreach(SourceModel s, m_modelList) {
652          if (s.watchPath == path && !QDir(s.rootPath).exists()) {
653               this->removeRoot(s.rootIndex);
654               break;
655          }
656     }
657 }
658 
canFetchMore(const QModelIndex & parent) const659 bool FolderListModel::canFetchMore(const QModelIndex &parent) const
660 {
661     if (!parent.isValid()) {
662         return false;
663     }
664     QModelIndex sourceIndex = mapToSource(parent);
665     return sourceIndex.model()->canFetchMore(sourceIndex);
666 }
667 
fetchMore(const QModelIndex & parent)668 void FolderListModel::fetchMore(const QModelIndex &parent)
669 {
670     if (!parent.isValid()) {
671         return;
672     }
673     QModelIndex sourceIndex = mapToSource(parent);
674     QAbstractItemModel *model = (QAbstractItemModel*)sourceIndex.model();
675     model->fetchMore(sourceIndex);
676 }
677 
sort(int column,Qt::SortOrder order)678 void FolderListModel::sort(int column, Qt::SortOrder order)
679 {
680     foreach (SourceModel s, m_modelList) {
681         s.model->sort(column,order);
682     }
683 }
684 
span(const QModelIndex & index) const685 QSize FolderListModel::span(const QModelIndex &index) const
686 {
687     if (!index.isValid()) {
688         return QAbstractItemModel::span(index);
689     }
690     QModelIndex sourceIndex = mapToSource(index);
691     return sourceIndex.model()->span(sourceIndex);
692 }
693 
hasChildren(const QModelIndex & parent) const694 bool FolderListModel::hasChildren(const QModelIndex &parent) const
695 {
696     if (!parent.isValid()) {
697         return m_modelList.size() > 0;
698     }
699     QModelIndex sourceIndex = mapToSource(parent);
700     return sourceIndex.model()->hasChildren(sourceIndex);
701 }
702 
buddy(const QModelIndex & index) const703 QModelIndex FolderListModel::buddy(const QModelIndex &index) const
704 {
705     return index;
706 }
707 
sourceColumnsAboutToBeInserted(const QModelIndex & parent,int start,int end)708 void FolderListModel::sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end)
709 {
710     //Q_ASSERT(parent.isValid() ? parent.model() == m_model : true);
711     this->beginInsertColumns(mapFromSource(parent), start, end);
712 }
713 
sourceColumnsAboutToBeMoved(const QModelIndex & sourceParent,int sourceStart,int sourceEnd,const QModelIndex & destParent,int dest)714 void FolderListModel::sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
715 {
716     //Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == m_model : true);
717     //Q_ASSERT(destParent.isValid() ? destParent.model() == m_model : true);
718     this->beginMoveColumns(this->mapFromSource(sourceParent), sourceStart, sourceEnd, this->mapFromSource(destParent), dest);
719 }
720 
sourceColumnsAboutToBeRemoved(const QModelIndex & parent,int start,int end)721 void FolderListModel::sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
722 {
723     //Q_ASSERT(parent.isValid() ? parent.model() == m_model : true);
724     this->beginRemoveColumns(this->mapFromSource(parent), start, end);
725 }
726 
sourceColumnsInserted(const QModelIndex & parent,int start,int end)727 void FolderListModel::sourceColumnsInserted(const QModelIndex &parent, int start, int end)
728 {
729     //Q_ASSERT(parent.isValid() ? parent.model() == m_model : true);
730     Q_UNUSED(parent)
731     Q_UNUSED(start)
732     Q_UNUSED(end)
733     this->endInsertColumns();
734 }
735 
sourceColumnsMoved(const QModelIndex & sourceParent,int sourceStart,int sourceEnd,const QModelIndex & destParent,int dest)736 void FolderListModel::sourceColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
737 {
738     //Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == m_model : true);
739     //Q_ASSERT(destParent.isValid() ? destParent.model() == m_model : true);
740     Q_UNUSED(sourceParent)
741     Q_UNUSED(sourceStart)
742     Q_UNUSED(sourceEnd)
743     Q_UNUSED(destParent)
744     Q_UNUSED(dest)
745     this->endMoveColumns();
746 }
747 
sourceColumnsRemoved(const QModelIndex & parent,int start,int end)748 void FolderListModel::sourceColumnsRemoved(const QModelIndex &parent, int start, int end)
749 {
750     //Q_ASSERT(parent.isValid() ? parent.model() == m_model : true);
751     Q_UNUSED(parent)
752     Q_UNUSED(start)
753     Q_UNUSED(end)
754     this->endRemoveColumns();
755 }
756 
sourceDataChanged(const QModelIndex & topLeft,const QModelIndex & bottomRight)757 void FolderListModel::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
758 {
759     //Q_ASSERT(topLeft.isValid() ? topLeft.model() == m_model : true);
760     //Q_ASSERT(bottomRight.isValid() ? bottomRight.model() == m_model : true);
761     this->dataChanged(this->mapFromSource(topLeft), this->mapFromSource(bottomRight));
762 }
763 
sourceHeaderDataChanged(Qt::Orientation orientation,int first,int last)764 void FolderListModel::sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last)
765 {
766     this->headerDataChanged(orientation, first, last);
767 }
768 
sourceLayoutAboutToBeChanged()769 void FolderListModel::sourceLayoutAboutToBeChanged()
770 {
771     if (ignoreNextLayoutAboutToBeChanged)
772         return;
773 
774     foreach(const QPersistentModelIndex &proxyPersistentIndex, this->persistentIndexList()) {
775    //     qDebug() << proxyPersistentIndex << this->filePath(proxyPersistentIndex);
776         proxyIndexes << proxyPersistentIndex;
777 //        Q_ASSERT(proxyPersistentIndex.isValid());
778         const QPersistentModelIndex srcPersistentIndex = this->mapToSource(proxyPersistentIndex);
779 //        Q_ASSERT(srcPersistentIndex.isValid());
780         layoutChangePersistentIndexes << srcPersistentIndex;
781     }
782 
783     this->layoutAboutToBeChanged();
784 }
785 
sourceLayoutChanged()786 void FolderListModel::sourceLayoutChanged()
787 {
788     if (ignoreNextLayoutChanged)
789         return;
790 
791     for (int i = 0; i < proxyIndexes.size(); ++i) {
792         this->changePersistentIndex(proxyIndexes.at(i), this->mapFromSource(layoutChangePersistentIndexes.at(i)));
793     }
794 
795     layoutChangePersistentIndexes.clear();
796     proxyIndexes.clear();
797 
798     this->layoutChanged();
799 }
800 
sourceModelAboutToBeReset()801 void FolderListModel::sourceModelAboutToBeReset()
802 {
803     this->beginResetModel();
804 }
805 
sourceModelReset()806 void FolderListModel::sourceModelReset()
807 {
808     this->endResetModel();
809 }
810 
sourceRowsAboutToBeInserted(const QModelIndex &,int,int)811 void FolderListModel::sourceRowsAboutToBeInserted(const QModelIndex &/*parent*/, int /*start*/, int /*end*/)
812 {
813     //Q_ASSERT(parent.isValid() ? parent.model() == m_model : true);
814     //this->beginInsertRows(this->mapFromSource(parent), start, end);
815 }
816 
sourceRowsAboutToBeMoved(const QModelIndex & sourceParent,int sourceStart,int sourceEnd,const QModelIndex & destParent,int dest)817 void FolderListModel::sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
818 {
819     //Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == m_model : true);
820     //Q_ASSERT(destParent.isValid() ? destParent.model() == m_model : true);
821     this->beginMoveRows(this->mapFromSource(sourceParent), sourceStart, sourceEnd, this->mapFromSource(destParent), dest);
822 }
823 
sourceRowsAboutToBeRemoved(const QModelIndex & parent,int start,int end)824 void FolderListModel::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
825 {
826     //Q_ASSERT(parent.isValid() ? parent.model() == m_model : true);
827     this->beginRemoveRows(this->mapFromSource(parent), start, end);
828 }
829 
sourceRowsInserted(const QModelIndex & parent,int start,int end)830 void FolderListModel::sourceRowsInserted(const QModelIndex &parent, int start, int end)
831 {
832     //Q_ASSERT(parent.isValid() ? parent.model() == m_model : true);
833     Q_UNUSED(parent)
834     Q_UNUSED(start)
835     Q_UNUSED(end)
836     //this->beginInsertRows(this->mapFromSource(parent), start, end);
837     //this->endInsertRows();
838     for (int i = start; i <= end; i++) {
839         this->beginInsertRows(this->mapFromSource(parent), i,i);
840         this->endInsertRows();
841     }
842 }
843 
sourceRowsMoved(const QModelIndex & sourceParent,int sourceStart,int sourceEnd,const QModelIndex & destParent,int dest)844 void FolderListModel::sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
845 {
846     //Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == m_model : true);
847     //Q_ASSERT(destParent.isValid() ? destParent.model() == m_model : true);
848     Q_UNUSED(sourceParent)
849     Q_UNUSED(sourceStart)
850     Q_UNUSED(sourceEnd)
851     Q_UNUSED(destParent)
852     Q_UNUSED(dest)
853     this->endMoveRows();
854 }
855 
sourceRowsRemoved(const QModelIndex & parent,int start,int end)856 void FolderListModel::sourceRowsRemoved(const QModelIndex &parent, int start, int end)
857 {
858     //Q_ASSERT(parent.isValid() ? parent.model() == m_model : true);
859     Q_UNUSED(parent)
860     Q_UNUSED(start)
861     Q_UNUSED(end)
862     this->endRemoveRows();
863 }
864