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: dirsortfilterproxymodel.cpp
22 // Creator: visualfc <visualfc@gmail.com>
23 
24 #include "dirsortfilterproxymodel.h"
25 #include <QFileSystemModel>
26 #include <QFileInfo>
27 #include <QDirModel>
28 #include <QDateTime>
29 //lite_memory_check_begin
30 #if defined(WIN32) && defined(_MSC_VER) &&  defined(_DEBUG)
31      #define _CRTDBG_MAP_ALLOC
32      #include <stdlib.h>
33      #include <crtdbg.h>
34      #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
35      #define new DEBUG_NEW
36 #endif
37 //lite_memory_check_end
38 
39 
40 /* For sorting */
41 struct QDirSortItem
42 {
43     mutable QString filename_cache;
44     mutable QString suffix_cache;
45     QFileInfo item;
46 };
47 
48 
49 class QDirSortItemComparator
50 {
51     int qt_cmp_si_sort_flags;
52 public:
QDirSortItemComparator(int flags)53     QDirSortItemComparator(int flags) : qt_cmp_si_sort_flags(flags) {}
54     bool sort(const QDirSortItem &, const QDirSortItem &);
55 };
56 
sort(const QDirSortItem & n1,const QDirSortItem & n2)57 bool QDirSortItemComparator::sort(const QDirSortItem &n1, const QDirSortItem &n2)
58 {
59     const QDirSortItem* f1 = &n1;
60     const QDirSortItem* f2 = &n2;
61 
62     if ((qt_cmp_si_sort_flags & QDir::DirsFirst) && (f1->item.isDir() != f2->item.isDir()))
63         return f1->item.isDir();
64     if ((qt_cmp_si_sort_flags & QDir::DirsLast) && (f1->item.isDir() != f2->item.isDir()))
65         return !f1->item.isDir();
66 
67     int r = 0;
68     int sortBy = (qt_cmp_si_sort_flags & QDir::SortByMask)
69                  | (qt_cmp_si_sort_flags & QDir::Type);
70 
71     switch (sortBy) {
72       case QDir::Time:
73         r = f1->item.lastModified().secsTo(f2->item.lastModified());
74         break;
75       case QDir::Size:
76           r = int(qBound<qint64>(-1, f2->item.size() - f1->item.size(), 1));
77         break;
78       case QDir::Type:
79       {
80         bool ic = qt_cmp_si_sort_flags & QDir::IgnoreCase;
81 
82         if (f1->suffix_cache.isNull())
83             f1->suffix_cache = ic ? f1->item.suffix().toLower()
84                                : f1->item.suffix();
85         if (f2->suffix_cache.isNull())
86             f2->suffix_cache = ic ? f2->item.suffix().toLower()
87                                : f2->item.suffix();
88 
89         r = qt_cmp_si_sort_flags & QDir::LocaleAware
90             ? f1->suffix_cache.localeAwareCompare(f2->suffix_cache)
91             : f1->suffix_cache.compare(f2->suffix_cache);
92       }
93         break;
94       default:
95         ;
96     }
97 
98     if (r == 0 && sortBy != QDir::Unsorted) {
99         // Still not sorted - sort by name
100         bool ic = qt_cmp_si_sort_flags & QDir::IgnoreCase;
101 
102         if (f1->filename_cache.isNull())
103             f1->filename_cache = ic ? f1->item.fileName().toLower()
104                                     : f1->item.fileName();
105         if (f2->filename_cache.isNull())
106             f2->filename_cache = ic ? f2->item.fileName().toLower()
107                                     : f2->item.fileName();
108 
109         r = qt_cmp_si_sort_flags & QDir::LocaleAware
110             ? f1->filename_cache.localeAwareCompare(f2->filename_cache)
111             : f1->filename_cache.compare(f2->filename_cache);
112     }
113     if (r == 0) // Enforce an order - the order the items appear in the array
114         r = (&n1) - (&n2);
115     if (qt_cmp_si_sort_flags & QDir::Reversed)
116         return r > 0;
117     return r < 0;
118 }
119 
120 
DirSortFilterProxyModel(QObject * parent)121 DirSortFilterProxyModel::DirSortFilterProxyModel(QObject *parent)
122     : QSortFilterProxyModel(parent), m_sorts(QDir::NoSort)
123 {
124 
125 }
126 
setSorting(QDir::SortFlags sort)127 void DirSortFilterProxyModel::setSorting(QDir::SortFlags sort)
128 {
129     m_sorts = sort;
130 }
131 
sorting() const132 QDir::SortFlags DirSortFilterProxyModel::sorting() const
133 {
134     return m_sorts;
135 }
136 
lessThan(const QModelIndex & left,const QModelIndex & right) const137 bool DirSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
138 {
139     QFileSystemModel *model = dynamic_cast<QFileSystemModel*>(this->sourceModel());
140     if (!model) {
141         return QSortFilterProxyModel::lessThan(left,right);
142     }
143     QDirSortItemComparator comp(m_sorts);
144     QDirSortItem n1;
145     QDirSortItem n2;
146     n1.item = model->fileInfo(left);
147     n2.item = model->fileInfo(right);
148     return comp.sort(n1,n2);
149 }
150 
151