2 * This file is part of the KDE project
3 * Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
21 #include "dolphinmodel.h"
23 #include "dolphinsortfilterproxymodel.h"
25 #include "kcategorizedview.h"
27 #include <config-nepomuk.h>
29 #include <nepomuk/global.h>
30 #include <nepomuk/resource.h>
31 #include <nepomuk/tag.h>
34 #include <kdatetime.h>
35 #include <kdirmodel.h>
36 #include <kfileitem.h>
37 #include <kiconloader.h>
41 #include <kmimetype.h>
42 #include <kstandarddirs.h>
45 #include <QSortFilterProxyModel>
50 DolphinModel::DolphinModel(QObject
*parent
)
55 DolphinModel::~DolphinModel()
59 QVariant
DolphinModel::data(const QModelIndex
&index
, int role
) const
61 if (role
== KCategorizedSortFilterProxyModel::CategoryDisplayRole
)
70 const KDirModel
*dirModel
= qobject_cast
<const KDirModel
*>(index
.model());
71 KFileItem item
= dirModel
->itemForIndex(index
);
73 switch (index
.column())
77 // KDirModel checks columns to know to which role are
79 QModelIndex theIndex
= index
.model()->index(index
.row(),
83 if (!theIndex
.isValid()) {
87 QVariant data
= theIndex
.model()->data(theIndex
, Qt::DisplayRole
);
88 if (data
.toString().size())
90 if (!item
.isHidden() && data
.toString().at(0).isLetter())
91 retString
= data
.toString().toUpper().at(0);
92 else if (item
.isHidden() && data
.toString().at(0) == '.' &&
93 data
.toString().at(1).isLetter())
94 retString
= data
.toString().toUpper().at(1);
95 else if (item
.isHidden() && data
.toString().at(0) == '.' &&
96 !data
.toString().at(1).isLetter())
97 retString
= i18nc("@title:group Name", "Others");
98 else if (item
.isHidden() && data
.toString().at(0) != '.')
99 retString
= data
.toString().toUpper().at(0);
100 else if (item
.isHidden())
101 retString
= data
.toString().toUpper().at(0);
104 bool validCategory
= false;
106 const QString
str(data
.toString().toUpper());
107 const QChar
* currA
= str
.unicode();
108 while (!currA
->isNull() && !validCategory
) {
109 if (currA
->isLetter())
110 validCategory
= true;
111 else if (currA
->isDigit())
112 return i18nc("@title:group", "Others");
118 retString
= i18nc("@title:group Name", "Others");
126 case KDirModel::Size
: {
127 const int fileSize
= !item
.isNull() ? item
.size() : -1;
128 if (!item
.isNull() && item
.isDir()) {
129 retString
= i18nc("@title:group Size", "Folders");
130 } else if (fileSize
< 5242880) {
131 retString
= i18nc("@title:group Size", "Small");
132 } else if (fileSize
< 10485760) {
133 retString
= i18nc("@title:group Size", "Medium");
135 retString
= i18nc("@title:group Size", "Big");
140 case KDirModel::ModifiedTime
:
142 KDateTime modifiedTime
;
143 modifiedTime
.setTime_t(item
.time(KIO::UDSEntry::UDS_MODIFICATION_TIME
));
144 modifiedTime
= modifiedTime
.toLocalZone();
146 retString
= modifiedTime
.toString(i18nc("Prints out the month and year: %B is full month name in current locale, and %Y is full year number", "%B, %Y"));
150 case KDirModel::Permissions
:
156 QFileInfo
info(item
.url().pathOrUrl());
158 if (info
.permission(QFile::ReadUser
))
159 user
= i18n("Read, ");
161 if (info
.permission(QFile::WriteUser
))
162 user
+= i18n("Write, ");
164 if (info
.permission(QFile::ExeUser
))
165 user
+= i18n("Execute, ");
168 user
= i18n("Forbidden");
170 user
= user
.mid(0, user
.count() - 2);
172 if (info
.permission(QFile::ReadGroup
))
173 group
= i18n("Read, ");
175 if (info
.permission(QFile::WriteGroup
))
176 group
+= i18n("Write, ");
178 if (info
.permission(QFile::ExeGroup
))
179 group
+= i18n("Execute, ");
182 group
= i18n("Forbidden");
184 group
= group
.mid(0, group
.count() - 2);
186 if (info
.permission(QFile::ReadOther
))
187 others
= i18n("Read, ");
189 if (info
.permission(QFile::WriteOther
))
190 others
+= i18n("Write, ");
192 if (info
.permission(QFile::ExeOther
))
193 others
+= i18n("Execute, ");
195 if (others
.isEmpty())
196 others
= i18n("Forbidden");
198 others
= others
.mid(0, others
.count() - 2);
200 retString
= i18nc("This shows files and folders permissions: user, group and others", "(User: %1) (Group: %2) (Others: %3)", user
, group
, others
);
204 case KDirModel::Owner
:
205 retString
= item
.user();
208 case KDirModel::Group
:
209 retString
= item
.group();
212 case KDirModel::Type
:
213 retString
= item
.mimeComment();
217 case DolphinModel::Rating
: {
218 const quint32 rating
= ratingForIndex(index
);
220 retString
= QString::number(rating
);
224 case DolphinModel::Tags
: {
225 retString
= tagsForIndex(index
);
227 if (retString
.isEmpty())
228 retString
= i18nc("@title:group Tags", "Not yet tagged");
237 else if (role
== KCategorizedSortFilterProxyModel::CategorySortRole
)
242 if (!index
.isValid())
247 const KDirModel
*dirModel
= qobject_cast
<const KDirModel
*>(index
.model());
248 KFileItem item
= dirModel
->itemForIndex(index
);
250 switch (index
.column()) {
251 case KDirModel::Name
: {
252 bool leftFileNameStartsByLetter
= false;
253 const QString
str(leftFileItem
.name().toUpper());
254 const QChar
* currA
= str
.unicode();
255 while (!currA
->isNull() && !leftFileNameStartsByLetter
) {
256 if (currA
->isLetter())
257 leftFileNameStartsByLetter
= true;
258 else if (currA
->isDigit()) {
264 bool rightFileNameStartsByLetter
= false;
265 const QString
strb(rightFileItem
.name().toUpper());
266 const QChar
*currB
= strb
.unicode();
267 while (!currB
->isNull() && !rightFileNameStartsByLetter
) {
268 if (currB
->isLetter())
269 rightFileNameStartsByLetter
= true;
270 else if (currB
->isDigit()) {
276 if (!rightFileNameStartsByLetter
)
279 if (!leftFileNameStartsByLetter
&& rightFileNameStartsByLetter
)
282 return naturalCompare(*currA
, *currB
);
285 case KDirModel::Size
: {
286 // If we are sorting by size, show folders first. We will sort them
288 if (leftFileItem
.isDir() && !rightFileItem
.isDir()) {
292 if (!leftFileItem
.isDir() && rightFileItem
.isDir()) {
296 if (leftFileItem
.isDir() && rightFileItem
.isDir()) {
300 const int leftFileSize
= !leftFileItem
.isNull() ? leftFileItem
.size() : -1;
301 const int rightFileSize
= !rightFileItem
.isNull() ? rightFileItem
.size() : -1;
305 if (leftFileSize
< 5242880) {
307 } else if (leftFileSize
< 10485760) {
313 if (rightFileSize
< 5242880) {
315 } else if (rightFileSize
< 10485760) {
321 return leftGroup
- rightGroup
;
324 case KDirModel::ModifiedTime
: {
325 KDateTime leftTime
= leftFileItem
.time(KFileItem::ModificationTime
);
326 KDateTime rightTime
= rightFileItem
.time(KFileItem::ModificationTime
);
328 if ((leftTime
.date().year() == rightTime
.date().year()) &&
329 (leftTime
.date().month() == rightTime
.date().month())) {
333 if (leftTime
> rightTime
) {
340 case KDirModel::Permissions
: {
341 QFileInfo
leftFileInfo(leftFileItem
.url().pathOrUrl());
342 QFileInfo
rightFileInfo(rightFileItem
.url().pathOrUrl());
344 int leftPermissionsPoints
= pointsForPermissions(leftFileInfo
);
345 int rightPermissionsPoints
= pointsForPermissions(rightFileInfo
);
347 return leftPermissionsPoints
- rightPermissionsPoints
;
350 case KDirModel::Owner
: {
351 return naturalCompare(leftFileItem
.user().toLower(),
352 rightFileItem
.user().toLower());
355 case KDirModel::Group
: {
356 return naturalCompare(leftFileItem
.group().toLower(),
357 rightFileItem
.group().toLower());
360 case KDirModel::Type
: {
361 // If we are sorting by size, show folders first. We will sort them
363 if (leftFileItem
.isDir() && !rightFileItem
.isDir()) {
365 } else if (!leftFileItem
.isDir() && rightFileItem
.isDir()) {
369 return naturalCompare(leftFileItem
.mimeComment().toLower(),
370 rightFileItem
.mimeComment().toLower());
374 case DolphinView::SortByRating
: {
375 const qint32 leftRating
= DolphinModel::ratingForIndex(left
);
376 const qint32 rightRating
= DolphinModel::ratingForIndex(right
);
377 return leftRating
- rightRating
;
380 case DolphinView::SortByTags
: {
381 const QString leftTags
= DolphinModel::tagsForIndex(left
);
382 const QString rightTags
= DolphinModel::tagsForIndex(right
);
384 if (leftTags
.isEmpty() && !rightTags
.isEmpty())
386 else if (!leftTags
.isEmpty() && rightTags
.isEmpty())
389 return naturalCompare(DolphinModel::tagsForIndex(left
), DolphinModel::tagsForIndex(right
)) < 0;
400 if (!index
.isValid())
405 const KDirModel
*dirModel
= qobject_cast
<const KDirModel
*>(index
.model());
406 KFileItem item
= dirModel
->itemForIndex(index
);
408 switch (index
.column())
410 case KDirModel::Name
:
412 // KDirModel checks columns to know to which role are
414 QModelIndex theIndex
= index
.model()->index(index
.row(),
418 if (!theIndex
.isValid()) {
422 QVariant data
= theIndex
.model()->data(theIndex
, Qt::DisplayRole
);
423 if (data
.toString().size())
425 if (!item
.isHidden() && data
.toString().at(0).isLetter())
426 retString
= data
.toString().toUpper().at(0);
427 else if (item
.isHidden() && data
.toString().at(0) == '.' &&
428 data
.toString().at(1).isLetter())
429 retString
= data
.toString().toUpper().at(1);
430 else if (item
.isHidden() && data
.toString().at(0) == '.' &&
431 !data
.toString().at(1).isLetter())
432 retString
= i18nc("@title:group Name", "Others");
433 else if (item
.isHidden() && data
.toString().at(0) != '.')
434 retString
= data
.toString().toUpper().at(0);
435 else if (item
.isHidden())
436 retString
= data
.toString().toUpper().at(0);
439 bool validCategory
= false;
441 const QString
str(data
.toString().toUpper());
442 const QChar
* currA
= str
.unicode();
443 while (!currA
->isNull() && !validCategory
) {
444 if (currA
->isLetter())
445 validCategory
= true;
446 else if (currA
->isDigit())
447 return i18nc("@title:group", "Others");
453 retString
= i18nc("@title:group Name", "Others");
461 case KDirModel::Size
: {
462 const int fileSize
= !item
.isNull() ? item
.size() : -1;
463 if (!item
.isNull() && item
.isDir()) {
464 retString
= i18nc("@title:group Size", "Folders");
465 } else if (fileSize
< 5242880) {
466 retString
= i18nc("@title:group Size", "Small");
467 } else if (fileSize
< 10485760) {
468 retString
= i18nc("@title:group Size", "Medium");
470 retString
= i18nc("@title:group Size", "Big");
475 case KDirModel::ModifiedTime
:
477 KDateTime modifiedTime
;
478 modifiedTime
.setTime_t(item
.time(KIO::UDSEntry::UDS_MODIFICATION_TIME
));
479 modifiedTime
= modifiedTime
.toLocalZone();
481 retString
= modifiedTime
.toString(i18nc("Prints out the month and year: %B is full month name in current locale, and %Y is full year number", "%B, %Y"));
485 case KDirModel::Permissions
:
491 QFileInfo
info(item
.url().pathOrUrl());
493 if (info
.permission(QFile::ReadUser
))
494 user
= i18n("Read, ");
496 if (info
.permission(QFile::WriteUser
))
497 user
+= i18n("Write, ");
499 if (info
.permission(QFile::ExeUser
))
500 user
+= i18n("Execute, ");
503 user
= i18n("Forbidden");
505 user
= user
.mid(0, user
.count() - 2);
507 if (info
.permission(QFile::ReadGroup
))
508 group
= i18n("Read, ");
510 if (info
.permission(QFile::WriteGroup
))
511 group
+= i18n("Write, ");
513 if (info
.permission(QFile::ExeGroup
))
514 group
+= i18n("Execute, ");
517 group
= i18n("Forbidden");
519 group
= group
.mid(0, group
.count() - 2);
521 if (info
.permission(QFile::ReadOther
))
522 others
= i18n("Read, ");
524 if (info
.permission(QFile::WriteOther
))
525 others
+= i18n("Write, ");
527 if (info
.permission(QFile::ExeOther
))
528 others
+= i18n("Execute, ");
530 if (others
.isEmpty())
531 others
= i18n("Forbidden");
533 others
= others
.mid(0, others
.count() - 2);
535 retString
= i18nc("This shows files and folders permissions: user, group and others", "(User: %1) (Group: %2) (Others: %3)", user
, group
, others
);
539 case KDirModel::Owner
:
540 retString
= item
.user();
543 case KDirModel::Group
:
544 retString
= item
.group();
547 case KDirModel::Type
:
548 retString
= item
.mimeComment();
552 case DolphinModel::Rating
: {
553 const quint32 rating
= ratingForIndex(index
);
555 retString
= QString::number(rating
);
559 case DolphinModel::Tags
: {
560 retString
= tagsForIndex(index
);
562 if (retString
.isEmpty())
563 retString
= i18nc("@title:group Tags", "Not yet tagged");
573 return KDirModel::data(index
, role
);
576 int DolphinModel::columnCount(const QModelIndex
&parent
) const
578 return KDirModel::columnCount(parent
) + (ExtraColumnCount
- ColumnCount
);
581 quint32
DolphinModel::ratingForIndex(const QModelIndex
& index
)
586 const DolphinModel
* dolphinModel
= static_cast<const DolphinModel
*>(index
.model());
587 KFileItem item
= dolphinModel
->itemForIndex(index
);
588 if (!item
.isNull()) {
589 const Nepomuk::Resource
resource(item
.url().url(), Nepomuk::NFO::File());
590 rating
= resource
.rating();
599 QString
DolphinModel::tagsForIndex(const QModelIndex
& index
)
604 const DolphinModel
* dolphinModel
= static_cast<const DolphinModel
*>(index
.model());
605 KFileItem item
= dolphinModel
->itemForIndex(index
);
606 if (!item
.isNull()) {
607 const Nepomuk::Resource
resource(item
.url().url(), Nepomuk::NFO::File());
608 const QList
<Nepomuk::Tag
> tags
= resource
.tags();
609 QStringList stringList
;
610 foreach (const Nepomuk::Tag
& tag
, tags
) {
611 stringList
.append(tag
.label());
615 foreach (const QString
& str
, stringList
) {
620 if (!tagsString
.isEmpty()) {
621 tagsString
.resize(tagsString
.size() - 2);