m_items.clear();
m_items.reserve(itemCount);
- const QList<QPair<int, QVariant>> oldGroups = m_groups;
-
- if (groupedSorting() && m_groupRole) {
- // Hacky way to implement grouped sorting without rewriting more code.
- // 1. Sort all items by grouping criteria. "Folders first" priority to be ignored.
- // 2. Generate groups, which will stay usable after in-group sorting.
- // 3. Perform sorts by the original sorting criteria inside groups.
-
- RoleType originalSortRole = m_sortRole;
- Qt::SortOrder originalSortOrder = sortOrder();
- bool originalSortDirsFirst = m_sortDirsFirst;
- m_sortRole = m_groupRole;
- setSortOrder(groupOrder(), false);
- m_sortDirsFirst = false;
-
- sort(m_itemData.begin(), m_itemData.end());
- m_groups.clear();
- groups();
-
- m_sortRole = originalSortRole;
- setSortOrder(originalSortOrder, false);
- m_sortDirsFirst = originalSortDirsFirst;
-
- int lastIndex = 0, newIndex = 0;
- for (int i = 0; i < m_groups.count() - 1; ++i) {
- qCritical() << m_groups[i];
- fflush(stderr);
- newIndex = m_groups[i + 1].first;
- sort(m_itemData.begin() + lastIndex, m_itemData.begin() + newIndex);
- lastIndex = newIndex;
- }
- } else {
- if (!m_groups.isEmpty()) {
- m_groups.clear();
- }
- sort(m_itemData.begin(), m_itemData.end());
- }
-
+ // Resort the items
+ sort(m_itemData.begin(), m_itemData.end());
for (int i = 0; i < itemCount; ++i) {
m_items.insert(m_itemData.at(i)->item.url(), i);
}
Q_EMIT itemsMoved(KItemRange(firstMovedIndex, movedItemsCount), movedToIndexes);
} else if (groupedSorting()) {
- if (m_groups != oldGroups) {
+ // The groups might have changed even if the order of the items has not.
+ const QList<QPair<int, QVariant>> oldGroups = m_groups;
+ m_groups.clear();
+ if (groups() != oldGroups) {
Q_EMIT groupsChanged();
}
}
-#ifdef KFILEITEMMODEL_DEBUGf
+#ifdef KFILEITEMMODEL_DEBUG
qCDebug(DolphinDebug) << "[TIME] Resorting of" << itemCount << "items:" << timer.elapsed();
#endif
}
}
// N
- //resortAllItems();
+ // resortAllItems();
// The indexes in m_items are not correct anymore. Therefore, we clear m_items.
// It will be re-populated with the updated indices if index(const QUrl&) is called.
m_items.clear();
}
}
- // Show hidden files and folders last
- if (m_sortHiddenLast) {
- const bool isHiddenA = a->item.isHidden();
- const bool isHiddenB = b->item.isHidden();
- if (isHiddenA && !isHiddenB) {
- return false;
- } else if (!isHiddenA && isHiddenB) {
- return true;
+ result = groupRoleCompare(a, b, collator);
+ if (result == 0) {
+ // Show hidden files and folders last
+ if (m_sortHiddenLast) {
+ const bool isHiddenA = a->item.isHidden();
+ const bool isHiddenB = b->item.isHidden();
+ if (isHiddenA && !isHiddenB) {
+ return false;
+ } else if (!isHiddenA && isHiddenB) {
+ return true;
+ }
}
- }
-
- if (m_sortDirsFirst
- || (ContentDisplaySettings::directorySizeMode() == ContentDisplaySettings::EnumDirectorySizeMode::ContentCount && m_sortRole == SizeRole)) {
- const bool isDirA = a->item.isDir();
- const bool isDirB = b->item.isDir();
- if (isDirA && !isDirB) {
- return true;
- } else if (!isDirA && isDirB) {
- return false;
+ if (m_sortDirsFirst
+ || (ContentDisplaySettings::directorySizeMode() == ContentDisplaySettings::EnumDirectorySizeMode::ContentCount && m_sortRole == SizeRole)) {
+ const bool isDirA = a->item.isDir();
+ const bool isDirB = b->item.isDir();
+ if (isDirA && !isDirB) {
+ return true;
+ } else if (!isDirA && isDirB) {
+ return false;
+ }
}
+ result = sortRoleCompare(a, b, collator);
+ result = (sortOrder() == Qt::AscendingOrder) ? result < 0 : result > 0;
+ } else {
+ result = (groupOrder() == Qt::AscendingOrder) ? result < 0 : result > 0;
}
-
- result = sortRoleCompare(a, b, collator);
-
- return (sortOrder() == Qt::AscendingOrder) ? result < 0 : result > 0;
+ return result;
}
void KFileItemModel::sort(const QList<KFileItemModel::ItemData *>::iterator &begin, const QList<KFileItemModel::ItemData *>::iterator &end) const
return QString::compare(itemA.url().url(), itemB.url().url(), Qt::CaseSensitive);
}
+int KFileItemModel::groupRoleCompare(const ItemData *a, const ItemData *b, const QCollator &collator) const
+{
+ // Unlike sortRoleCompare, this function can and often will return 0.
+ const KFileItem &itemA = a->item;
+ const KFileItem &itemB = b->item;
+
+ int result = 0;
+
+ switch (m_groupRole) {
+ case NoRole:
+ break;
+ case NameRole: {
+ QChar groupA = getNameRoleGroup(a, false).toChar();
+ QChar groupB = getNameRoleGroup(b, false).toChar();
+ if (groupA < groupB) {
+ result = -1;
+ } else if (groupA > groupB) {
+ result = 1;
+ }
+ break;
+ }
+ case SizeRole: {
+ int groupA = getSizeRoleGroup(a, false).toInt();
+ int groupB = getSizeRoleGroup(b, false).toInt();
+ if (groupA < groupB) {
+ result = -1;
+ } else if (groupA > groupB) {
+ result = 1;
+ }
+ break;
+ }
+ case ModificationTimeRole: {
+ int groupA = getTimeRoleGroup(
+ [](const ItemData *item) {
+ return item->item.time(KFileItem::ModificationTime);
+ },
+ a,
+ false)
+ .toInt();
+ int groupB = getTimeRoleGroup(
+ [](const ItemData *item) {
+ return item->item.time(KFileItem::ModificationTime);
+ },
+ b,
+ false)
+ .toInt();
+ if (groupA < groupB) {
+ result = -1;
+ } else if (groupA > groupB) {
+ result = 1;
+ }
+ break;
+ }
+ case CreationTimeRole: {
+ int groupA = getTimeRoleGroup(
+ [](const ItemData *item) {
+ return item->item.time(KFileItem::CreationTime);
+ },
+ a,
+ false)
+ .toInt();
+ int groupB = getTimeRoleGroup(
+ [](const ItemData *item) {
+ return item->item.time(KFileItem::CreationTime);
+ },
+ b,
+ false)
+ .toInt();
+ if (groupA < groupB) {
+ result = -1;
+ } else if (groupA > groupB) {
+ result = 1;
+ }
+ break;
+ }
+ case AccessTimeRole: {
+ int groupA = getTimeRoleGroup(
+ [](const ItemData *item) {
+ return item->item.time(KFileItem::AccessTime);
+ },
+ a,
+ false)
+ .toInt();
+ int groupB = getTimeRoleGroup(
+ [](const ItemData *item) {
+ return item->item.time(KFileItem::AccessTime);
+ },
+ b,
+ false)
+ .toInt();
+ if (groupA < groupB) {
+ result = -1;
+ } else if (groupA > groupB) {
+ result = 1;
+ }
+ break;
+ }
+ case DeletionTimeRole: {
+ int groupA = getTimeRoleGroup(
+ [](const ItemData *item) {
+ return item->values.value("deletiontime").toDateTime();
+ },
+ a,
+ false)
+ .toInt();
+ int groupB = getTimeRoleGroup(
+ [](const ItemData *item) {
+ return item->values.value("deletiontime").toDateTime();
+ },
+ b,
+ false)
+ .toInt();
+ if (groupA < groupB) {
+ result = -1;
+ } else if (groupA > groupB) {
+ result = 1;
+ }
+ break;
+ }
+ // case PermissionsRole:
+ // case RatingRole:
+ default: {
+ QString groupA = getGenericStringRoleGroup(groupRole(), a);
+ QString groupB = getGenericStringRoleGroup(groupRole(), b);
+ if (groupA < groupB) {
+ result = -1;
+ } else if (groupA > groupB) {
+ result = 1;
+ }
+ break;
+ }
+ }
+ return result;
+}
+
int KFileItemModel::stringCompare(const QString &a, const QString &b, const QCollator &collator) const
{
QMutexLocker collatorLock(s_collatorMutex());
return QString::compare(a, b, Qt::CaseSensitive);
}
-QList<QPair<int, QVariant>> KFileItemModel::nameRoleGroups() const
+QVariant KFileItemModel::getNameRoleGroup(const ItemData *itemData, bool asString) const
{
- Q_ASSERT(!m_itemData.isEmpty());
-
- const int maxIndex = count() - 1;
- QList<QPair<int, QVariant>> groups;
-
- QString groupValue;
- QChar firstChar;
- for (int i = 0; i <= maxIndex; ++i) {
- if (isChildItem(i)) {
- continue;
- }
-
- const QString name = m_itemData.at(i)->item.text();
-
- // 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).toUpper();
- }
-
- if (firstChar != newFirstChar) {
- QString newGroupValue;
- if (newFirstChar.isLetter()) {
- if (m_collator.compare(newFirstChar, QChar(QLatin1Char('A'))) >= 0 && m_collator.compare(newFirstChar, QChar(QLatin1Char('Z'))) <= 0) {
- // WARNING! Symbols based on latin 'Z' like 'Z' with acute are treated wrong as non Latin and put in a new group.
-
- // Try to find a matching group in the range 'A' to 'Z'.
- static std::vector<QChar> lettersAtoZ;
- lettersAtoZ.reserve('Z' - 'A' + 1);
- if (lettersAtoZ.empty()) {
- for (char c = 'A'; c <= 'Z'; ++c) {
- lettersAtoZ.push_back(QLatin1Char(c));
- }
- }
+ const KFileItem item = itemData->item;
+ const QString name = item.text();
+ QVariant newGroupValue;
+ // 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).toUpper();
+ }
- auto localeAwareLessThan = [this](QChar c1, QChar c2) -> bool {
- return m_collator.compare(c1, c2) < 0;
- };
+ if (newFirstChar.isLetter()) {
+ if (m_collator.compare(newFirstChar, QChar(QLatin1Char('A'))) >= 0 && m_collator.compare(newFirstChar, QChar(QLatin1Char('Z'))) <= 0) {
+ // WARNING! Symbols based on latin 'Z' like 'Z' with acute are treated wrong as non Latin and put in a new group.
- std::vector<QChar>::iterator it = std::lower_bound(lettersAtoZ.begin(), lettersAtoZ.end(), newFirstChar, localeAwareLessThan);
- if (it != lettersAtoZ.end()) {
- if (localeAwareLessThan(newFirstChar, *it)) {
- // newFirstChar belongs to the group preceding *it.
- // Example: for an umlaut 'A' in the German locale, *it would be 'B' now.
- --it;
- }
- newGroupValue = *it;
- }
-
- } else {
- // Symbols from non Latin-based scripts
- newGroupValue = newFirstChar;
+ // Try to find a matching group in the range 'A' to 'Z'.
+ static std::vector<QChar> lettersAtoZ;
+ lettersAtoZ.reserve('Z' - 'A' + 1);
+ if (lettersAtoZ.empty()) {
+ for (char c = 'A'; c <= 'Z'; ++c) {
+ lettersAtoZ.push_back(QLatin1Char(c));
}
- } else if (newFirstChar >= QLatin1Char('0') && newFirstChar <= QLatin1Char('9')) {
- // Apply group '0 - 9' for any name that starts with a digit
- newGroupValue = i18nc("@title:group Groups that start with a digit", "0 - 9");
- } else {
- newGroupValue = i18nc("@title:group", "Others");
}
- if (newGroupValue != groupValue) {
- groupValue = newGroupValue;
- groups.append(QPair<int, QVariant>(i, newGroupValue));
+ auto localeAwareLessThan = [this](QChar c1, QChar c2) -> bool {
+ return m_collator.compare(c1, c2) < 0;
+ };
+
+ std::vector<QChar>::iterator it = std::lower_bound(lettersAtoZ.begin(), lettersAtoZ.end(), newFirstChar, localeAwareLessThan);
+ if (it != lettersAtoZ.end()) {
+ if (localeAwareLessThan(newFirstChar, *it)) {
+ // newFirstChar belongs to the group preceding *it.
+ // Example: for an umlaut 'A' in the German locale, *it would be 'B' now.
+ --it;
+ }
+ newGroupValue = *it;
}
- firstChar = newFirstChar;
+ } else {
+ // Symbols from non Latin-based scripts
+ newGroupValue = newFirstChar;
+ }
+ } else if (newFirstChar >= QLatin1Char('0') && newFirstChar <= QLatin1Char('9')) {
+ // Apply group '0 - 9' for any name that starts with a digit
+ if (asString) {
+ newGroupValue = i18nc("@title:group Groups that start with a digit", "0 - 9");
+ } else {
+ newGroupValue = QChar('0');
+ }
+ } else {
+ if (asString) {
+ newGroupValue = i18nc("@title:group", "Others");
+ } else {
+ newGroupValue = QChar('.');
}
}
- return groups;
+ return newGroupValue;
}
-QList<QPair<int, QVariant>> KFileItemModel::sizeRoleGroups() const
+QVariant KFileItemModel::getSizeRoleGroup(const ItemData *itemData, bool asString) const
{
- Q_ASSERT(!m_itemData.isEmpty());
-
- const int maxIndex = count() - 1;
- QList<QPair<int, QVariant>> groups;
+ const KFileItem item = itemData->item;
- QString groupValue;
- for (int i = 0; i <= maxIndex; ++i) {
- if (isChildItem(i)) {
- continue;
- }
-
- const KFileItem &item = m_itemData.at(i)->item;
- KIO::filesize_t fileSize = !item.isNull() ? item.size() : ~0U;
- QString newGroupValue;
- if (!item.isNull() && item.isDir()) {
- if (ContentDisplaySettings::directorySizeMode() == ContentDisplaySettings::EnumDirectorySizeMode::ContentCount || m_sortDirsFirst) {
- newGroupValue = i18nc("@title:group Size", "Folders");
- } else {
- fileSize = m_itemData.at(i)->values.value("size").toULongLong();
- }
- }
-
- if (newGroupValue.isEmpty()) {
- if (fileSize < 5 * 1024 * 1024) { // < 5 MB
- newGroupValue = i18nc("@title:group Size", "Small");
- } else if (fileSize < 10 * 1024 * 1024) { // < 10 MB
- newGroupValue = i18nc("@title:group Size", "Medium");
- } else {
- newGroupValue = i18nc("@title:group Size", "Big");
- }
+ KIO::filesize_t fileSize = !item.isNull() ? item.size() : ~0U;
+ int newGroupValue = -1; // None
+ if (!item.isNull() && item.isDir()) {
+ if (ContentDisplaySettings::directorySizeMode() == ContentDisplaySettings::EnumDirectorySizeMode::ContentCount || m_sortDirsFirst) {
+ newGroupValue = 0; // Folders
+ } else {
+ fileSize = itemData->values.value("size").toULongLong();
}
+ }
- if (newGroupValue != groupValue) {
- groupValue = newGroupValue;
- groups.append(QPair<int, QVariant>(i, newGroupValue));
+ if (newGroupValue < 0) {
+ if (fileSize < 5 * 1024 * 1024) { // < 5 MB
+ newGroupValue = 1; // Small
+ } else if (fileSize < 10 * 1024 * 1024) { // < 10 MB
+ newGroupValue = 2; // Medium
+ } else {
+ newGroupValue = 3; // Big
}
}
- return groups;
+ if (asString) {
+ char const *groupNames[] = {"Folders", "Small", "Medium", "Big"};
+ return i18nc("@title:group Size", groupNames[newGroupValue]);
+ } else {
+ return newGroupValue;
+ }
}
-QList<QPair<int, QVariant>> KFileItemModel::timeRoleGroups(const std::function<QDateTime(const ItemData *)> &fileTimeCb) const
+QVariant KFileItemModel::getTimeRoleGroup(const std::function<QDateTime(const ItemData *)> &fileTimeCb, const ItemData *itemData, bool asString) const
{
- Q_ASSERT(!m_itemData.isEmpty());
-
- const int maxIndex = count() - 1;
- QList<QPair<int, QVariant>> groups;
-
const QDate currentDate = QDate::currentDate();
+ const QDateTime fileTime = fileTimeCb(itemData);
+ const QDate fileDate = fileTime.date();
+ const int daysDistance = fileDate.daysTo(currentDate);
- QDate previousFileDate;
- QString groupValue;
- for (int i = 0; i <= maxIndex; ++i) {
- if (isChildItem(i)) {
- continue;
- }
+ int intGroupValue;
+ QString strGroupValue;
- const QDateTime fileTime = fileTimeCb(m_itemData.at(i));
- const QDate fileDate = fileTime.date();
- if (fileDate == previousFileDate) {
- // The current item is in the same group as the previous item
- continue;
+ if (!asString) {
+ // Simplified grouping algorithm, preserving dates
+ // but not taking "pretty printing" into account
+ if (currentDate.year() == fileDate.year() && currentDate.month() == fileDate.month()) {
+ if (daysDistance < 7) {
+ intGroupValue = daysDistance; // Today, Yesterday and week days
+ } else if (daysDistance < 14) {
+ intGroupValue = 10; // One Week Ago
+ } else if (daysDistance < 21) {
+ intGroupValue = 20; // Two Weeks Ago
+ } else if (daysDistance < 28) {
+ intGroupValue = 30; // Three Weeks Ago
+ } else {
+ intGroupValue = 40; // Earlier This Month
+ }
+ } else {
+ const QDate lastMonthDate = currentDate.addMonths(-1);
+ if (lastMonthDate.year() == fileDate.year() && lastMonthDate.month() == fileDate.month()) {
+ if (daysDistance < 7) {
+ intGroupValue = daysDistance; // Today, Yesterday and week days (Month, Year)
+ } else if (daysDistance < 14) {
+ intGroupValue = 9; // One Week Ago (Month, Year)
+ } else if (daysDistance < 21) {
+ intGroupValue = 19; // Two Weeks Ago (Month, Year)
+ } else if (daysDistance < 28) {
+ intGroupValue = 29; // Three Weeks Ago (Month, Year)
+ } else {
+ intGroupValue = 39; // Earlier on Month, Year
+ }
+ } else {
+ // The trick will fail for dates past April, 178956967 or before 1 AD.
+ intGroupValue = 2147483647 - (fileDate.year() * 12 + fileDate.month() - 1); // Month, Year; newer < older
+ }
}
- previousFileDate = fileDate;
-
- const int daysDistance = fileDate.daysTo(currentDate);
-
- QString newGroupValue;
+ return QVariant(intGroupValue);
+ } else {
if (currentDate.year() == fileDate.year() && currentDate.month() == fileDate.month()) {
switch (daysDistance / 7) {
case 0:
switch (daysDistance) {
case 0:
- newGroupValue = i18nc("@title:group Date", "Today");
+ strGroupValue = i18nc("@title:group Date", "Today");
break;
case 1:
- newGroupValue = i18nc("@title:group Date", "Yesterday");
+ strGroupValue = i18nc("@title:group Date", "Yesterday");
break;
default:
- newGroupValue = fileTime.toString(i18nc("@title:group Date: The week day name: dddd", "dddd"));
- newGroupValue = i18nc(
+ strGroupValue = fileTime.toString(i18nc("@title:group Date: The week day name: dddd", "dddd"));
+ strGroupValue = i18nc(
"Can be used to script translation of \"dddd\""
"with context @title:group Date",
"%1",
- newGroupValue);
+ strGroupValue);
}
break;
case 1:
- newGroupValue = i18nc("@title:group Date", "One Week Ago");
+ strGroupValue = i18nc("@title:group Date", "One Week Ago");
break;
case 2:
- newGroupValue = i18nc("@title:group Date", "Two Weeks Ago");
+ strGroupValue = i18nc("@title:group Date", "Two Weeks Ago");
break;
case 3:
- newGroupValue = i18nc("@title:group Date", "Three Weeks Ago");
+ strGroupValue = i18nc("@title:group Date", "Three Weeks Ago");
break;
case 4:
case 5:
- newGroupValue = i18nc("@title:group Date", "Earlier this Month");
+ strGroupValue = i18nc("@title:group Date", "Earlier this Month");
break;
default:
Q_ASSERT(false);
"'Yesterday' (MMMM, yyyy)");
const QString translatedFormat = format.toString();
if (translatedFormat.count(QLatin1Char('\'')) == 2) {
- newGroupValue = fileTime.toString(translatedFormat);
- newGroupValue = i18nc(
+ strGroupValue = fileTime.toString(translatedFormat);
+ strGroupValue = i18nc(
"Can be used to script translation of "
"\"'Yesterday' (MMMM, yyyy)\" with context @title:group Date",
"%1",
- newGroupValue);
+ strGroupValue);
} else {
qCWarning(DolphinDebug).nospace()
<< "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org";
const QString untranslatedFormat = format.toString({QLatin1String("en_US")});
- newGroupValue = fileTime.toString(untranslatedFormat);
+ strGroupValue = fileTime.toString(untranslatedFormat);
}
} else if (daysDistance <= 7) {
- newGroupValue =
+ strGroupValue =
fileTime.toString(i18nc("@title:group Date: "
"The week day name: dddd, MMMM is full month name "
"in current locale, and yyyy is full year number.",
"dddd (MMMM, yyyy)"));
- newGroupValue = i18nc(
+ strGroupValue = i18nc(
"Can be used to script translation of "
"\"dddd (MMMM, yyyy)\" with context @title:group Date",
"%1",
- newGroupValue);
+ strGroupValue);
} else if (daysDistance <= 7 * 2) {
const KLocalizedString format = ki18nc(
"@title:group Date: "
"'One Week Ago' (MMMM, yyyy)");
const QString translatedFormat = format.toString();
if (translatedFormat.count(QLatin1Char('\'')) == 2) {
- newGroupValue = fileTime.toString(translatedFormat);
- newGroupValue = i18nc(
+ strGroupValue = fileTime.toString(translatedFormat);
+ strGroupValue = i18nc(
"Can be used to script translation of "
"\"'One Week Ago' (MMMM, yyyy)\" with context @title:group Date",
"%1",
- newGroupValue);
+ strGroupValue);
} else {
qCWarning(DolphinDebug).nospace()
<< "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org";
const QString untranslatedFormat = format.toString({QLatin1String("en_US")});
- newGroupValue = fileTime.toString(untranslatedFormat);
+ strGroupValue = fileTime.toString(untranslatedFormat);
}
} else if (daysDistance <= 7 * 3) {
const KLocalizedString format = ki18nc(
"'Two Weeks Ago' (MMMM, yyyy)");
const QString translatedFormat = format.toString();
if (translatedFormat.count(QLatin1Char('\'')) == 2) {
- newGroupValue = fileTime.toString(translatedFormat);
- newGroupValue = i18nc(
+ strGroupValue = fileTime.toString(translatedFormat);
+ strGroupValue = i18nc(
"Can be used to script translation of "
"\"'Two Weeks Ago' (MMMM, yyyy)\" with context @title:group Date",
"%1",
- newGroupValue);
+ strGroupValue);
} else {
qCWarning(DolphinDebug).nospace()
<< "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org";
const QString untranslatedFormat = format.toString({QLatin1String("en_US")});
- newGroupValue = fileTime.toString(untranslatedFormat);
+ strGroupValue = fileTime.toString(untranslatedFormat);
}
} else if (daysDistance <= 7 * 4) {
const KLocalizedString format = ki18nc(
"'Three Weeks Ago' (MMMM, yyyy)");
const QString translatedFormat = format.toString();
if (translatedFormat.count(QLatin1Char('\'')) == 2) {
- newGroupValue = fileTime.toString(translatedFormat);
- newGroupValue = i18nc(
+ strGroupValue = fileTime.toString(translatedFormat);
+ strGroupValue = i18nc(
"Can be used to script translation of "
"\"'Three Weeks Ago' (MMMM, yyyy)\" with context @title:group Date",
"%1",
- newGroupValue);
+ strGroupValue);
} else {
qCWarning(DolphinDebug).nospace()
<< "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org";
const QString untranslatedFormat = format.toString({QLatin1String("en_US")});
- newGroupValue = fileTime.toString(untranslatedFormat);
+ strGroupValue = fileTime.toString(untranslatedFormat);
}
} else {
const KLocalizedString format = ki18nc(
"'Earlier on' MMMM, yyyy");
const QString translatedFormat = format.toString();
if (translatedFormat.count(QLatin1Char('\'')) == 2) {
- newGroupValue = fileTime.toString(translatedFormat);
- newGroupValue = i18nc(
+ strGroupValue = fileTime.toString(translatedFormat);
+ strGroupValue = i18nc(
"Can be used to script translation of "
"\"'Earlier on' MMMM, yyyy\" with context @title:group Date",
"%1",
- newGroupValue);
+ strGroupValue);
} else {
qCWarning(DolphinDebug).nospace()
<< "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org";
const QString untranslatedFormat = format.toString({QLatin1String("en_US")});
- newGroupValue = fileTime.toString(untranslatedFormat);
+ strGroupValue = fileTime.toString(untranslatedFormat);
}
}
} else {
- newGroupValue =
+ strGroupValue =
fileTime.toString(i18nc("@title:group "
"The month and year: MMMM is full month name in current locale, "
"and yyyy is full year number",
"MMMM, yyyy"));
- newGroupValue = i18nc(
+ strGroupValue = i18nc(
"Can be used to script translation of "
"\"MMMM, yyyy\" with context @title:group Date",
"%1",
- newGroupValue);
+ strGroupValue);
}
}
+ return QVariant(strGroupValue);
+ }
+}
+
+QString KFileItemModel::getGenericStringRoleGroup(const QByteArray &role, const ItemData *itemData) const
+{
+ return itemData->values.value(role).toString();
+}
+
+QList<QPair<int, QVariant>> KFileItemModel::nameRoleGroups() const
+{
+ Q_ASSERT(!m_itemData.isEmpty());
+
+ const int maxIndex = count() - 1;
+ QList<QPair<int, QVariant>> groups;
+
+ QString groupValue;
+ QChar firstChar;
+ for (int i = 0; i <= maxIndex; ++i) {
+ if (isChildItem(i)) {
+ continue;
+ }
+
+ QString newGroupValue = getNameRoleGroup(m_itemData.at(i)).toString();
+
+ 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_itemData.isEmpty());
+
+ const int maxIndex = count() - 1;
+ QList<QPair<int, QVariant>> groups;
+
+ QString groupValue;
+ for (int i = 0; i <= maxIndex; ++i) {
+ if (isChildItem(i)) {
+ continue;
+ }
+
+ QString newGroupValue = getSizeRoleGroup(m_itemData.at(i)).toString();
+
+ if (newGroupValue != groupValue) {
+ groupValue = newGroupValue;
+ groups.append(QPair<int, QVariant>(i, newGroupValue));
+ }
+ }
+
+ return groups;
+}
+
+QList<QPair<int, QVariant>> KFileItemModel::timeRoleGroups(const std::function<QDateTime(const ItemData *)> &fileTimeCb) const
+{
+ Q_ASSERT(!m_itemData.isEmpty());
+
+ const int maxIndex = count() - 1;
+ QList<QPair<int, QVariant>> groups;
+
+ const QDate currentDate = QDate::currentDate();
+
+ QDate previousFileDate;
+ QString groupValue;
+ for (int i = 0; i <= maxIndex; ++i) {
+ if (isChildItem(i)) {
+ continue;
+ }
+
+ const QDateTime fileTime = fileTimeCb(m_itemData.at(i));
+ const QDate fileDate = fileTime.date();
+ if (fileDate == previousFileDate) {
+ // The current item is in the same group as the previous item
+ continue;
+ }
+ previousFileDate = fileDate;
+
+ QString newGroupValue = getTimeRoleGroup(fileTimeCb, m_itemData.at(i)).toString();
if (newGroupValue != groupValue) {
groupValue = newGroupValue;
if (isChildItem(i)) {
continue;
}
+
const int newGroupValue = m_itemData.at(i)->values.value("rating", 0).toInt();
if (newGroupValue != groupValue) {
groupValue = newGroupValue;
if (isChildItem(i)) {
continue;
}
- const QString newGroupValue = m_itemData.at(i)->values.value(role).toString();
+
+ const QString newGroupValue = getGenericStringRoleGroup(role, m_itemData.at(i));
if (newGroupValue != groupValue || isFirstGroupValue) {
groupValue = newGroupValue;
groups.append(QPair<int, QVariant>(i, newGroupValue));