int count = 0;
const RoleInfoMap* map = rolesInfoMap(count);
for (int i = 0; i < count; ++i) {
+ if (!map[i].roleTranslation) {
+ continue;
+ }
description.insert(map[i].role, i18nc(map[i].roleTranslationContext, map[i].roleTranslation));
}
}
m_groups.clear();
}
-void KFileItemModel::onSortRoleChanged(const QByteArray& current, const QByteArray& previous)
+void KFileItemModel::onSortRoleChanged(const QByteArray& current, const QByteArray& previous, bool resortItems)
{
Q_UNUSED(previous);
m_sortRole = typeForRole(current);
setRoles(newRoles);
}
- resortAllItems();
+ if (resortItems) {
+ resortAllItems();
+ }
}
void KFileItemModel::onSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous)
default:
Q_UNREACHABLE();
}
+ // Workaround for bug https://bugreports.qt.io/browse/QTBUG-69361
+ // Force the clean state of QCollator in single thread to avoid thread safety problems in sort
+ m_collator.compare(QString(), QString());
}
void KFileItemModel::resortAllItems()
}
// Extract the item-ranges out of the changed indexes
- qSort(indexes);
+ std::sort(indexes.begin(), indexes.end());
const KItemRangeList itemRangeList = KItemRangeList::fromSortedContainer(indexes);
emitItemsChangedAndTriggerResorting(itemRangeList, changedRoles);
}
} else {
m_itemData.reserve(totalItemCount);
for (int i = existingItemCount; i < totalItemCount; ++i) {
- m_itemData.append(0);
+ m_itemData.append(nullptr);
}
// We build the new list m_itemData in reverse order to minimize
delete m_itemData.at(index);
}
- m_itemData[index] = 0;
+ m_itemData[index] = nullptr;
}
}
}
const int parentIndex = index(parentUrl);
- ItemData* parentItem = parentIndex < 0 ? 0 : m_itemData.at(parentIndex);
+ ItemData* parentItem = parentIndex < 0 ? nullptr : m_itemData.at(parentIndex);
QList<ItemData*> itemDataList;
itemDataList.reserve(items.count());
data.insert(sharedValue("isLink"), true);
}
- if (m_requestRole[IsHiddenRole] && item.isHidden()) {
- data.insert(sharedValue("isHidden"), true);
+ if (m_requestRole[IsHiddenRole]) {
+ data.insert(sharedValue("isHidden"), item.isHidden());
}
if (m_requestRole[NameRole]) {
}
if (m_requestRole[ModificationTimeRole]) {
- // Don't use KFileItem::timeString() as this is too expensive when
- // having several thousands of items. Instead the formatting of the
- // date-time will be done on-demand by the view when the date will be shown.
- const QDateTime dateTime = item.time(KFileItem::ModificationTime);
+ // Don't use KFileItem::timeString() or KFileItem::time() as this is too expensive when
+ // having several thousands of items. Instead read the raw number from UDSEntry directly
+ // and the formatting of the date-time will be done on-demand by the view when the date will be shown.
+ const long long dateTime = item.entry().numberValue(KIO::UDSEntry::UDS_MODIFICATION_TIME, -1);
data.insert(sharedValue("modificationtime"), dateTime);
}
if (m_requestRole[CreationTimeRole]) {
- // Don't use KFileItem::timeString() as this is too expensive when
- // having several thousands of items. Instead the formatting of the
- // date-time will be done on-demand by the view when the date will be shown.
- const QDateTime dateTime = item.time(KFileItem::CreationTime);
+ // Don't use KFileItem::timeString() or KFileItem::time() as this is too expensive when
+ // having several thousands of items. Instead read the raw number from UDSEntry directly
+ // and the formatting of the date-time will be done on-demand by the view when the date will be shown.
+ const long long dateTime = item.entry().numberValue(KIO::UDSEntry::UDS_CREATION_TIME, -1);
data.insert(sharedValue("creationtime"), dateTime);
}
if (m_requestRole[AccessTimeRole]) {
- // Don't use KFileItem::timeString() as this is too expensive when
- // having several thousands of items. Instead the formatting of the
- // date-time will be done on-demand by the view when the date will be shown.
- const QDateTime dateTime = item.time(KFileItem::AccessTime);
+ // Don't use KFileItem::timeString() or KFileItem::time() as this is too expensive when
+ // having several thousands of items. Instead read the raw number from UDSEntry directly
+ // and the formatting of the date-time will be done on-demand by the view when the date will be shown.
+ const long long dateTime = item.entry().numberValue(KIO::UDSEntry::UDS_ACCESS_TIME, -1);
data.insert(sharedValue("accesstime"), dateTime);
}
return (sortOrder() == Qt::AscendingOrder) ? result < 0 : result > 0;
}
-/**
- * Helper class for KFileItemModel::sort().
- */
-class KFileItemModelLessThan
+void KFileItemModel::sort(const QList<KFileItemModel::ItemData*>::iterator &begin,
+ const QList<KFileItemModel::ItemData*>::iterator &end) const
{
-public:
- KFileItemModelLessThan(const KFileItemModel* model, const QCollator& collator) :
- m_model(model),
- m_collator(collator)
- {
- }
-
- KFileItemModelLessThan(const KFileItemModelLessThan& other) :
- m_model(other.m_model),
- m_collator()
- {
- m_collator.setCaseSensitivity(other.m_collator.caseSensitivity());
- m_collator.setIgnorePunctuation(other.m_collator.ignorePunctuation());
- m_collator.setLocale(other.m_collator.locale());
- m_collator.setNumericMode(other.m_collator.numericMode());
- }
-
- ~KFileItemModelLessThan() = default;
- //We do not delete m_model as the pointer was passed from outside ant it will be deleted elsewhere.
-
- KFileItemModelLessThan& operator=(const KFileItemModelLessThan& other)
+ auto lambdaLessThan = [&] (const KFileItemModel::ItemData* a, const KFileItemModel::ItemData* b)
{
- m_model = other.m_model;
- m_collator = other.m_collator;
- return *this;
- }
-
- bool operator()(const KFileItemModel::ItemData* a, const KFileItemModel::ItemData* b) const
- {
- return m_model->lessThan(a, b, m_collator);
- }
-
-private:
- const KFileItemModel* m_model;
- QCollator m_collator;
-};
-
-void KFileItemModel::sort(QList<KFileItemModel::ItemData*>::iterator begin,
- QList<KFileItemModel::ItemData*>::iterator end) const
-{
- KFileItemModelLessThan lessThan(this, m_collator);
+ return lessThan(a, b, m_collator);
+ };
if (m_sortRole == NameRole) {
// Sorting by name can be expensive, in particular if natural sorting is
// enabled. Use all CPU cores to speed up the sorting process.
static const int numberOfThreads = QThread::idealThreadCount();
- parallelMergeSort(begin, end, lessThan, numberOfThreads);
+ parallelMergeSort(begin, end, lambdaLessThan, numberOfThreads);
} else {
// Sorting by other roles is quite fast. Use only one thread to prevent
// problems caused by non-reentrant comparison functions, see
// https://bugs.kde.org/show_bug.cgi?id=312679
- mergeSort(begin, end, lessThan);
+ mergeSort(begin, end, lambdaLessThan);
}
}
}
case ModificationTimeRole: {
- const QDateTime dateTimeA = itemA.time(KFileItem::ModificationTime);
- const QDateTime dateTimeB = itemB.time(KFileItem::ModificationTime);
+ const long long dateTimeA = itemA.entry().numberValue(KIO::UDSEntry::UDS_MODIFICATION_TIME, -1);
+ const long long dateTimeB = itemB.entry().numberValue(KIO::UDSEntry::UDS_MODIFICATION_TIME, -1);
if (dateTimeA < dateTimeB) {
result = -1;
} else if (dateTimeA > dateTimeB) {
}
case CreationTimeRole: {
- const QDateTime dateTimeA = itemA.time(KFileItem::CreationTime);
- const QDateTime dateTimeB = itemB.time(KFileItem::CreationTime);
+ const long long dateTimeA = itemA.entry().numberValue(KIO::UDSEntry::UDS_CREATION_TIME, -1);
+ const long long dateTimeB = itemB.entry().numberValue(KIO::UDSEntry::UDS_CREATION_TIME, -1);
if (dateTimeA < dateTimeB) {
result = -1;
} else if (dateTimeA > dateTimeB) {
return groups;
}
-QList<QPair<int, QVariant> > KFileItemModel::timeRoleGroups(std::function<QDateTime(const ItemData *)> fileTimeCb) const
+QList<QPair<int, QVariant> > KFileItemModel::timeRoleGroups(const std::function<QDateTime(const ItemData *)> &fileTimeCb) const
{
Q_ASSERT(!m_itemData.isEmpty());
lastMonthDate.month() == fileDate.month()) {
if (daysDistance == 1) {
- newGroupValue = fileTime.toString(i18nc("@title:group Date: "
- "MMMM is full month name in current locale, and yyyy is "
- "full year number", "'Yesterday' (MMMM, yyyy)"));
- newGroupValue = i18nc("Can be used to script translation of "
- "\"'Yesterday' (MMMM, yyyy)\" with context @title:group Date",
- "%1", newGroupValue);
+ const KLocalizedString format = ki18nc("@title:group Date: "
+ "MMMM is full month name in current locale, and yyyy is "
+ "full year number", "'Yesterday' (MMMM, yyyy)");
+ const QString translatedFormat = format.toString();
+ if (translatedFormat.count(QLatin1Char('\'')) == 2) {
+ newGroupValue = fileTime.toString(translatedFormat);
+ newGroupValue = i18nc("Can be used to script translation of "
+ "\"'Yesterday' (MMMM, yyyy)\" with context @title:group Date",
+ "%1", newGroupValue);
+ } 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);
+ }
} else if (daysDistance <= 7) {
newGroupValue = fileTime.toString(i18nc("@title:group Date: "
"The week day name: dddd, MMMM is full month name "
"\"dddd (MMMM, yyyy)\" with context @title:group Date",
"%1", newGroupValue);
} else if (daysDistance <= 7 * 2) {
- newGroupValue = fileTime.toString(i18nc("@title:group Date: "
- "MMMM is full month name in current locale, and yyyy is "
- "full year number", "'One Week Ago' (MMMM, yyyy)"));
- newGroupValue = i18nc("Can be used to script translation of "
- "\"'One Week Ago' (MMMM, yyyy)\" with context @title:group Date",
- "%1", newGroupValue);
+ const KLocalizedString format = ki18nc("@title:group Date: "
+ "MMMM is full month name in current locale, and yyyy is "
+ "full year number", "'One Week Ago' (MMMM, yyyy)");
+ const QString translatedFormat = format.toString();
+ if (translatedFormat.count(QLatin1Char('\'')) == 2) {
+ newGroupValue = fileTime.toString(translatedFormat);
+ newGroupValue = i18nc("Can be used to script translation of "
+ "\"'One Week Ago' (MMMM, yyyy)\" with context @title:group Date",
+ "%1", newGroupValue);
+ } 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);
+ }
} else if (daysDistance <= 7 * 3) {
- newGroupValue = fileTime.toString(i18nc("@title:group Date: "
- "MMMM is full month name in current locale, and yyyy is "
- "full year number", "'Two Weeks Ago' (MMMM, yyyy)"));
- newGroupValue = i18nc("Can be used to script translation of "
- "\"'Two Weeks Ago' (MMMM, yyyy)\" with context @title:group Date",
- "%1", newGroupValue);
+ const KLocalizedString format = ki18nc("@title:group Date: "
+ "MMMM is full month name in current locale, and yyyy is "
+ "full year number", "'Two Weeks Ago' (MMMM, yyyy)");
+ const QString translatedFormat = format.toString();
+ if (translatedFormat.count(QLatin1Char('\'')) == 2) {
+ newGroupValue = fileTime.toString(translatedFormat);
+ newGroupValue = i18nc("Can be used to script translation of "
+ "\"'Two Weeks Ago' (MMMM, yyyy)\" with context @title:group Date",
+ "%1", newGroupValue);
+ } 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);
+ }
} else if (daysDistance <= 7 * 4) {
- newGroupValue = fileTime.toString(i18nc("@title:group Date: "
- "MMMM is full month name in current locale, and yyyy is "
- "full year number", "'Three Weeks Ago' (MMMM, yyyy)"));
- newGroupValue = i18nc("Can be used to script translation of "
- "\"'Three Weeks Ago' (MMMM, yyyy)\" with context @title:group Date",
- "%1", newGroupValue);
+ const KLocalizedString format = ki18nc("@title:group Date: "
+ "MMMM is full month name in current locale, and yyyy is "
+ "full year number", "'Three Weeks Ago' (MMMM, yyyy)");
+ const QString translatedFormat = format.toString();
+ if (translatedFormat.count(QLatin1Char('\'')) == 2) {
+ newGroupValue = fileTime.toString(translatedFormat);
+ newGroupValue = i18nc("Can be used to script translation of "
+ "\"'Three Weeks Ago' (MMMM, yyyy)\" with context @title:group Date",
+ "%1", newGroupValue);
+ } 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);
+ }
} else {
- newGroupValue = fileTime.toString(i18nc("@title:group Date: "
- "MMMM is full month name in current locale, and yyyy is "
- "full year number", "'Earlier on' MMMM, yyyy"));
- newGroupValue = i18nc("Can be used to script translation of "
- "\"'Earlier on' MMMM, yyyy\" with context @title:group Date",
- "%1", newGroupValue);
+ const KLocalizedString format = ki18nc("@title:group Date: "
+ "MMMM is full month name in current locale, and yyyy is "
+ "full year number", "'Earlier on' MMMM, yyyy");
+ const QString translatedFormat = format.toString();
+ if (translatedFormat.count(QLatin1Char('\'')) == 2) {
+ newGroupValue = fileTime.toString(translatedFormat);
+ newGroupValue = i18nc("Can be used to script translation of "
+ "\"'Earlier on' MMMM, yyyy\" with context @title:group Date",
+ "%1", newGroupValue);
+ } 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);
+ }
}
} else {
newGroupValue = fileTime.toString(i18nc("@title:group "
{ "bitrate", BitrateRole, I18N_NOOP2_NOSTRIP("@label", "Bitrate"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
{ "track", TrackRole, I18N_NOOP2_NOSTRIP("@label", "Track"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
{ "releaseYear", ReleaseYearRole, I18N_NOOP2_NOSTRIP("@label", "Release Year"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "aspectRatio", AspectRatioRole, I18N_NOOP2_NOSTRIP("@label", "Aspect Ratio"), I18N_NOOP2_NOSTRIP("@label", "Video"), true, true },
+ { "frameRate", FrameRateRole, I18N_NOOP2_NOSTRIP("@label", "Frame Rate"), I18N_NOOP2_NOSTRIP("@label", "Video"), true, true },
{ "path", PathRole, I18N_NOOP2_NOSTRIP("@label", "Path"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
{ "deletiontime",DeletionTimeRole,I18N_NOOP2_NOSTRIP("@label", "Deletion Time"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
{ "destination", DestinationRole, I18N_NOOP2_NOSTRIP("@label", "Link Destination"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },