dolphinsortfilterproxymodel.cpp 10.9 KB
Newer Older
1
/***************************************************************************
2 3 4
 *   Copyright (C) 2006 by Peter Penz <peter.penz@gmx.at>                  *
 *   Copyright (C) 2006 by Dominic Battre <dominic@battre.de>              *
 *   Copyright (C) 2006 by Martin Pool <mbp@canonical.com>                 *
5
 *   Copyright (C) 2007 by Rafael Fernández López <ereslibre@gmail.com>    *
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
 ***************************************************************************/
22 23 24

#include "dolphinsortfilterproxymodel.h"

25 26 27 28
#ifdef HAVE_NEPOMUK
#include <config-nepomuk.h>
#include <nepomuk/global.h>
#include <nepomuk/resource.h>
29
#include <nepomuk/tag.h>
30 31
#endif

32 33
#include <kdirmodel.h>
#include <kfileitem.h>
34
#include <kdatetime.h>
35
#include <klocale.h>
36

37
static DolphinView::Sorting sortingTypeTable[] =
Peter Penz's avatar
Peter Penz committed
38 39 40 41 42 43 44 45
{
    DolphinView::SortByName,        // KDirModel::Name
    DolphinView::SortBySize,        // KDirModel::Size
    DolphinView::SortByDate,        // KDirModel::ModifiedTime
    DolphinView::SortByPermissions, // KDirModel::Permissions
    DolphinView::SortByOwner,       // KDirModel::Owner
    DolphinView::SortByGroup,       // KDirModel::Group
    DolphinView::SortByType         // KDirModel::Type
46 47 48 49
#ifdef HAVE_NEPOMUK
    , DolphinView::SortByRating
    , DolphinView::SortByTags
#endif
Peter Penz's avatar
Peter Penz committed
50
};
51

52
DolphinSortFilterProxyModel::DolphinSortFilterProxyModel(QObject* parent) :
53
    KDirSortFilterProxyModel(parent),
54 55
    m_sorting(DolphinView::SortByName),
    m_sortOrder(Qt::AscendingOrder)
56 57 58 59
{
}

DolphinSortFilterProxyModel::~DolphinSortFilterProxyModel()
60 61
{
}
62 63 64

void DolphinSortFilterProxyModel::setSorting(DolphinView::Sorting sorting)
{
65 66
    // change the sorting column by keeping the current sort order
    sort(sorting, m_sortOrder);
67 68
}

69 70 71
void DolphinSortFilterProxyModel::setSortOrder(Qt::SortOrder sortOrder)
{
    // change the sort order by keeping the current column
72
    sort(m_sorting, sortOrder);
73 74
}

75 76
void DolphinSortFilterProxyModel::sort(int column, Qt::SortOrder sortOrder)
{
77
    m_sorting = sortingForColumn(column);
78
    m_sortOrder = sortOrder;
79
    setSortRole(m_sorting);
80
    KDirSortFilterProxyModel::sort(column, sortOrder);
81
    emit sortingRoleChanged();
82 83
}

84 85
DolphinView::Sorting DolphinSortFilterProxyModel::sortingForColumn(int column)
{
86 87 88
    Q_ASSERT(column >= 0);
    Q_ASSERT(column < static_cast<int>(sizeof(sortingTypeTable) / sizeof(DolphinView::Sorting)));
    return sortingTypeTable[column];
89 90
}

91 92 93 94 95
bool DolphinSortFilterProxyModel::lessThanGeneralPurpose(const QModelIndex &left,
                                                         const QModelIndex &right) const
{
    KDirModel* dirModel = static_cast<KDirModel*>(sourceModel());

96 97
    const KFileItem* leftFileItem  = dirModel->itemForIndex(left);
    const KFileItem* rightFileItem = dirModel->itemForIndex(right);
98

99
    //FIXME left.column() should be used instead!
100
    switch (sortRole()) {
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
    case DolphinView::SortByName: {
        QString leftFileName(leftFileItem->name());
        if (leftFileName.at(0) == '.') {
            leftFileName = leftFileName.mid(1);
        }

        QString rightFileName(rightFileItem->name());
        if (rightFileName.at(0) == '.') {
            rightFileName = rightFileName.mid(1);
        }

        // We don't care about case for building categories. We also don't
        // want here to compare by a natural comparison.
        return naturalCompare(leftFileName, rightFileName) < 0;
    }
116

117 118 119 120
    case DolphinView::SortBySize:
        // If we are sorting by size, show folders first. We will sort them
        // correctly later.
        return leftFileItem->isDir() && !rightFileItem->isDir();
121

122
    case DolphinView::SortByDate: {
123 124
        KDateTime leftTime = leftFileItem->time(KFileItem::ModificationTime);
        KDateTime rightTime = rightFileItem->time(KFileItem::ModificationTime);
125 126
        return leftTime > rightTime;
    }
127

128 129 130 131
    case DolphinView::SortByPermissions: {
        return naturalCompare(leftFileItem->permissionsString(),
                            rightFileItem->permissionsString()) < 0;
    }
132

133 134 135 136
    case DolphinView::SortByOwner: {
        return naturalCompare(leftFileItem->user().toLower(),
                              rightFileItem->user().toLower()) < 0;
    }
137

138 139 140 141
    case DolphinView::SortByGroup: {
        return naturalCompare(leftFileItem->group().toLower(),
                              rightFileItem->group().toLower()) < 0;
    }
142

143 144
    case DolphinView::SortByType: {
        // If we are sorting by size, show folders first. We will sort them
145
        // correctly later.
146 147 148 149 150
        if (leftFileItem->isDir() && !rightFileItem->isDir()) {
            return true;
        } else if (!leftFileItem->isDir() && rightFileItem->isDir()) {
            return false;
        }
151

152 153 154
        return naturalCompare(leftFileItem->mimeComment().toLower(),
                              rightFileItem->mimeComment().toLower()) < 0;
    }
155 156 157 158 159 160
#ifdef HAVE_NEPOMUK
    case DolphinView::SortByRating: {
        const quint32 leftRating = ratingForIndex(left);
        const quint32 rightRating = ratingForIndex(right);
        return leftRating > rightRating;
    }
161
    case DolphinView::SortByTags: {
162 163 164 165 166 167 168 169
        const QString leftTags = tagsForIndex(left);
        const QString rightTags = tagsForIndex(right);

        if (leftTags.isEmpty() && !rightTags.isEmpty())
            return false;
        else if (!leftTags.isEmpty() && rightTags.isEmpty())
            return true;

170 171
        return naturalCompare(tagsForIndex(left), tagsForIndex(right)) < 0;
    }
172 173 174
#endif
    default:
        break;
175
    }
Dirk Mueller's avatar
Dirk Mueller committed
176
    return false;
177 178
}

179
bool DolphinSortFilterProxyModel::lessThan(const QModelIndex& left,
180
                                           const QModelIndex& right) const
181
{
182
#ifdef HAVE_NEPOMUK
183 184
    KDirModel* dirModel = static_cast<KDirModel*>(sourceModel());

185 186
    const KFileItem* leftFileItem  = dirModel->itemForIndex(left);
    const KFileItem* rightFileItem = dirModel->itemForIndex(right);
187 188


189
    // Hidden elements go before visible ones, if they both are
190
    // folders or files.
191 192
    if (leftFileItem->isHidden() && !rightFileItem->isHidden()) {
        return true;
193
    } else if (!leftFileItem->isHidden() && rightFileItem->isHidden()) {
194 195
        return false;
    }
196

197
    //FIXME left.column() should be used instead!
198
    switch (sortRole()) {
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
    case DolphinView::SortByRating: {
        const quint32 leftRating  = ratingForIndex(left);
        const quint32 rightRating = ratingForIndex(right);

        if (leftRating == rightRating) {
            // On our priority, folders go above regular files.
            // This checks are needed (don't think it's the same doing it here
            // than above). Here we make dirs citizens of first class because
            // we know we are on the same category. On the check we do on the
            // top of the method we don't know, so we remove that check when we
            // are sorting by rating. (ereslibre)
            if (leftFileItem->isDir() && !rightFileItem->isDir()) {
                return true;
            } else if (!leftFileItem->isDir() && rightFileItem->isDir()) {
                return false;
214 215
            }

216 217 218
            return sortCaseSensitivity() ?
                   (naturalCompare(leftFileItem->name(), rightFileItem->name()) < 0) :
                   (naturalCompare(leftFileItem->name().toLower(), rightFileItem->name().toLower()) < 0);
219
        }
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246

        return leftRating > rightRating;
    }

    case DolphinView::SortByTags: {
        const QString leftTags = tagsForIndex(left);
        const QString rightTags = tagsForIndex(right);

        if (leftTags == rightTags) {
            // On our priority, folders go above regular files.
            // This checks are needed (don't think it's the same doing it here
            // than above). Here we make dirs citizens of first class because
            // we know we are on the same category. On the check we do on the
            // top of the method we don't know, so we remove that check when we
            // are sorting by tags. (ereslibre)
            if (leftFileItem->isDir() && !rightFileItem->isDir()) {
                return true;
            } else if (!leftFileItem->isDir() && rightFileItem->isDir()) {
                return false;
            }

            return sortCaseSensitivity() ?
                   (naturalCompare(leftFileItem->name(), rightFileItem->name()) < 0) :
                   (naturalCompare(leftFileItem->name().toLower(), rightFileItem->name().toLower()) < 0);
        }

        return naturalCompare(leftTags, rightTags) < 0;
247
    }
248
    }
249
#endif
250

251
    return KDirSortFilterProxyModel::lessThan(left, right);
252 253
}

254
quint32 DolphinSortFilterProxyModel::ratingForIndex(const QModelIndex& index)
255 256 257 258
{
#ifdef HAVE_NEPOMUK
    quint32 rating = 0;

259
    const KDirModel* dirModel = static_cast<const KDirModel*>(index.model());
260 261 262 263 264 265 266 267 268 269 270 271
    KFileItem* item = dirModel->itemForIndex(index);
    if (item != 0) {
        const Nepomuk::Resource resource(item->url().url(), Nepomuk::NFO::File());
        rating = resource.rating();
    }
    return rating;
#else
    Q_UNUSED(index);
    return 0;
#endif
}

272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
QString DolphinSortFilterProxyModel::tagsForIndex(const QModelIndex& index)
{
#ifdef HAVE_NEPOMUK
    QString tagsString;

    const KDirModel* dirModel = static_cast<const KDirModel*>(index.model());
    KFileItem* item = dirModel->itemForIndex(index);
    if (item != 0) {
        const Nepomuk::Resource resource(item->url().url(), Nepomuk::NFO::File());
        const QList<Nepomuk::Tag> tags = resource.tags();
        QStringList stringList;
        foreach (const Nepomuk::Tag& tag, tags) {
            stringList.append(tag.label());
        }
        stringList.sort();

        foreach (const QString& str, stringList) {
            tagsString += str;
290
            tagsString += ", ";
291 292
        }

293
        if (!tagsString.isEmpty()) {
294
            tagsString.resize(tagsString.size() - 2);
295
        }
296 297 298 299
    }

    return tagsString;
#else
300
    Q_UNUSED(index);
301 302 303 304
    return QString();
#endif
}

305
#include "dolphinsortfilterproxymodel.moc"