• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KFile

  • kfile
kdirsortfilterproxymodel.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2006 by Peter Penz <peter.penz@gmx.at>
3 Copyright (C) 2006 by Dominic Battre <dominic@battre.de>
4 Copyright (C) 2006 by Martin Pool <mbp@canonical.com>
5
6 Separated from Dolphin by Nick Shaforostoff <shafff@ukr.net>
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License version 2 as published by the Free Software Foundation.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21*/
22
23#include "kdirsortfilterproxymodel.h"
24
25#include <kdatetime.h>
26#include <kdirmodel.h>
27#include <kfileitem.h>
28#include <kglobalsettings.h>
29#include <klocale.h>
30#include <kstringhandler.h>
31
32
33class KDirSortFilterProxyModel::KDirSortFilterProxyModelPrivate
34{
35public:
36 KDirSortFilterProxyModelPrivate(KDirSortFilterProxyModel* q);
37
38 int compare(const QString&, const QString&, Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive) const;
39 void slotNaturalSortingChanged();
40
41 bool m_sortFoldersFirst;
42 bool m_naturalSorting;
43};
44
45KDirSortFilterProxyModel::KDirSortFilterProxyModelPrivate::KDirSortFilterProxyModelPrivate(KDirSortFilterProxyModel* q) :
46 m_sortFoldersFirst(true),
47 m_naturalSorting(KGlobalSettings::naturalSorting())
48{
49 connect(KGlobalSettings::self(), SIGNAL(naturalSortingChanged()),
50 q, SLOT(slotNaturalSortingChanged()));
51}
52
53int KDirSortFilterProxyModel::KDirSortFilterProxyModelPrivate::compare(const QString& a,
54 const QString& b,
55 Qt::CaseSensitivity caseSensitivity) const
56{
57 if (caseSensitivity == Qt::CaseInsensitive) {
58 const int result = m_naturalSorting ? KStringHandler::naturalCompare(a, b, Qt::CaseInsensitive)
59 : QString::compare(a, b, Qt::CaseInsensitive);
60 if (result != 0) {
61 // Only return the result, if the strings are not equal. If they are equal by a case insensitive
62 // comparison, still a deterministic sort order is required. A case sensitive
63 // comparison is done as fallback.
64 return result;
65 }
66 }
67
68 return m_naturalSorting ? KStringHandler::naturalCompare(a, b, Qt::CaseSensitive)
69 : QString::compare(a, b, Qt::CaseSensitive);
70}
71
72
73void KDirSortFilterProxyModel::KDirSortFilterProxyModelPrivate::slotNaturalSortingChanged()
74{
75 m_naturalSorting = KGlobalSettings::naturalSorting();
76}
77
78KDirSortFilterProxyModel::KDirSortFilterProxyModel(QObject* parent)
79 : KCategorizedSortFilterProxyModel(parent), d(new KDirSortFilterProxyModelPrivate(this))
80{
81 setDynamicSortFilter(true);
82
83 // sort by the user visible string for now
84 setSortCaseSensitivity(Qt::CaseInsensitive);
85 sort(KDirModel::Name, Qt::AscendingOrder);
86
87 setSupportedDragActions(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction | Qt::IgnoreAction);
88}
89
90KDirSortFilterProxyModel::~KDirSortFilterProxyModel()
91{
92 delete d;
93}
94
95bool KDirSortFilterProxyModel::hasChildren(const QModelIndex& parent) const
96{
97 const QModelIndex sourceParent = mapToSource(parent);
98 return sourceModel()->hasChildren(sourceParent);
99}
100
101bool KDirSortFilterProxyModel::canFetchMore(const QModelIndex& parent) const
102{
103 const QModelIndex sourceParent = mapToSource(parent);
104 return sourceModel()->canFetchMore(sourceParent);
105}
106
107int KDirSortFilterProxyModel::pointsForPermissions(const QFileInfo &info)
108{
109 int points = 0;
110
111 QFile::Permission permissionsCheck[] = { QFile::ReadUser,
112 QFile::WriteUser,
113 QFile::ExeUser,
114 QFile::ReadGroup,
115 QFile::WriteGroup,
116 QFile::ExeGroup,
117 QFile::ReadOther,
118 QFile::WriteOther,
119 QFile::ExeOther };
120
121 for (int i = 0; i < 9; i++) {
122 points += info.permission(permissionsCheck[i]) ? 1 : 0;
123 }
124
125 return points;
126}
127
128void KDirSortFilterProxyModel::setSortFoldersFirst(bool foldersFirst)
129{
130 d->m_sortFoldersFirst = foldersFirst;
131}
132
133bool KDirSortFilterProxyModel::sortFoldersFirst() const
134{
135 return d->m_sortFoldersFirst;
136}
137
138bool KDirSortFilterProxyModel::subSortLessThan(const QModelIndex& left,
139 const QModelIndex& right) const
140{
141 KDirModel* dirModel = static_cast<KDirModel*>(sourceModel());
142
143 const KFileItem leftFileItem = dirModel->itemForIndex(left);
144 const KFileItem rightFileItem = dirModel->itemForIndex(right);
145
146 const bool isLessThan = (sortOrder() == Qt::AscendingOrder);
147
148 // Folders go before files if the corresponding setting is set.
149 if (d->m_sortFoldersFirst) {
150 const bool leftItemIsDir = leftFileItem.isDir();
151 const bool rightItemIsDir = rightFileItem.isDir();
152 if (leftItemIsDir && !rightItemIsDir) {
153 return isLessThan;
154 } else if (!leftItemIsDir && rightItemIsDir) {
155 return !isLessThan;
156 }
157 }
158
159
160 // Hidden elements go before visible ones.
161 const bool leftItemIsHidden = leftFileItem.isHidden();
162 const bool rightItemIsHidden = rightFileItem.isHidden();
163 if (leftItemIsHidden && !rightItemIsHidden) {
164 return isLessThan;
165 } else if (!leftItemIsHidden && rightItemIsHidden) {
166 return !isLessThan;
167 }
168
169 switch (left.column()) {
170 case KDirModel::Name: {
171 int result = d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity());
172 if (result == 0) {
173 // KFileItem::text() may not be unique in case UDS_DISPLAY_NAME is used
174 result = d->compare(leftFileItem.name(sortCaseSensitivity() == Qt::CaseInsensitive),
175 rightFileItem.name(sortCaseSensitivity() == Qt::CaseInsensitive),
176 sortCaseSensitivity());
177 if (result == 0) {
178 // If KFileItem::text() is also not unique most probably a search protocol is used
179 // that allows showing the same file names from different directories
180 result = d->compare(leftFileItem.url().url(), rightFileItem.url().url(), sortCaseSensitivity());
181 }
182 }
183
184 return result < 0;
185 }
186
187 case KDirModel::Size: {
188 // If we have two folders, what we have to measure is the number of
189 // items that contains each other
190 if (leftFileItem.isDir() && rightFileItem.isDir()) {
191 QVariant leftValue = dirModel->data(left, KDirModel::ChildCountRole);
192 int leftCount = (leftValue.type() == QVariant::Int) ? leftValue.toInt() : KDirModel::ChildCountUnknown;
193
194 QVariant rightValue = dirModel->data(right, KDirModel::ChildCountRole);
195 int rightCount = (rightValue.type() == QVariant::Int) ? rightValue.toInt() : KDirModel::ChildCountUnknown;
196
197 // In the case they two have the same child items, we sort them by
198 // their names. So we have always everything ordered. We also check
199 // if we are taking in count their cases.
200 if (leftCount == rightCount) {
201 return d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity()) < 0;
202 }
203
204 // If one of them has unknown child items, place them on the end. If we
205 // were comparing two unknown childed items, the previous comparation
206 // sorted them by naturalCompare between them. This case is when we
207 // have an unknown childed item, and another known.
208 if (leftCount == KDirModel::ChildCountUnknown) {
209 return false;
210 }
211
212 if (rightCount == KDirModel::ChildCountUnknown) {
213 return true;
214 }
215
216 // If they had different number of items, we sort them depending
217 // on how many items had each other.
218 return leftCount < rightCount;
219 }
220
221 // If what we are measuring is two files and they have the same size,
222 // sort them by their file names.
223 if (leftFileItem.size() == rightFileItem.size()) {
224 return d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity()) < 0;
225 }
226
227 // If their sizes are different, sort them by their sizes, as expected.
228 return leftFileItem.size() < rightFileItem.size();
229 }
230
231 case KDirModel::ModifiedTime: {
232 KDateTime leftModifiedTime = leftFileItem.time(KFileItem::ModificationTime).toLocalZone();
233 KDateTime rightModifiedTime = rightFileItem.time(KFileItem::ModificationTime).toLocalZone();
234
235 if (leftModifiedTime == rightModifiedTime) {
236 return d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity()) < 0;
237 }
238
239 return leftModifiedTime < rightModifiedTime;
240 }
241
242 case KDirModel::Permissions: {
243 // ### You can't use QFileInfo on urls!! Use the KFileItem instead.
244 QFileInfo leftFileInfo(leftFileItem.url().pathOrUrl());
245 QFileInfo rightFileInfo(rightFileItem.url().pathOrUrl());
246
247 int leftPermissionsPoints = pointsForPermissions(leftFileInfo);
248 int rightPermissionsPoints = pointsForPermissions(rightFileInfo);
249
250 if (leftPermissionsPoints == rightPermissionsPoints) {
251 return d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity()) < 0;
252 }
253
254 return leftPermissionsPoints > rightPermissionsPoints;
255 }
256
257 case KDirModel::Owner: {
258 if (leftFileItem.user() == rightFileItem.user()) {
259 return d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity()) < 0;
260 }
261
262 return d->compare(leftFileItem.user(), rightFileItem.user()) < 0;
263 }
264
265 case KDirModel::Group: {
266 if (leftFileItem.group() == rightFileItem.group()) {
267 return d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity()) < 0;
268 }
269
270 return d->compare(leftFileItem.group(), rightFileItem.group()) < 0;
271 }
272
273 case KDirModel::Type: {
274 if (leftFileItem.mimetype() == rightFileItem.mimetype()) {
275 return d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity()) < 0;
276 }
277
278 return d->compare(leftFileItem.mimeComment(), rightFileItem.mimeComment()) < 0;
279 }
280
281 }
282
283 // We have set a SortRole and trust the ProxyModel to do
284 // the right thing for now.
285 return KCategorizedSortFilterProxyModel::subSortLessThan(left, right);
286}
287
288#include "kdirsortfilterproxymodel.moc"
KCategorizedSortFilterProxyModel
KCategorizedSortFilterProxyModel::subSortLessThan
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const
KCategorizedSortFilterProxyModel::sort
virtual void sort(int column, Qt::SortOrder order=Qt::AscendingOrder)
KCategorizedSortFilterProxyModel::sortOrder
Qt::SortOrder sortOrder() const
KDateTime
KDateTime::toLocalZone
KDateTime toLocalZone() const
KDirModel
KDirModel::ChildCountUnknown
ChildCountUnknown
KDirModel::ChildCountRole
ChildCountRole
KDirModel::itemForIndex
KFileItem itemForIndex(const QModelIndex &index) const
KDirModel::Type
Type
KDirModel::Size
Size
KDirModel::ModifiedTime
ModifiedTime
KDirModel::Permissions
Permissions
KDirModel::Owner
Owner
KDirModel::Name
Name
KDirModel::Group
Group
KDirModel::data
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
KDirSortFilterProxyModel
Acts as proxy model for KDirModel to sort and filter KFileItems.
Definition: kdirsortfilterproxymodel.h:52
KDirSortFilterProxyModel::hasChildren
virtual bool hasChildren(const QModelIndex &parent=QModelIndex()) const
Reimplemented from QAbstractItemModel.
Definition: kdirsortfilterproxymodel.cpp:95
KDirSortFilterProxyModel::pointsForPermissions
static int pointsForPermissions(const QFileInfo &info)
Returns the permissions in "points".
Definition: kdirsortfilterproxymodel.cpp:107
KDirSortFilterProxyModel::KDirSortFilterProxyModel
KDirSortFilterProxyModel(QObject *parent=0)
Definition: kdirsortfilterproxymodel.cpp:78
KDirSortFilterProxyModel::subSortLessThan
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const
Reimplemented from KCategorizedSortFilterProxyModel.
Definition: kdirsortfilterproxymodel.cpp:138
KDirSortFilterProxyModel::canFetchMore
virtual bool canFetchMore(const QModelIndex &parent) const
Reimplemented from QAbstractItemModel.
Definition: kdirsortfilterproxymodel.cpp:101
KDirSortFilterProxyModel::sortFoldersFirst
bool sortFoldersFirst() const
Returns if files and folders are sorted separately (with folders first) or not.
Definition: kdirsortfilterproxymodel.cpp:133
KDirSortFilterProxyModel::setSortFoldersFirst
void setSortFoldersFirst(bool foldersFirst)
Choose if files and folders are sorted separately (with folders first) or not.
Definition: kdirsortfilterproxymodel.cpp:128
KDirSortFilterProxyModel::~KDirSortFilterProxyModel
virtual ~KDirSortFilterProxyModel()
Definition: kdirsortfilterproxymodel.cpp:90
KFileItem
KFileItem::time
KDateTime time(FileTimes which) const
KFileItem::user
QString user() const
KFileItem::size
KIO::filesize_t size() const
KFileItem::ModificationTime
ModificationTime
KFileItem::mimetype
QString mimetype() const
KFileItem::group
QString group() const
KFileItem::isDir
bool isDir() const
KFileItem::url
KUrl url() const
KFileItem::text
QString text() const
KFileItem::isHidden
bool isHidden() const
KFileItem::name
QString name(bool lowerCase=false) const
KFileItem::mimeComment
QString mimeComment() const
KGlobalSettings
KGlobalSettings::self
static KGlobalSettings * self()
KGlobalSettings::naturalSorting
static bool naturalSorting()
KUrl::pathOrUrl
QString pathOrUrl() const
KUrl::url
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
QObject
kdatetime.h
kdirmodel.h
kdirsortfilterproxymodel.h
kfileitem.h
kglobalsettings.h
klocale.h
kstringhandler.h
KStringHandler::naturalCompare
int naturalCompare(const QString &a, const QString &b, Qt::CaseSensitivity caseSensitivity=Qt::CaseSensitive)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KFile

Skip menu "KFile"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal