]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Implement grouping for all roles
authorPeter Penz <peter.penz19@gmail.com>
Sat, 29 Oct 2011 16:05:37 +0000 (18:05 +0200)
committerPeter Penz <peter.penz19@gmail.com>
Sat, 29 Oct 2011 16:06:03 +0000 (18:06 +0200)
src/kitemviews/kfileitemmodel.cpp
src/kitemviews/kfileitemmodel.h
src/kitemviews/kitemlistview.cpp

index 27265487214efdb4eb98316c9d235f3bd447e624..083b6421c077e18ef349dccd971b561a7f9c12e1 100644 (file)
@@ -236,11 +236,11 @@ QList<QPair<int, QVariant> > KFileItemModel::groups() const
         case SizeRole:           m_groups = sizeRoleGroups(); break;
         case DateRole:           m_groups = dateRoleGroups(); break;
         case PermissionsRole:    m_groups = permissionRoleGroups(); break;
-        case OwnerRole:          m_groups = ownerRoleGroups(); break;
-        case GroupRole:          m_groups = groupRoleGroups(); break;
-        case TypeRole:           m_groups = typeRoleGroups(); break;
-        case DestinationRole:    m_groups = destinationRoleGroups(); break;
-        case PathRole:           m_groups = pathRoleGroups(); break;
+        case OwnerRole:          m_groups = genericStringRoleGroups("owner"); break;
+        case GroupRole:          m_groups = genericStringRoleGroups("group"); break;
+        case TypeRole:           m_groups = genericStringRoleGroups("type"); break;
+        case DestinationRole:    m_groups = genericStringRoleGroups("destination"); break;
+        case PathRole:           m_groups = genericStringRoleGroups("path"); break;
         case NoRole:             break;
         case IsDirRole:          break;
         case IsExpandedRole:     break;
@@ -762,12 +762,11 @@ void KFileItemModel::resortAllItems()
         return;
     }
 
-    m_groups.clear();
-
     const KFileItemList oldSortedItems = m_sortedItems;
     const QHash<KUrl, int> oldItems = m_items;
     const QList<QHash<QByteArray, QVariant> > oldData = m_data;
 
+    m_groups.clear();
     m_items.clear();
     m_data.clear();
 
