┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/kitemviews/kfileitemmodel.cpp
diff options
context:
space:
mode:
authorPeter Penz <[email protected]>2011-10-22 01:31:02 +0200
committerPeter Penz <[email protected]>2011-10-22 01:33:26 +0200
commiteac436d0374d3be323c6ba36799d3cddc98301ea (patch)
treeca149d04153f6d169a70cb232fb0c420e90016e4 /src/kitemviews/kfileitemmodel.cpp
parentfd9cac1188130d3ef09530a902c95cf6190990a1 (diff)
Implement grouping for names
- Use a custom header for KFileItems - Cache the groups - Allow enabling/disabling grouping dynamically Currently there is a random crash in combination with the groupheader-recycler, this will be fixed during the next days.
Diffstat (limited to 'src/kitemviews/kfileitemmodel.cpp')
-rw-r--r--src/kitemviews/kfileitemmodel.cpp158
1 files changed, 145 insertions, 13 deletions
diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp
index 46de7c5aa..da2126aa3 100644
--- a/src/kitemviews/kfileitemmodel.cpp
+++ b/src/kitemviews/kfileitemmodel.cpp
@@ -45,6 +45,7 @@ KFileItemModel::KFileItemModel(KDirLister* dirLister, QObject* parent) :
m_maximumUpdateIntervalTimer(0),
m_pendingItemsToInsert(),
m_pendingEmitLoadingCompleted(false),
+ m_groups(),
m_rootExpansionLevel(-1),
m_expandedUrls(),
m_restoredExpandedUrls()
@@ -225,20 +226,34 @@ QString KFileItemModel::roleDescription(const QByteArray& role) const
QList<QPair<int, QVariant> > KFileItemModel::groups() const
{
- // TODO: dirty hack for initial testing of grouping functionality
- QPair<int, QVariant> group1(0, "Group 1");
- QPair<int, QVariant> group2(2, "Group 2");
- QPair<int, QVariant> group3(10, "Group 3");
- QPair<int, QVariant> group4(11, "Group 4");
- QPair<int, QVariant> group5(40, "Group 5");
+ if (!m_data.isEmpty() && m_groups.isEmpty()) {
+#ifdef KFILEITEMMODEL_DEBUG
+ QElapsedTimer timer;
+ timer.start();
+#endif
+ switch (roleIndex(sortRole())) {
+ case NameRole: m_groups = nameRoleGroups(); break;
+ 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 NoRole: break;
+ case IsDirRole: break;
+ case IsExpandedRole: break;
+ case ExpansionLevelRole: break;
+ default: Q_ASSERT(false); break;
+ }
- QList<QPair<int, QVariant> > groups;
- groups.append(group1);
- groups.append(group2);
- groups.append(group3);
- groups.append(group4);
- groups.append(group5);
- return groups;
+#ifdef KFILEITEMMODEL_DEBUG
+ kDebug() << "[TIME] Calculating groups for" << count() << "items:" << timer.elapsed();
+#endif
+ }
+
+ return m_groups;
}
KFileItem KFileItemModel::fileItem(int index) const
@@ -413,6 +428,7 @@ void KFileItemModel::restoreExpandedUrls(const QSet<KUrl>& urls)
void KFileItemModel::onGroupedSortingChanged(bool current)
{
Q_UNUSED(current);
+ m_groups.clear();
}
void KFileItemModel::onSortRoleChanged(const QByteArray& current, const QByteArray& previous)
@@ -500,6 +516,8 @@ void KFileItemModel::slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >&
kDebug() << "Refreshing" << items.count() << "items";
#endif
+ m_groups.clear();
+
// Get the indexes of all items that have been refreshed
QList<int> indexes;
indexes.reserve(items.count());
@@ -554,6 +572,8 @@ void KFileItemModel::slotClear()
kDebug() << "Clearing all items";
#endif
+ m_groups.clear();
+
m_minimumUpdateIntervalTimer->stop();
m_maximumUpdateIntervalTimer->stop();
m_pendingItemsToInsert.clear();
@@ -601,6 +621,8 @@ void KFileItemModel::insertItems(const KFileItemList& items)
kDebug() << "Inserting" << items.count() << "items";
#endif
+ m_groups.clear();
+
KFileItemList sortedItems = items;
sort(sortedItems.begin(), sortedItems.end());
@@ -671,6 +693,8 @@ void KFileItemModel::removeItems(const KFileItemList& items)
kDebug() << "Removing " << items.count() << "items";
#endif
+ m_groups.clear();
+
KFileItemList sortedItems = items;
sort(sortedItems.begin(), sortedItems.end());
@@ -738,6 +762,8 @@ 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;
@@ -1131,4 +1157,110 @@ bool KFileItemModel::useMaximumUpdateInterval() const
return dirLister && !dirLister->url().isLocalFile();
}
+QList<QPair<int, QVariant> > KFileItemModel::nameRoleGroups() const
+{
+ Q_ASSERT(!m_data.isEmpty());
+
+ const int maxIndex = count() - 1;
+ QList<QPair<int, QVariant> > groups;
+
+ QString groupValue;
+ QChar firstChar;
+ bool isLetter = false;
+ for (int i = 0; i <= maxIndex; ++i) {
+ const QString name = m_data.at(i).value("name").toString();
+
+ // Use the first character of the name as group indication
+ QChar newFirstChar = name.at(0).toUpper();
+ if (newFirstChar == QLatin1Char('~') && name.length() > 1) {
+ newFirstChar = name.at(1);
+ }
+
+ if (firstChar != newFirstChar) {
+ QString newGroupValue;
+ if (newFirstChar >= QLatin1Char('A') && newFirstChar <= QLatin1Char('Z')) {
+ // Apply group 'A' - 'Z'
+ newGroupValue = newFirstChar;
+ isLetter = true;
+ } else if (newFirstChar >= QLatin1Char('0') && newFirstChar <= QLatin1Char('9')) {
+ // Apply group 'Numerics' for any name that starts with a digit
+ newGroupValue = i18nc("@title:group", "Numerics");
+ isLetter = false;
+ } else {
+ if (isLetter) {
+ // If the current group is 'A' - 'Z' check whether a locale character
+ // fits into the existing group.
+ const QChar prevChar(firstChar.unicode() - ushort(1));
+ const QChar nextChar(firstChar.unicode() + ushort(1));
+ const QString currChar(newFirstChar);
+ const bool partOfCurrentGroup = currChar.localeAwareCompare(prevChar) > 0 &&
+ currChar.localeAwareCompare(nextChar) < 0;
+ if (partOfCurrentGroup) {
+ continue;
+ }
+ }
+ newGroupValue = i18nc("@title:group", "Others");
+ isLetter = false;
+ }
+
+ if (newGroupValue != groupValue) {
+ groupValue = newGroupValue;
+ groups.append(QPair<int, QVariant>(i, newGroupValue));
+ }
+
+ firstChar = newFirstChar;
+ }
+ }
+ return groups;
+}
+
+QList<QPair<int, QVariant> > KFileItemModel::sizeRoleGroups() const
+{
+ Q_ASSERT(!m_data.isEmpty());
+
+ return QList<QPair<int, QVariant> >();
+}
+
+QList<QPair<int, QVariant> > KFileItemModel::dateRoleGroups() const
+{
+ Q_ASSERT(!m_data.isEmpty());
+ return QList<QPair<int, QVariant> >();
+}
+
+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> >();
+}
+
+QList<QPair<int, QVariant> > KFileItemModel::groupRoleGroups() const
+{
+ Q_ASSERT(!m_data.isEmpty());
+ return QList<QPair<int, QVariant> >();
+}
+
+QList<QPair<int, QVariant> > KFileItemModel::typeRoleGroups() const
+{
+ Q_ASSERT(!m_data.isEmpty());
+ return QList<QPair<int, QVariant> >();
+}
+
+QList<QPair<int, QVariant> > KFileItemModel::destinationRoleGroups() const
+{
+ Q_ASSERT(!m_data.isEmpty());
+ return QList<QPair<int, QVariant> >();
+}
+
+QList<QPair<int, QVariant> > KFileItemModel::pathRoleGroups() const
+{
+ Q_ASSERT(!m_data.isEmpty());
+ return QList<QPair<int, QVariant> >();
+}
+
#include "kfileitemmodel.moc"