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

KFile

kdirsortfilterproxymodel.cpp

Go to the documentation of this file.
00001 /*
00002    Copyright (C) 2006 by Peter Penz <peter.penz@gmx.at>
00003    Copyright (C) 2006 by Dominic Battre <dominic@battre.de>
00004    Copyright (C) 2006 by Martin Pool <mbp@canonical.com>
00005 
00006    Separated from Dolphin by Nick Shaforostoff <shafff@ukr.net>
00007 
00008    This library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Library General Public
00010    License version 2 as published by the Free Software Foundation.
00011 
00012    This library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Library General Public License for more details.
00016 
00017    You should have received a copy of the GNU Library General Public License
00018    along with this library; see the file COPYING.LIB.  If not, write to
00019    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020    Boston, MA 02110-1301, USA.
00021 */
00022 
00023 #include "kdirsortfilterproxymodel.h"
00024 
00025 #include <kdatetime.h>
00026 #include <kdirmodel.h>
00027 #include <kfileitem.h>
00028 #include <kglobalsettings.h>
00029 #include <klocale.h>
00030 #include <kstringhandler.h>
00031 
00032 
00033 class KDirSortFilterProxyModel::KDirSortFilterProxyModelPrivate
00034 {
00035 public:
00036     KDirSortFilterProxyModelPrivate(KDirSortFilterProxyModel* q);
00037 
00038     int compare(const QString&, const QString&, Qt::CaseSensitivity caseSensitivity  = Qt::CaseSensitive) const;
00039     void slotNaturalSortingChanged();
00040 
00041     bool m_sortFoldersFirst;
00042     bool m_naturalSorting;
00043 };
00044 
00045 KDirSortFilterProxyModel::KDirSortFilterProxyModelPrivate::KDirSortFilterProxyModelPrivate(KDirSortFilterProxyModel* q) :
00046     m_sortFoldersFirst(true),
00047     m_naturalSorting(KGlobalSettings::naturalSorting())
00048 {
00049     connect(KGlobalSettings::self(), SIGNAL(naturalSortingChanged()),
00050             q, SLOT(slotNaturalSortingChanged()));
00051 }
00052 
00053 int KDirSortFilterProxyModel::KDirSortFilterProxyModelPrivate::compare(const QString& a,
00054                                                                        const QString& b,
00055                                                                        Qt::CaseSensitivity caseSensitivity) const
00056 {
00057     if (caseSensitivity == Qt::CaseInsensitive) {
00058         const int result = m_naturalSorting ? KStringHandler::naturalCompare(a, b, Qt::CaseInsensitive)
00059                                             : QString::compare(a, b, Qt::CaseInsensitive);
00060         if (result != 0) {
00061             // Only return the result, if the strings are not equal. If they are equal by a case insensitive
00062             // comparison, still a deterministic sort order is required. A case sensitive
00063             // comparison is done as fallback.
00064             return result;
00065         }
00066     }
00067     
00068     return m_naturalSorting ? KStringHandler::naturalCompare(a, b, Qt::CaseSensitive)
00069                             : QString::compare(a, b, Qt::CaseSensitive);
00070 }
00071 
00072 
00073 void KDirSortFilterProxyModel::KDirSortFilterProxyModelPrivate::slotNaturalSortingChanged()
00074 {
00075     m_naturalSorting = KGlobalSettings::naturalSorting();
00076 }
00077 
00078 KDirSortFilterProxyModel::KDirSortFilterProxyModel(QObject* parent)
00079     : KCategorizedSortFilterProxyModel(parent), d(new KDirSortFilterProxyModelPrivate(this))
00080 {
00081     setDynamicSortFilter(true);
00082 
00083     // sort by the user visible string for now
00084     setSortCaseSensitivity(Qt::CaseInsensitive);
00085     sort(KDirModel::Name, Qt::AscendingOrder);
00086 
00087     setSupportedDragActions(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction | Qt::IgnoreAction);
00088 }
00089 
00090 KDirSortFilterProxyModel::~KDirSortFilterProxyModel()
00091 {
00092     delete d;
00093 }
00094 
00095 bool KDirSortFilterProxyModel::hasChildren(const QModelIndex& parent) const
00096 {
00097     const QModelIndex sourceParent = mapToSource(parent);
00098     return sourceModel()->hasChildren(sourceParent);
00099 }
00100 
00101 bool KDirSortFilterProxyModel::canFetchMore(const QModelIndex& parent) const
00102 {
00103     const QModelIndex sourceParent = mapToSource(parent);
00104     return sourceModel()->canFetchMore(sourceParent);
00105 }
00106 
00107 int KDirSortFilterProxyModel::pointsForPermissions(const QFileInfo &info)
00108 {
00109     int points = 0;
00110 
00111     QFile::Permission permissionsCheck[] = { QFile::ReadUser,
00112                                              QFile::WriteUser,
00113                                              QFile::ExeUser,
00114                                              QFile::ReadGroup,
00115                                              QFile::WriteGroup,
00116                                              QFile::ExeGroup,
00117                                              QFile::ReadOther,
00118                                              QFile::WriteOther,
00119                                              QFile::ExeOther };
00120 
00121     for (int i = 0; i < 9; i++) {
00122         points += info.permission(permissionsCheck[i]) ? 1 : 0;
00123     }
00124 
00125     return points;
00126 }
00127 
00128 void KDirSortFilterProxyModel::setSortFoldersFirst(bool foldersFirst)
00129 {
00130     d->m_sortFoldersFirst = foldersFirst;
00131 }
00132 
00133 bool KDirSortFilterProxyModel::sortFoldersFirst() const
00134 {
00135     return d->m_sortFoldersFirst;
00136 }
00137 
00138 bool KDirSortFilterProxyModel::subSortLessThan(const QModelIndex& left,
00139                                                const QModelIndex& right) const
00140 {
00141     KDirModel* dirModel = static_cast<KDirModel*>(sourceModel());
00142 
00143     const KFileItem leftFileItem  = dirModel->itemForIndex(left);
00144     const KFileItem rightFileItem = dirModel->itemForIndex(right);
00145 
00146     const bool isLessThan = (sortOrder() == Qt::AscendingOrder);
00147 
00148     // Folders go before files if the corresponding setting is set.
00149     if (d->m_sortFoldersFirst) {
00150         const bool leftItemIsDir  = leftFileItem.isDir();
00151         const bool rightItemIsDir = rightFileItem.isDir();
00152         if (leftItemIsDir && !rightItemIsDir) {
00153             return isLessThan;
00154         } else if (!leftItemIsDir && rightItemIsDir) {
00155             return !isLessThan;
00156         }
00157     }
00158 
00159 
00160     // Hidden elements go before visible ones.
00161     const bool leftItemIsHidden  = leftFileItem.isHidden();
00162     const bool rightItemIsHidden = rightFileItem.isHidden();
00163     if (leftItemIsHidden && !rightItemIsHidden) {
00164         return isLessThan;
00165     } else if (!leftItemIsHidden && rightItemIsHidden) {
00166         return !isLessThan;
00167     }
00168 
00169     switch (left.column()) {
00170     case KDirModel::Name: {
00171         // KFileItem::text() may not be unique (in case UDS_DISPLAY_NAME is used). In that case we
00172         // fall back to the name which is always unique
00173         const int result = d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity());
00174         if (result == 0) {
00175             return d->compare(leftFileItem.name(sortCaseSensitivity() == Qt::CaseInsensitive),
00176                               rightFileItem.name(sortCaseSensitivity() == Qt::CaseInsensitive),
00177                               sortCaseSensitivity()) < 0;
00178         } else {
00179             return result < 0;
00180         }
00181     }
00182 
00183     case KDirModel::Size: {
00184         // If we have two folders, what we have to measure is the number of
00185         // items that contains each other
00186         if (leftFileItem.isDir() && rightFileItem.isDir()) {
00187             QVariant leftValue = dirModel->data(left, KDirModel::ChildCountRole);
00188             int leftCount = (leftValue.type() == QVariant::Int) ? leftValue.toInt() : KDirModel::ChildCountUnknown;
00189 
00190             QVariant rightValue = dirModel->data(right, KDirModel::ChildCountRole);
00191             int rightCount = (rightValue.type() == QVariant::Int) ? rightValue.toInt() : KDirModel::ChildCountUnknown;
00192 
00193             // In the case they two have the same child items, we sort them by
00194             // their names. So we have always everything ordered. We also check
00195             // if we are taking in count their cases.
00196             if (leftCount == rightCount) {
00197                 return d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity()) < 0;
00198             }
00199 
00200             // If one of them has unknown child items, place them on the end. If we
00201             // were comparing two unknown childed items, the previous comparation
00202             // sorted them by naturalCompare between them. This case is when we
00203             // have an unknown childed item, and another known.
00204             if (leftCount == KDirModel::ChildCountUnknown) {
00205                 return false;
00206             }
00207 
00208             if (rightCount == KDirModel::ChildCountUnknown) {
00209                 return true;
00210             }
00211 
00212             // If they had different number of items, we sort them depending
00213             // on how many items had each other.
00214             return leftCount < rightCount;
00215         }
00216 
00217         // If what we are measuring is two files and they have the same size,
00218         // sort them by their file names.
00219         if (leftFileItem.size() == rightFileItem.size()) {
00220             return d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity()) < 0;
00221         }
00222 
00223         // If their sizes are different, sort them by their sizes, as expected.
00224         return leftFileItem.size() < rightFileItem.size();
00225     }
00226 
00227     case KDirModel::ModifiedTime: {
00228         KDateTime leftModifiedTime = leftFileItem.time(KFileItem::ModificationTime).toLocalZone();
00229         KDateTime rightModifiedTime = rightFileItem.time(KFileItem::ModificationTime).toLocalZone();
00230 
00231         if (leftModifiedTime == rightModifiedTime) {
00232             return d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity()) < 0;
00233         }
00234 
00235         return leftModifiedTime < rightModifiedTime;
00236     }
00237 
00238     case KDirModel::Permissions: {
00239         // ### You can't use QFileInfo on urls!! Use the KFileItem instead.
00240         QFileInfo leftFileInfo(leftFileItem.url().pathOrUrl());
00241         QFileInfo rightFileInfo(rightFileItem.url().pathOrUrl());
00242 
00243         int leftPermissionsPoints = pointsForPermissions(leftFileInfo);
00244         int rightPermissionsPoints = pointsForPermissions(rightFileInfo);
00245 
00246         if (leftPermissionsPoints == rightPermissionsPoints) {
00247             return d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity()) < 0;
00248         }
00249 
00250         return leftPermissionsPoints > rightPermissionsPoints;
00251     }
00252 
00253     case KDirModel::Owner: {
00254         if (leftFileItem.user() == rightFileItem.user()) {
00255             return d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity()) < 0;
00256         }
00257 
00258         return d->compare(leftFileItem.user(), rightFileItem.user()) < 0;
00259     }
00260 
00261     case KDirModel::Group: {
00262         if (leftFileItem.group() == rightFileItem.group()) {
00263             return d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity()) < 0;
00264         }
00265 
00266         return d->compare(leftFileItem.group(), rightFileItem.group()) < 0;
00267     }
00268 
00269     case KDirModel::Type: {
00270         if (leftFileItem.mimetype() == rightFileItem.mimetype()) {
00271             return d->compare(leftFileItem.text(), rightFileItem.text(), sortCaseSensitivity()) < 0;
00272         }
00273 
00274         return d->compare(leftFileItem.mimeComment(), rightFileItem.mimeComment()) < 0;
00275     }
00276 
00277     }
00278 
00279     // We have set a SortRole and trust the ProxyModel to do
00280     // the right thing for now.
00281     return KCategorizedSortFilterProxyModel::subSortLessThan(left, right);
00282 }
00283 
00284 #include "kdirsortfilterproxymodel.moc"

KFile

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • 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
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal