+void KFileItemModel::emitSortProgress(int resolvedCount)
+{
+ // Be tolerant against a resolvedCount with a wrong range.
+ // Although there should not be a case where KFileItemModelRolesUpdater
+ // (= caller) provides a wrong range, it is important to emit
+ // a useful progress information even if there is an unexpected
+ // implementation issue.
+
+ const int itemCount = count();
+ if (resolvedCount >= itemCount) {
+ m_sortingProgressPercent = -1;
+ if (m_resortAllItemsTimer->isActive()) {
+ m_resortAllItemsTimer->stop();
+ resortAllItems();
+ }
+
+ emit directorySortingProgress(100);
+ } else if (itemCount > 0) {
+ resolvedCount = qBound(0, resolvedCount, itemCount);
+
+ const int progress = resolvedCount * 100 / itemCount;
+ if (m_sortingProgressPercent != progress) {
+ m_sortingProgressPercent = progress;
+ emit directorySortingProgress(progress);
+ }
+ }
+}
+
+const KFileItemModel::RoleInfoMap* KFileItemModel::rolesInfoMap(int& count)
+{
+ static const RoleInfoMap rolesInfoMap[] = {
+ // | role | roleType | role translation | group translation | requires Baloo | requires indexer
+ { nullptr, NoRole, nullptr, nullptr, nullptr, nullptr, false, false },
+ { "text", NameRole, I18N_NOOP2_NOSTRIP("@label", "Name"), nullptr, nullptr, false, false },
+ { "size", SizeRole, I18N_NOOP2_NOSTRIP("@label", "Size"), nullptr, nullptr, false, false },
+ { "modificationtime", ModificationTimeRole, I18N_NOOP2_NOSTRIP("@label", "Modified"), nullptr, nullptr, false, false },
+ { "creationtime", CreationTimeRole, I18N_NOOP2_NOSTRIP("@label", "Created"), nullptr, nullptr, false, false },
+ { "accesstime", AccessTimeRole, I18N_NOOP2_NOSTRIP("@label", "Accessed"), nullptr, nullptr, false, false },
+ { "type", TypeRole, I18N_NOOP2_NOSTRIP("@label", "Type"), nullptr, nullptr, false, false },
+ { "rating", RatingRole, I18N_NOOP2_NOSTRIP("@label", "Rating"), nullptr, nullptr, true, false },
+ { "tags", TagsRole, I18N_NOOP2_NOSTRIP("@label", "Tags"), nullptr, nullptr, true, false },
+ { "comment", CommentRole, I18N_NOOP2_NOSTRIP("@label", "Comment"), nullptr, nullptr, true, false },
+ { "title", TitleRole, I18N_NOOP2_NOSTRIP("@label", "Title"), I18N_NOOP2_NOSTRIP("@label", "Document"), true, true },
+ { "wordCount", WordCountRole, I18N_NOOP2_NOSTRIP("@label", "Word Count"), I18N_NOOP2_NOSTRIP("@label", "Document"), true, true },
+ { "lineCount", LineCountRole, I18N_NOOP2_NOSTRIP("@label", "Line Count"), I18N_NOOP2_NOSTRIP("@label", "Document"), true, true },
+ { "imageDateTime", ImageDateTimeRole, I18N_NOOP2_NOSTRIP("@label", "Date Photographed"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
+ { "imageSize", ImageSizeRole, I18N_NOOP2_NOSTRIP("@label", "Image Size"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
+ { "orientation", OrientationRole, I18N_NOOP2_NOSTRIP("@label", "Orientation"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
+ { "artist", ArtistRole, I18N_NOOP2_NOSTRIP("@label", "Artist"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "genre", GenreRole, I18N_NOOP2_NOSTRIP("@label", "Genre"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "album", AlbumRole, I18N_NOOP2_NOSTRIP("@label", "Album"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "duration", DurationRole, I18N_NOOP2_NOSTRIP("@label", "Duration"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "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 },
+ { "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 },
+ { "originUrl", OriginUrlRole, I18N_NOOP2_NOSTRIP("@label", "Downloaded From"), I18N_NOOP2_NOSTRIP("@label", "Other"), true, false },
+ { "permissions", PermissionsRole, I18N_NOOP2_NOSTRIP("@label", "Permissions"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
+ { "owner", OwnerRole, I18N_NOOP2_NOSTRIP("@label", "Owner"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
+ { "group", GroupRole, I18N_NOOP2_NOSTRIP("@label", "User Group"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
+ };
+
+ count = sizeof(rolesInfoMap) / sizeof(RoleInfoMap);
+ return rolesInfoMap;
+}
+
+void KFileItemModel::determineMimeTypes(const KFileItemList& items, int timeout)
+{
+ QElapsedTimer timer;
+ timer.start();
+ foreach (const KFileItem& item, items) { // krazy:exclude=foreach
+ // Only determine mime types for files here. For directories,
+ // KFileItem::determineMimeType() reads the .directory file inside to
+ // load the icon, but this is not necessary at all if we just need the
+ // type. Some special code for setting the correct mime type for
+ // directories is in retrieveData().
+ if (!item.isDir()) {
+ item.determineMimeType();
+ }
+
+ if (timer.elapsed() > timeout) {
+ // Don't block the user interface, let the remaining items
+ // be resolved asynchronously.
+ return;
+ }
+ }
+}
+
+QByteArray KFileItemModel::sharedValue(const QByteArray& value)
+{
+ static QSet<QByteArray> pool;
+ const QSet<QByteArray>::const_iterator it = pool.constFind(value);
+
+ if (it != pool.constEnd()) {
+ return *it;
+ } else {
+ pool.insert(value);
+ return value;
+ }
+}
+
+bool KFileItemModel::isConsistent() const
+{
+ // m_items may contain less items than m_itemData because m_items
+ // is populated lazily, see KFileItemModel::index(const QUrl& url).
+ if (m_items.count() > m_itemData.count()) {
+ return false;
+ }
+
+ for (int i = 0, iMax = count(); i < iMax; ++i) {
+ // Check if m_items and m_itemData are consistent.
+ const KFileItem item = fileItem(i);
+ if (item.isNull()) {
+ qCWarning(DolphinDebug) << "Item" << i << "is null";
+ return false;
+ }
+
+ const int itemIndex = index(item);
+ if (itemIndex != i) {
+ qCWarning(DolphinDebug) << "Item" << i << "has a wrong index:" << itemIndex;
+ return false;
+ }
+
+ // Check if the items are sorted correctly.
+ if (i > 0 && !lessThan(m_itemData.at(i - 1), m_itemData.at(i), m_collator)) {
+ qCWarning(DolphinDebug) << "The order of items" << i - 1 << "and" << i << "is wrong:"
+ << fileItem(i - 1) << fileItem(i);
+ return false;
+ }
+
+ // Check if all parent-child relationships are consistent.
+ const ItemData* data = m_itemData.at(i);
+ const ItemData* parent = data->parent;
+ if (parent) {
+ if (expandedParentsCount(data) != expandedParentsCount(parent) + 1) {
+ qCWarning(DolphinDebug) << "expandedParentsCount is inconsistent for parent" << parent->item << "and child" << data->item;
+ return false;
+ }
+
+ const int parentIndex = index(parent->item);
+ if (parentIndex >= i) {
+ qCWarning(DolphinDebug) << "Index" << parentIndex << "of parent" << parent->item << "is not smaller than index" << i << "of child" << data->item;
+ return false;
+ }
+ }
+ }
+
+ return true;
+}