• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.10.5 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 
33 class KDirSortFilterProxyModel::KDirSortFilterProxyModelPrivate
34 {
35 public:
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 
45 KDirSortFilterProxyModel::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 
53 int 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 
73 void KDirSortFilterProxyModel::KDirSortFilterProxyModelPrivate::slotNaturalSortingChanged()
74 {
75  m_naturalSorting = KGlobalSettings::naturalSorting();
76 }
77 
78 KDirSortFilterProxyModel::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 
90 KDirSortFilterProxyModel::~KDirSortFilterProxyModel()
91 {
92  delete d;
93 }
94 
95 bool KDirSortFilterProxyModel::hasChildren(const QModelIndex& parent) const
96 {
97  const QModelIndex sourceParent = mapToSource(parent);
98  return sourceModel()->hasChildren(sourceParent);
99 }
100 
101 bool KDirSortFilterProxyModel::canFetchMore(const QModelIndex& parent) const
102 {
103  const QModelIndex sourceParent = mapToSource(parent);
104  return sourceModel()->canFetchMore(sourceParent);
105 }
106 
107 int 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 
128 void KDirSortFilterProxyModel::setSortFoldersFirst(bool foldersFirst)
129 {
130  d->m_sortFoldersFirst = foldersFirst;
131 }
132 
133 bool KDirSortFilterProxyModel::sortFoldersFirst() const
134 {
135  return d->m_sortFoldersFirst;
136 }
137 
138 bool 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"
QVariant
KCategorizedSortFilterProxyModel::subSortLessThan
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const
KDirModel::Group
KDirSortFilterProxyModel::canFetchMore
virtual bool canFetchMore(const QModelIndex &parent) const
Reimplemented from QAbstractItemModel.
Definition: kdirsortfilterproxymodel.cpp:101
KDirModel::ChildCountUnknown
KFileItem::isDir
bool isDir() const
KStringHandler::naturalCompare
int naturalCompare(const QString &a, const QString &b, Qt::CaseSensitivity caseSensitivity=Qt::CaseSensitive)
kdatetime.h
kglobalsettings.h
KFileItem::mimetype
QString mimetype() const
KFileItem::user
QString user() const
KDirSortFilterProxyModel::setSortFoldersFirst
void setSortFoldersFirst(bool foldersFirst)
Choose if files and folders are sorted separately (with folders first) or not.
Definition: kdirsortfilterproxymodel.cpp:128
KDirSortFilterProxyModel
Acts as proxy model for KDirModel to sort and filter KFileItems.
Definition: kdirsortfilterproxymodel.h:50
KDirModel::Permissions
KDirModel::data
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
KCategorizedSortFilterProxyModel::sortOrder
Qt::SortOrder sortOrder() const
KCategorizedSortFilterProxyModel
QString
KGlobalSettings::self
static KGlobalSettings * self()
QObject
klocale.h
KDirModel::ChildCountRole
KDirModel::itemForIndex
KFileItem itemForIndex(const QModelIndex &index) const
KFileItem::ModificationTime
KDirSortFilterProxyModel::sortFoldersFirst
bool sortFoldersFirst() const
Returns if files and folders are sorted separately (with folders first) or not.
Definition: kdirsortfilterproxymodel.cpp:133
KUrl::pathOrUrl
QString pathOrUrl() const
KFileItem::mimeComment
QString mimeComment() const
KFileItem::group
QString group() const
KFileItem::size
KIO::filesize_t size() const
KDirSortFilterProxyModel::KDirSortFilterProxyModel
KDirSortFilterProxyModel(QObject *parent=0)
Definition: kdirsortfilterproxymodel.cpp:78
KFileItem::text
QString text() const
KDirModel::Name
KGlobalSettings
KDateTime
kstringhandler.h
KDirModel::Type
kdirmodel.h
kdirsortfilterproxymodel.h
KDateTime::toLocalZone
KDateTime toLocalZone() const
KFileItem::time
KDateTime time(FileTimes which) const
KDirSortFilterProxyModel::pointsForPermissions
static int pointsForPermissions(const QFileInfo &info)
Returns the permissions in &quot;points&quot;.
Definition: kdirsortfilterproxymodel.cpp:107
KFileItem::name
QString name(bool lowerCase=false) const
KDirModel::ModifiedTime
KFileItem::isHidden
bool isHidden() const
KDirSortFilterProxyModel::hasChildren
virtual bool hasChildren(const QModelIndex &parent=QModelIndex()) const
Reimplemented from QAbstractItemModel.
Definition: kdirsortfilterproxymodel.cpp:95
KUrl::url
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
KCategorizedSortFilterProxyModel::sort
virtual void sort(int column, Qt::SortOrder order=Qt::AscendingOrder)
KDirSortFilterProxyModel::subSortLessThan
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const
Reimplemented from KCategorizedSortFilterProxyModel.
Definition: kdirsortfilterproxymodel.cpp:138
KDirModel::Size
KDirModel
kfileitem.h
KFileItem::url
KUrl url() const
KDirModel::Owner
KFileItem
KDirSortFilterProxyModel::~KDirSortFilterProxyModel
virtual ~KDirSortFilterProxyModel()
Definition: kdirsortfilterproxymodel.cpp:90
KGlobalSettings::naturalSorting
static bool naturalSorting()
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Mon Jun 9 2014 22:03:41 by doxygen 1.8.5 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KFile

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

kdelibs-4.10.5 API Reference

Skip menu "kdelibs-4.10.5 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