]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphinmodel.cpp
More changes will follow to fix logic. This makes the stuff compile.
[dolphin.git] / src / dolphinmodel.cpp
1 /**
2 * This file is part of the KDE project
3 * Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
4 *
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.
9 *
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.
14 *
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.
19 */
20
21 #include "dolphinmodel.h"
22
23 #include "dolphinsortfilterproxymodel.h"
24
25 #include "kcategorizedview.h"
26
27 #include <config-nepomuk.h>
28 #ifdef HAVE_NEPOMUK
29 #include <nepomuk/global.h>
30 #include <nepomuk/resource.h>
31 #include <nepomuk/tag.h>
32 #endif
33
34 #include <kdatetime.h>
35 #include <kdirmodel.h>
36 #include <kfileitem.h>
37 #include <kiconloader.h>
38 #include <klocale.h>
39 #include <kurl.h>
40 #include <kuser.h>
41 #include <kmimetype.h>
42 #include <kstandarddirs.h>
43
44 #include <QList>
45 #include <QSortFilterProxyModel>
46 #include <QPainter>
47 #include <QDir>
48 #include <QFileInfo>
49
50 DolphinModel::DolphinModel(QObject *parent)
51 : KDirModel(parent)
52 {
53 }
54
55 DolphinModel::~DolphinModel()
56 {
57 }
58
59 QVariant DolphinModel::data(const QModelIndex &index, int role) const
60 {
61 if (role == KCategorizedSortFilterProxyModel::CategoryDisplayRole)
62 {
63 QString retString;
64
65 if (!index.isValid())
66 {
67 return retString;
68 }
69
70 const KDirModel *dirModel = qobject_cast<const KDirModel*>(index.model());
71 KFileItem item = dirModel->itemForIndex(index);
72
73 switch (index.column())
74 {
75 case KDirModel::Name:
76 {
77 // KDirModel checks columns to know to which role are
78 // we talking about
79 QModelIndex theIndex = index.model()->index(index.row(),
80 KDirModel::Name,
81 index.parent());
82
83 if (!theIndex.isValid()) {
84 return retString;
85 }
86
87 QVariant data = theIndex.model()->data(theIndex, Qt::DisplayRole);
88 if (data.toString().size())
89 {
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);
102 else
103 {
104 bool validCategory = false;
105
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");
113 else
114 ++currA;
115 }
116
117 if (!validCategory)
118 retString = i18nc("@title:group Name", "Others");
119 else
120 retString = *currA;
121 }
122 }
123 break;
124 }
125
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");
134 } else {
135 retString = i18nc("@title:group Size", "Big");
136 }
137 break;
138 }
139
140 case KDirModel::ModifiedTime:
141 {
142 KDateTime modifiedTime;
143 modifiedTime.setTime_t(item.time(KIO::UDSEntry::UDS_MODIFICATION_TIME));
144 modifiedTime = modifiedTime.toLocalZone();
145
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"));
147 break;
148 }
149
150 case KDirModel::Permissions:
151 {
152 QString user;
153 QString group;
154 QString others;
155
156 QFileInfo info(item.url().pathOrUrl());
157
158 if (info.permission(QFile::ReadUser))
159 user = i18n("Read, ");
160
161 if (info.permission(QFile::WriteUser))
162 user += i18n("Write, ");
163
164 if (info.permission(QFile::ExeUser))
165 user += i18n("Execute, ");
166
167 if (user.isEmpty())
168 user = i18n("Forbidden");
169 else
170 user = user.mid(0, user.count() - 2);
171
172 if (info.permission(QFile::ReadGroup))
173 group = i18n("Read, ");
174
175 if (info.permission(QFile::WriteGroup))
176 group += i18n("Write, ");
177
178 if (info.permission(QFile::ExeGroup))
179 group += i18n("Execute, ");
180
181 if (group.isEmpty())
182 group = i18n("Forbidden");
183 else
184 group = group.mid(0, group.count() - 2);
185
186 if (info.permission(QFile::ReadOther))
187 others = i18n("Read, ");
188
189 if (info.permission(QFile::WriteOther))
190 others += i18n("Write, ");
191
192 if (info.permission(QFile::ExeOther))
193 others += i18n("Execute, ");
194
195 if (others.isEmpty())
196 others = i18n("Forbidden");
197 else
198 others = others.mid(0, others.count() - 2);
199
200 retString = i18nc("This shows files and folders permissions: user, group and others", "(User: %1) (Group: %2) (Others: %3)", user, group, others);
201 break;
202 }
203
204 case KDirModel::Owner:
205 retString = item.user();
206 break;
207
208 case KDirModel::Group:
209 retString = item.group();
210 break;
211
212 case KDirModel::Type:
213 retString = item.mimeComment();
214 break;
215
216 #ifdef HAVE_NEPOMUK
217 case DolphinModel::Rating: {
218 const quint32 rating = ratingForIndex(index);
219
220 retString = QString::number(rating);
221 break;
222 }
223
224 case DolphinModel::Tags: {
225 retString = tagsForIndex(index);
226
227 if (retString.isEmpty())
228 retString = i18nc("@title:group Tags", "Not yet tagged");
229
230 break;
231 }
232 #endif
233 }
234
235 return retString;
236 }
237 else if (role == KCategorizedSortFilterProxyModel::CategorySortRole)
238 {
239 #if 0
240 QVariant retVariant;
241
242 if (!index.isValid())
243 {
244 return retVariant;
245 }
246
247 const KDirModel *dirModel = qobject_cast<const KDirModel*>(index.model());
248 KFileItem item = dirModel->itemForIndex(index);
249
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()) {
259 break;
260 } else
261 ++currA;
262 }
263
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()) {
271 break;
272 } else
273 ++currB;
274 }
275
276 if (!rightFileNameStartsByLetter)
277 return -1;
278
279 if (!leftFileNameStartsByLetter && rightFileNameStartsByLetter)
280 return 1;
281
282 return naturalCompare(*currA, *currB);
283 }
284
285 case KDirModel::Size: {
286 // If we are sorting by size, show folders first. We will sort them
287 // correctly later.
288 if (leftFileItem.isDir() && !rightFileItem.isDir()) {
289 return -1;
290 }
291
292 if (!leftFileItem.isDir() && rightFileItem.isDir()) {
293 return 1;
294 }
295
296 if (leftFileItem.isDir() && rightFileItem.isDir()) {
297 return 0;
298 }
299
300 const int leftFileSize = !leftFileItem.isNull() ? leftFileItem.size() : -1;
301 const int rightFileSize = !rightFileItem.isNull() ? rightFileItem.size() : -1;
302 int leftGroup;
303 int rightGroup;
304
305 if (leftFileSize < 5242880) {
306 leftGroup = 0;
307 } else if (leftFileSize < 10485760) {
308 leftGroup = 1;
309 } else {
310 leftGroup = 2;
311 }
312
313 if (rightFileSize < 5242880) {
314 rightGroup = 0;
315 } else if (rightFileSize < 10485760) {
316 rightGroup = 1;
317 } else {
318 rightGroup = 2;
319 }
320
321 return leftGroup - rightGroup;
322 }
323
324 case KDirModel::ModifiedTime: {
325 KDateTime leftTime = leftFileItem.time(KFileItem::ModificationTime);
326 KDateTime rightTime = rightFileItem.time(KFileItem::ModificationTime);
327
328 if ((leftTime.date().year() == rightTime.date().year()) &&
329 (leftTime.date().month() == rightTime.date().month())) {
330 return 0;
331 }
332
333 if (leftTime > rightTime) {
334 return 1;
335 }
336
337 return -1;
338 }
339
340 case KDirModel::Permissions: {
341 QFileInfo leftFileInfo(leftFileItem.url().pathOrUrl());
342 QFileInfo rightFileInfo(rightFileItem.url().pathOrUrl());
343
344 int leftPermissionsPoints = pointsForPermissions(leftFileInfo);
345 int rightPermissionsPoints = pointsForPermissions(rightFileInfo);
346
347 return leftPermissionsPoints - rightPermissionsPoints;
348 }
349
350 case KDirModel::Owner: {
351 return naturalCompare(leftFileItem.user().toLower(),
352 rightFileItem.user().toLower());
353 }
354
355 case KDirModel::Group: {
356 return naturalCompare(leftFileItem.group().toLower(),
357 rightFileItem.group().toLower());
358 }
359
360 case KDirModel::Type: {
361 // If we are sorting by size, show folders first. We will sort them
362 // correctly later.
363 if (leftFileItem.isDir() && !rightFileItem.isDir()) {
364 return -1;
365 } else if (!leftFileItem.isDir() && rightFileItem.isDir()) {
366 return 1;
367 }
368
369 return naturalCompare(leftFileItem.mimeComment().toLower(),
370 rightFileItem.mimeComment().toLower());
371 }
372
373 #ifdef HAVE_NEPOMUK
374 case DolphinView::SortByRating: {
375 const qint32 leftRating = DolphinModel::ratingForIndex(left);
376 const qint32 rightRating = DolphinModel::ratingForIndex(right);
377 return leftRating - rightRating;
378 }
379
380 case DolphinView::SortByTags: {
381 const QString leftTags = DolphinModel::tagsForIndex(left);
382 const QString rightTags = DolphinModel::tagsForIndex(right);
383
384 if (leftTags.isEmpty() && !rightTags.isEmpty())
385 return 1;
386 else if (!leftTags.isEmpty() && rightTags.isEmpty())
387 return -1;
388
389 return naturalCompare(DolphinModel::tagsForIndex(left), DolphinModel::tagsForIndex(right)) < 0;
390 }
391 #endif
392
393 default:
394 break;
395
396 }
397 #endif
398 QString retString;
399
400 if (!index.isValid())
401 {
402 return retString;
403 }
404
405 const KDirModel *dirModel = qobject_cast<const KDirModel*>(index.model());
406 KFileItem item = dirModel->itemForIndex(index);
407
408 switch (index.column())
409 {
410 case KDirModel::Name:
411 {
412 // KDirModel checks columns to know to which role are
413 // we talking about
414 QModelIndex theIndex = index.model()->index(index.row(),
415 KDirModel::Name,
416 index.parent());
417
418 if (!theIndex.isValid()) {
419 return retString;
420 }
421
422 QVariant data = theIndex.model()->data(theIndex, Qt::DisplayRole);
423 if (data.toString().size())
424 {
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);
437 else
438 {
439 bool validCategory = false;
440
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");
448 else
449 ++currA;
450 }
451
452 if (!validCategory)
453 retString = i18nc("@title:group Name", "Others");
454 else
455 retString = *currA;
456 }
457 }
458 break;
459 }
460
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");
469 } else {
470 retString = i18nc("@title:group Size", "Big");
471 }
472 break;
473 }
474
475 case KDirModel::ModifiedTime:
476 {
477 KDateTime modifiedTime;
478 modifiedTime.setTime_t(item.time(KIO::UDSEntry::UDS_MODIFICATION_TIME));
479 modifiedTime = modifiedTime.toLocalZone();
480
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"));
482 break;
483 }
484
485 case KDirModel::Permissions:
486 {
487 QString user;
488 QString group;
489 QString others;
490
491 QFileInfo info(item.url().pathOrUrl());
492
493 if (info.permission(QFile::ReadUser))
494 user = i18n("Read, ");
495
496 if (info.permission(QFile::WriteUser))
497 user += i18n("Write, ");
498
499 if (info.permission(QFile::ExeUser))
500 user += i18n("Execute, ");
501
502 if (user.isEmpty())
503 user = i18n("Forbidden");
504 else
505 user = user.mid(0, user.count() - 2);
506
507 if (info.permission(QFile::ReadGroup))
508 group = i18n("Read, ");
509
510 if (info.permission(QFile::WriteGroup))
511 group += i18n("Write, ");
512
513 if (info.permission(QFile::ExeGroup))
514 group += i18n("Execute, ");
515
516 if (group.isEmpty())
517 group = i18n("Forbidden");
518 else
519 group = group.mid(0, group.count() - 2);
520
521 if (info.permission(QFile::ReadOther))
522 others = i18n("Read, ");
523
524 if (info.permission(QFile::WriteOther))
525 others += i18n("Write, ");
526
527 if (info.permission(QFile::ExeOther))
528 others += i18n("Execute, ");
529
530 if (others.isEmpty())
531 others = i18n("Forbidden");
532 else
533 others = others.mid(0, others.count() - 2);
534
535 retString = i18nc("This shows files and folders permissions: user, group and others", "(User: %1) (Group: %2) (Others: %3)", user, group, others);
536 break;
537 }
538
539 case KDirModel::Owner:
540 retString = item.user();
541 break;
542
543 case KDirModel::Group:
544 retString = item.group();
545 break;
546
547 case KDirModel::Type:
548 retString = item.mimeComment();
549 break;
550
551 #ifdef HAVE_NEPOMUK
552 case DolphinModel::Rating: {
553 const quint32 rating = ratingForIndex(index);
554
555 retString = QString::number(rating);
556 break;
557 }
558
559 case DolphinModel::Tags: {
560 retString = tagsForIndex(index);
561
562 if (retString.isEmpty())
563 retString = i18nc("@title:group Tags", "Not yet tagged");
564
565 break;
566 }
567 #endif
568 }
569
570 return retString;
571 }
572
573 return KDirModel::data(index, role);
574 }
575
576 int DolphinModel::columnCount(const QModelIndex &parent) const
577 {
578 return KDirModel::columnCount(parent) + (ExtraColumnCount - ColumnCount);
579 }
580
581 quint32 DolphinModel::ratingForIndex(const QModelIndex& index)
582 {
583 #ifdef HAVE_NEPOMUK
584 quint32 rating = 0;
585
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();
591 }
592 return rating;
593 #else
594 Q_UNUSED(index);
595 return 0;
596 #endif
597 }
598
599 QString DolphinModel::tagsForIndex(const QModelIndex& index)
600 {
601 #ifdef HAVE_NEPOMUK
602 QString tagsString;
603
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());
612 }
613 stringList.sort();
614
615 foreach (const QString& str, stringList) {
616 tagsString += str;
617 tagsString += ", ";
618 }
619
620 if (!tagsString.isEmpty()) {
621 tagsString.resize(tagsString.size() - 2);
622 }
623 }
624
625 return tagsString;
626 #else
627 Q_UNUSED(index);
628 return QString();
629 #endif
630 }