@@ -1168,10 +1167,7 @@ QList<QPair<int, QVariant> > KFileItemModel::nameRoleGroups() const
     QChar firstChar;
     bool isLetter = false;
     for (int i = 0; i <= maxIndex; ++i) {
-        if (m_requestRole[ExpansionLevelRole] && m_data.at(i).value("expansionLevel").toInt() > 0) {
-            // KItemListView would be capable to show sub-groups in groups but
-            // in typical usecases this results in visual clutter, hence we
-            // just ignore sub-groups.
+        if (isChildItem(i)) {
             continue;
         }
 
@@ -1227,49 +1223,227 @@ QList<QPair<int, QVariant> > KFileItemModel::sizeRoleGroups() const
 {
     Q_ASSERT(!m_data.isEmpty());
 
-    return QList<QPair<int, QVariant> >();
+    const int maxIndex = count() - 1;
+    QList<QPair<int, QVariant> > groups;
+
+    QString groupValue;
+    for (int i = 0; i <= maxIndex; ++i) {
+        if (isChildItem(i)) {
+            continue;
+        }
+
+        const KFileItem& item = m_sortedItems.at(i);
+        const KIO::filesize_t fileSize = !item.isNull() ? item.size() : ~0U;
+        QString newGroupValue;
+        if (!item.isNull() && item.isDir()) {
+            newGroupValue = i18nc("@title:group Size", "Folders");
+        } else if (fileSize < 5 * 1024 * 1024) {
+            newGroupValue = i18nc("@title:group Size", "Small");
+        } else if (fileSize < 10 * 1024 * 1024) {
+            newGroupValue = i18nc("@title:group Size", "Medium");
+        } else {
+            newGroupValue = i18nc("@title:group Size", "Big");
+        }
+
+        if (newGroupValue != groupValue) {
+            groupValue = newGroupValue;
+            groups.append(QPair<int, QVariant>(i, newGroupValue));
+        }
+    }
+
+    return groups;
 }
 
 QList<QPair<int, QVariant> > KFileItemModel::dateRoleGroups() const
 {
     Q_ASSERT(!m_data.isEmpty());
-    return QList<QPair<int, QVariant> >();
+
+    const int maxIndex = count() - 1;
+    QList<QPair<int, QVariant> > groups;
+
+    const QDate currentDate = KDateTime::currentLocalDateTime().date();
+
+    int yearForCurrentWeek = 0;
+    int currentWeek = currentDate.weekNumber(&yearForCurrentWeek);
+    if (yearForCurrentWeek == currentDate.year() + 1) {
+        currentWeek = 53;
+    }
+
+    QDate previousModifiedDate;
+    QString groupValue;
+    for (int i = 0; i <= maxIndex; ++i) {
+        if (isChildItem(i)) {
+            continue;
+        }
+
+        const KDateTime modifiedTime = m_sortedItems.at(i).time(KFileItem::ModificationTime);
+        const QDate modifiedDate = modifiedTime.date();
+        if (modifiedDate == previousModifiedDate) {
+            // The current item is in the same group as the previous item
+            continue;
+        }
+        previousModifiedDate = modifiedDate;
+
+        const int daysDistance = modifiedDate.daysTo(currentDate);
+
+        int yearForModifiedWeek = 0;
+        int modifiedWeek = modifiedDate.weekNumber(&yearForModifiedWeek);
+        if (yearForModifiedWeek == modifiedDate.year() + 1) {
+            modifiedWeek = 53;
+        }
+
+        QString newGroupValue;
+        if (currentDate.year() == modifiedDate.year() && currentDate.month() == modifiedDate.month()) {
+            if (modifiedWeek > currentWeek) {
+                // Usecase: modified date = 2010-01-01, current date = 2010-01-22
+                //          modified week = 53,         current week = 3
+                modifiedWeek = 0;
+            }
+            switch (currentWeek - modifiedWeek) {
+            case 0:
+                switch (daysDistance) {
+                case 0:  newGroupValue = i18nc("@title:group Date", "Today"); break;
+                case 1:  newGroupValue = i18nc("@title:group Date", "Yesterday"); break;
+                default: newGroupValue = modifiedTime.toString(i18nc("@title:group The week day name: %A", "%A"));
+                }
+                break;
+            case 1:
+                newGroupValue = i18nc("@title:group Date", "Last Week");
+                break;
+            case 2:
+                newGroupValue = i18nc("@title:group Date", "Two Weeks Ago");
+                break;
+            case 3:
+                newGroupValue = i18nc("@title:group Date", "Three Weeks Ago");
+                break;
+            case 4:
+            case 5:
+                newGroupValue = i18nc("@title:group Date", "Earlier this Month");
+                break;
+            default:
+                Q_ASSERT(false);
+            }
+        } else {
+            const QDate lastMonthDate = currentDate.addMonths(-1);
+            if  (lastMonthDate.year() == modifiedDate.year() && lastMonthDate.month() == modifiedDate.month()) {
+                if (daysDistance == 1) {
+                    newGroupValue = modifiedTime.toString(i18nc("@title:group Date: %B is full month name in current locale, and %Y is full year number", "Yesterday (%B, %Y)"));
+                } else if (daysDistance <= 7) {
+                    newGroupValue = 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)"));
+                } else if (daysDistance <= 7 * 2) {
+                    newGroupValue = modifiedTime.toString(i18nc("@title:group Date: %B is full month name in current locale, and %Y is full year number", "Last Week (%B, %Y)"));
+                } else if (daysDistance <= 7 * 3) {
+                    newGroupValue = 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)"));
+                } else if (daysDistance <= 7 * 4) {
+                    newGroupValue = 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)"));
+                } else {
+                    newGroupValue = modifiedTime.toString(i18nc("@title:group Date: %B is full month name in current locale, and %Y is full year number", "Earlier on %B, %Y"));
+                }
+            } else {
+                newGroupValue = 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"));
+            }
+        }
+
+        if (newGroupValue != groupValue) {
+            groupValue = newGroupValue;
+            groups.append(QPair<int, QVariant>(i, newGroupValue));
+        }
+    }
+
+    return groups;
 }
 
 QList<QPair<int, QVariant> > KFileItemModel::permissionRoleGroups() const
 {
     Q_ASSERT(!m_data.isEmpty());
-    return QList<QPair<int, QVariant> >();
-}
 
-QList<QPair<int, QVariant> > KFileItemModel::ownerRoleGroups() const
-{
-    Q_ASSERT(!m_data.isEmpty());
-    return QList<QPair<int, QVariant> >();
-}
+    const int maxIndex = count() - 1;
+    QList<QPair<int, QVariant> > groups;
 
-QList<QPair<int, QVariant> > KFileItemModel::groupRoleGroups() const
-{
-    Q_ASSERT(!m_data.isEmpty());
-    return QList<QPair<int, QVariant> >();
-}
+    QString permissionsString;
+    QString groupValue;
+    for (int i = 0; i <= maxIndex; ++i) {
+        if (isChildItem(i)) {
+            continue;
+        }
 
-QList<QPair<int, QVariant> > KFileItemModel::typeRoleGroups() const
-{
-    Q_ASSERT(!m_data.isEmpty());
-    return QList<QPair<int, QVariant> >();
-}
+        const QString newPermissionsString = m_data.at(i).value("permissions").toString();
+        if (newPermissionsString == permissionsString) {
+            continue;
+        }
+        permissionsString = newPermissionsString;
 
-QList<QPair<int, QVariant> > KFileItemModel::destinationRoleGroups() const
-{
-    Q_ASSERT(!m_data.isEmpty());
-    return QList<QPair<int, QVariant> >();
+        const QFileInfo info(m_sortedItems.at(i).url().pathOrUrl());
+
+        // Set user string
+        QString user;
+        if (info.permission(QFile::ReadUser)) {
+            user = i18nc("@item:intext Access permission, concatenated", "Read, ");
+        }
+        if (info.permission(QFile::WriteUser)) {
+            user += i18nc("@item:intext Access permission, concatenated", "Write, ");
+        }
+        if (info.permission(QFile::ExeUser)) {
+            user += i18nc("@item:intext Access permission, concatenated", "Execute, ");
+        }
+        user = user.isEmpty() ? i18nc("@item:intext Access permission, concatenated", "Forbidden") : user.mid(0, user.count() - 2);
+
+        // Set group string
+        QString group;
+        if (info.permission(QFile::ReadGroup)) {
+            group = i18nc("@item:intext Access permission, concatenated", "Read, ");
+        }
+        if (info.permission(QFile::WriteGroup)) {
+            group += i18nc("@item:intext Access permission, concatenated", "Write, ");
+        }
+        if (info.permission(QFile::ExeGroup)) {
+            group += i18nc("@item:intext Access permission, concatenated", "Execute, ");
+        }
+        group = group.isEmpty() ? i18nc("@item:intext Access permission, concatenated", "Forbidden") : group.mid(0, group.count() - 2);
+
+        // Set others string
+        QString others;
+        if (info.permission(QFile::ReadOther)) {
+            others = i18nc("@item:intext Access permission, concatenated", "Read, ");
+        }
+        if (info.permission(QFile::WriteOther)) {
+            others += i18nc("@item:intext Access permission, concatenated", "Write, ");
+        }
+        if (info.permission(QFile::ExeOther)) {
+            others += i18nc("@item:intext Access permission, concatenated", "Execute, ");
+        }
+        others = others.isEmpty() ? i18nc("@item:intext Access permission, concatenated", "Forbidden") : others.mid(0, others.count() - 2);
+
+        const QString newGroupValue = i18nc("@title:group Files and folders by permissions", "User: %1 | Group: %2 | Others: %3", user, group, others);
+        if (newGroupValue != groupValue) {
+            groupValue = newGroupValue;
+            groups.append(QPair<int, QVariant>(i, newGroupValue));
+        }
+    }
+
+    return groups;
 }
 
-QList<QPair<int, QVariant> > KFileItemModel::pathRoleGroups() const
+QList<QPair<int, QVariant> > KFileItemModel::genericStringRoleGroups(const QByteArray& role) const
 {
     Q_ASSERT(!m_data.isEmpty());
-    return QList<QPair<int, QVariant> >();
+
+    const int maxIndex = count() - 1;
+    QList<QPair<int, QVariant> > groups;
+
+    QString groupValue;
+    for (int i = 0; i <= maxIndex; ++i) {
+        if (isChildItem(i)) {
+            continue;
+        }
+        const QString newGroupValue = m_data.at(i).value(role).toString();
+        if (newGroupValue != groupValue) {
+            groupValue = newGroupValue;
+            groups.append(QPair<int, QVariant>(i, newGroupValue));
+        }
+    }
+
+    return groups;
 }
 
 #include "kfileitemmodel.moc"
index 8ccff95e8a4bdf833fd8299de314cd18ee70645b..f2e783f4682adf00e7137b6d7b9e1975a22191bd 100644 (file)
@@ -198,11 +198,17 @@ private:
     QList<QPair<int, QVariant> > sizeRoleGroups() const;
     QList<QPair<int, QVariant> > dateRoleGroups() const;
     QList<QPair<int, QVariant> > permissionRoleGroups() const;
-    QList<QPair<int, QVariant> > ownerRoleGroups() const;
-    QList<QPair<int, QVariant> > groupRoleGroups() const;
-    QList<QPair<int, QVariant> > typeRoleGroups() const;
-    QList<QPair<int, QVariant> > destinationRoleGroups() const;
-    QList<QPair<int, QVariant> > pathRoleGroups() const;
+    QList<QPair<int, QVariant> > genericStringRoleGroups(const QByteArray& role) const;
+
+    /**
+     * Helper method for all xxxRoleGroups() methods to check whether the
+     * item with the given index is a child-item. A child-item is defined
+     * as item having an expansion-level > 0. All xxxRoleGroups() methods
+     * should skip the grouping if the item is a child-item (although
+     * KItemListView would be capable to show sub-groups in groups this
+     * results in visual clutter for most usecases).
+     */
+    bool isChildItem(int index) const;
 
 private:
     QWeakPointer<KDirLister> m_dirLister;
@@ -241,6 +247,11 @@ private:
     friend class KFileItemModelTest; // For unit testing
 };
 
+inline bool KFileItemModel::isChildItem(int index) const
+{
+    return m_requestRole[ExpansionLevelRole] && m_data.at(index).value("expansionLevel").toInt() > 0;
+}
+
 #endif
 
 
index 478bf62603de3b0b481815e33b7ad6a93d023191..eff48cf0907d4c234b496725d855438119b2cd6a 100644 (file)
@@ -1466,6 +1466,11 @@ void KItemListView::updateGroupHeaderForWidget(KItemListWidget* widget)
         return;
     }
 
+    const QList<QPair<int, QVariant> > groups = model()->groups();
+    if (groups.isEmpty()) {
+        return;
+    }
+
     KItemListGroupHeader* header = m_visibleGroups.value(widget);
     if (!header) {
         header = m_groupHeaderCreator->create(this);
@@ -1476,7 +1481,6 @@ void KItemListView::updateGroupHeaderForWidget(KItemListWidget* widget)
 
     // Determine the shown data for the header by doing a binary
     // search in the groups-list
-    const QList<QPair<int, QVariant> > groups = model()->groups();
     int min = 0;
     int max = groups.count() - 1;
     int mid = 0;