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>
32 #include <Soprano/Vocabulary/Xesam>
35 #include <kdatetime.h>
36 #include <kdirmodel.h>
37 #include <kfileitem.h>
38 #include <kiconloader.h>
42 #include <kmimetype.h>
43 #include <kstandarddirs.h>
46 #include <QSortFilterProxyModel>
51 const char* DolphinModel::m_others
= I18N_NOOP2("@title:group Name", "Others");
53 DolphinModel::DolphinModel(QObject
* parent
)
58 DolphinModel::~DolphinModel()
62 QVariant
DolphinModel::data(const QModelIndex
& index
, int role
) const
65 case KCategorizedSortFilterProxyModel::CategoryDisplayRole
:
66 return displayRoleData(index
);
67 case KCategorizedSortFilterProxyModel::CategorySortRole
:
68 return sortRoleData(index
);
70 return KDirModel::data(index
, role
);
74 int DolphinModel::columnCount(const QModelIndex
&parent
) const
76 return KDirModel::columnCount(parent
) + (ExtraColumnCount
- ColumnCount
);
79 quint32
DolphinModel::ratingForIndex(const QModelIndex
& index
)
84 const DolphinModel
* dolphinModel
= static_cast<const DolphinModel
*>(index
.model());
85 KFileItem item
= dolphinModel
->itemForIndex(index
);
87 const Nepomuk::Resource
resource(item
.url().url(), Soprano::Vocabulary::Xesam::File());
88 rating
= resource
.rating();
97 QString
DolphinModel::tagsForIndex(const QModelIndex
& index
)
102 const DolphinModel
* dolphinModel
= static_cast<const DolphinModel
*>(index
.model());
103 KFileItem item
= dolphinModel
->itemForIndex(index
);
104 if (!item
.isNull()) {
105 const Nepomuk::Resource
resource(item
.url().url(), Soprano::Vocabulary::Xesam::File());
106 const QList
<Nepomuk::Tag
> tags
= resource
.tags();
107 QStringList stringList
;
108 foreach (const Nepomuk::Tag
& tag
, tags
) {
109 stringList
.append(tag
.label());
113 foreach (const QString
& str
, stringList
) {
118 if (!tagsString
.isEmpty()) {
119 tagsString
.resize(tagsString
.size() - 2);
130 QVariant
DolphinModel::displayRoleData(const QModelIndex
& index
) const
134 if (!index
.isValid()) {
138 const KDirModel
*dirModel
= qobject_cast
<const KDirModel
*>(index
.model());
139 KFileItem item
= dirModel
->itemForIndex(index
);
141 switch (index
.column()) {
142 case KDirModel::Name
: {
143 // KDirModel checks columns to know to which role are
145 const QModelIndex nameIndex
= index
.model()->index(index
.row(), KDirModel::Name
, index
.parent());
146 if (!nameIndex
.isValid()) {
149 const QVariant data
= nameIndex
.model()->data(nameIndex
, Qt::DisplayRole
);
150 const QString name
= data
.toString();
151 if (!name
.isEmpty()) {
152 if (!item
.isHidden() && name
.at(0).isLetter())
153 retString
= name
.at(0).toUpper();
154 else if (item
.isHidden()) {
155 if (name
.at(0) == '.') {
156 if (name
.size() > 1 && name
.at(1).isLetter()) {
157 retString
= name
.at(1).toUpper();
159 retString
= i18nc("@title:group Name", m_others
);
162 retString
= name
.at(0).toUpper();
165 bool validCategory
= false;
167 const QString
str(name
.toUpper());
168 const QChar
* currA
= str
.unicode();
169 while (!currA
->isNull() && !validCategory
) {
170 if (currA
->isLetter()) {
171 validCategory
= true;
172 } else if (currA
->isDigit()) {
173 return i18nc("@title:group Name", m_others
);
179 if (!validCategory
) {
180 retString
= validCategory
? *currA
: i18nc("@title:group Name", m_others
);
189 case KDirModel::Size
: {
190 const KIO::filesize_t fileSize
= !item
.isNull() ? item
.size() : ~0U;
191 if (!item
.isNull() && item
.isDir()) {
192 retString
= i18nc("@title:group Size", "Folders");
193 } else if (fileSize
< 5242880) {
194 retString
= i18nc("@title:group Size", "Small");
195 } else if (fileSize
< 10485760) {
196 retString
= i18nc("@title:group Size", "Medium");
198 retString
= i18nc("@title:group Size", "Big");
203 case KDirModel::ModifiedTime
: {
204 KDateTime modifiedTime
= item
.time(KFileItem::ModificationTime
);
205 modifiedTime
= modifiedTime
.toLocalZone();
207 const QDate currentDate
= KDateTime::currentLocalDateTime().date();
208 const QDate modifiedDate
= modifiedTime
.date();
210 const int daysDistance
= modifiedDate
.daysTo(currentDate
);
212 int yearForCurrentWeek
= 0;
213 int currentWeek
= currentDate
.weekNumber(&yearForCurrentWeek
);
214 if (yearForCurrentWeek
== currentDate
.year() + 1) {
218 int yearForModifiedWeek
= 0;
219 int modifiedWeek
= modifiedDate
.weekNumber(&yearForModifiedWeek
);
220 if (yearForModifiedWeek
== modifiedDate
.year() + 1) {
224 if (currentDate
.year() == modifiedDate
.year() &&
225 currentDate
.month() == modifiedDate
.month()) {
226 switch (currentWeek
- modifiedWeek
) {
228 switch (daysDistance
) {
229 case 0: retString
= i18nc("@title:group Date", "Today"); break;
230 case 1: retString
= i18nc("@title:group Date", "Yesterday"); break;
231 default: retString
= modifiedTime
.toString(i18nc("@title:group The week day name: %A", "%A"));
235 retString
= i18nc("@title:group Date", "Last Week");
238 retString
= i18nc("@title:group Date", "Two Weeks Ago");
241 retString
= i18nc("@title:group Date", "Three Weeks Ago");
245 retString
= i18nc("@title:group Date", "Earlier this Month");
251 if (daysDistance
<= (currentDate
.day() + modifiedDate
.daysInMonth())) {
252 if (daysDistance
== 1) {
253 retString
= i18nc("@title:group Date: %B is full month name in current locale, and %Y is full year number", "Yesterday (%B, %Y)");
254 } else if (daysDistance
<= 7) {
255 retString
= modifiedTime
.toString(i18nc("@title:group The week day name: %A, %B is full month name in current locale, and %Y is full year number", "%A (%B, %Y)"));
256 } else if (daysDistance
<= 7 * 2) {
257 retString
= modifiedTime
.toString(i18nc("@title:group Date: %B is full month name in current locale, and %Y is full year number", "Last Week (%B, %Y)"));
258 } else if (daysDistance
<= 7 * 3) {
259 retString
= modifiedTime
.toString(i18nc("@title:group Date: %B is full month name in current locale, and %Y is full year number", "Two Weeks Ago (%B, %Y)"));
260 } else if (daysDistance
<= 7 * 4) {
261 retString
= modifiedTime
.toString(i18nc("@title:group Date: %B is full month name in current locale, and %Y is full year number", "Three Weeks Ago (%B, %Y)"));
263 retString
= modifiedTime
.toString(i18nc("@title:group Date: %B is full month name in current locale, and %Y is full year number", "Earlier on %B, %Y"));
266 retString
= modifiedTime
.toString(i18nc("@title:group The month and year: %B is full month name in current locale, and %Y is full year number", "%B, %Y"));
272 case KDirModel::Permissions
: {
277 QFileInfo
info(item
.url().pathOrUrl());
280 if (info
.permission(QFile::ReadUser
)) {
281 user
= i18nc("@item:intext Access permission, concatenated", "Read, ");
283 if (info
.permission(QFile::WriteUser
)) {
284 user
+= i18nc("@item:intext Access permission, concatenated", "Write, ");
286 if (info
.permission(QFile::ExeUser
)) {
287 user
+= i18nc("@item:intext Access permission, concatenated", "Execute, ");
289 user
= user
.isEmpty() ? i18nc("@item:intext Access permission, concatenated", "Forbidden") : user
.mid(0, user
.count() - 2);
292 if (info
.permission(QFile::ReadGroup
)) {
293 group
= i18nc("@item:intext Access permission, concatenated", "Read, ");
295 if (info
.permission(QFile::WriteGroup
)) {
296 group
+= i18nc("@item:intext Access permission, concatenated", "Write, ");
298 if (info
.permission(QFile::ExeGroup
)) {
299 group
+= i18nc("@item:intext Access permission, concatenated", "Execute, ");
301 group
= group
.isEmpty() ? i18nc("@item:intext Access permission, concatenated", "Forbidden") : group
.mid(0, group
.count() - 2);
303 // set permission string
304 if (info
.permission(QFile::ReadOther
)) {
305 others
= i18nc("@item:intext Access permission, concatenated", "Read, ");
307 if (info
.permission(QFile::WriteOther
)) {
308 others
+= i18nc("@item:intext Access permission, concatenated", "Write, ");
310 if (info
.permission(QFile::ExeOther
)) {
311 others
+= i18nc("@item:intext Access permission, concatenated", "Execute, ");
313 others
= others
.isEmpty() ? i18nc("@item:intext Access permission, concatenated", "Forbidden") : others
.mid(0, others
.count() - 2);
315 retString
= i18nc("@title:group Files and folders by permissions", "(User: %1) (Group: %2) (Others: %3)", user
, group
, others
);
319 case KDirModel::Owner
:
320 retString
= item
.user();
323 case KDirModel::Group
:
324 retString
= item
.group();
327 case KDirModel::Type
:
328 retString
= item
.mimeComment();
332 case DolphinModel::Rating
: {
333 const quint32 rating
= ratingForIndex(index
);
334 retString
= QString::number(rating
);
338 case DolphinModel::Tags
: {
339 retString
= tagsForIndex(index
);
340 if (retString
.isEmpty()) {
341 retString
= i18nc("@title:group Tags", "Not yet tagged");
351 QVariant
DolphinModel::sortRoleData(const QModelIndex
& index
) const
355 if (!index
.isValid()) {
359 const KDirModel
*dirModel
= qobject_cast
<const KDirModel
*>(index
.model());
360 KFileItem item
= dirModel
->itemForIndex(index
);
362 switch (index
.column()) {
363 case KDirModel::Name
: {
364 retVariant
= data(index
, KCategorizedSortFilterProxyModel::CategoryDisplayRole
);
365 if (retVariant
== i18nc("@title:group Name", m_others
)) {
366 // assure that the "Others" group is always the last categorization
367 retVariant
= QString(QChar(QChar::ReplacementCharacter
));
372 case KDirModel::Size
: {
373 const KIO::filesize_t fileSize
= !item
.isNull() ? item
.size() : ~0U;
376 } else if (fileSize
< 5242880) {
378 } else if (fileSize
< 10485760) {
386 case KDirModel::ModifiedTime
: {
387 KDateTime modifiedTime
= item
.time(KFileItem::ModificationTime
);
388 modifiedTime
= modifiedTime
.toLocalZone();
390 const QDate currentDate
= KDateTime::currentLocalDateTime().date();
391 const QDate modifiedDate
= modifiedTime
.date();
393 retVariant
= -modifiedDate
.daysTo(currentDate
);
397 case KDirModel::Permissions
: {
398 QFileInfo
info(item
.url().pathOrUrl());
400 retVariant
= -KDirSortFilterProxyModel::pointsForPermissions(info
);
404 case KDirModel::Owner
:
405 retVariant
= item
.user();
408 case KDirModel::Group
:
409 retVariant
= item
.group();
412 case KDirModel::Type
:
414 retVariant
= QString(); // when sorting we want folders to be placed first
416 retVariant
= item
.mimeComment();
420 case DolphinModel::Rating
: {
421 retVariant
= ratingForIndex(index
);
425 case DolphinModel::Tags
: {
426 retVariant
= tagsForIndex(index
).count();