┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/kitemviews/kfileitemmodelrolesupdater.cpp
diff options
context:
space:
mode:
authorPeter Penz <[email protected]>2012-04-10 16:30:50 +0200
committerPeter Penz <[email protected]>2012-04-10 16:36:26 +0200
commitd9dbd3398a258d04ec4517fd13e795b437c869d6 (patch)
tree6f608d12001818cd416271ac7c4f462e9ddefc7a /src/kitemviews/kfileitemmodelrolesupdater.cpp
parentb8c3d933e66598c78180a73cb394b211ca6b52d0 (diff)
Improvements for slow sorting roles
If the sorting is done for data which is resolved asynchronously (e.g. rating), it is important to give a visual feedback about the state of the sorting. This is done now by a progress indication in the statusbar. Also optimizations for "Sort by type" have been done: Although resolving a type can be expensive in the most often case it is a very cheap operation. So it the sorting is done by type, try to resolve the type synchronously for at least 200 ms to prevent a asynchronous resorting. This is usually sufficient to have resolved types even for directories with several thousands of items. BUG: 292733 FIXED-IN: 4.9.0
Diffstat (limited to 'src/kitemviews/kfileitemmodelrolesupdater.cpp')
-rw-r--r--src/kitemviews/kfileitemmodelrolesupdater.cpp99
1 files changed, 92 insertions, 7 deletions
diff --git a/src/kitemviews/kfileitemmodelrolesupdater.cpp b/src/kitemviews/kfileitemmodelrolesupdater.cpp
index 34165843f..632df676d 100644
--- a/src/kitemviews/kfileitemmodelrolesupdater.cpp
+++ b/src/kitemviews/kfileitemmodelrolesupdater.cpp
@@ -69,6 +69,7 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO
m_previewShown(false),
m_enlargeSmallPreviews(true),
m_clearPreviews(false),
+ m_sortProgress(-1),
m_model(model),
m_iconSize(),
m_firstVisibleIndex(0),
@@ -100,6 +101,8 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO
this, SLOT(slotItemsRemoved(KItemRangeList)));
connect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
this, SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
+ connect(m_model, SIGNAL(sortRoleChanged(QByteArray,QByteArray)),
+ this, SLOT(slotSortRoleChanged(QByteArray,QByteArray)));
// Use a timer to prevent that each call of slotItemsChanged() results in a synchronous
// resolving of the roles. Postpone the resolving until no update has been done for 1 second.
@@ -107,6 +110,13 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO
m_changedItemsTimer->setInterval(1000);
m_changedItemsTimer->setSingleShot(true);
connect(m_changedItemsTimer, SIGNAL(timeout()), this, SLOT(resolveChangedItems()));
+
+ m_resolvableRoles.insert("size");
+ m_resolvableRoles.insert("type");
+ m_resolvableRoles.insert("isExpandable");
+#ifdef HAVE_NEPOMUK
+ m_resolvableRoles += KNepomukRolesProvider::instance().roles();
+#endif
}
KFileItemModelRolesUpdater::~KFileItemModelRolesUpdater()
@@ -245,7 +255,7 @@ void KFileItemModelRolesUpdater::setRoles(const QSet<QByteArray>& roles)
QSetIterator<QByteArray> it(roles);
while (it.hasNext()) {
const QByteArray& role = it.next();
- if (rolesProvider.isNepomukRole(role)) {
+ if (rolesProvider.roles().contains(role)) {
hasNepomukRole = true;
break;
}
@@ -270,6 +280,8 @@ void KFileItemModelRolesUpdater::setRoles(const QSet<QByteArray>& roles)
}
#endif
+ updateSortProgress();
+
if (m_paused) {
m_rolesChangedDuringPausing = true;
} else {
@@ -378,6 +390,14 @@ void KFileItemModelRolesUpdater::slotItemsChanged(const KItemRangeList& itemRang
m_changedItemsTimer->start();
}
+void KFileItemModelRolesUpdater::slotSortRoleChanged(const QByteArray& current,
+ const QByteArray& previous)
+{
+ Q_UNUSED(current);
+ Q_UNUSED(previous);
+ updateSortProgress();
+}
+
void KFileItemModelRolesUpdater::slotGotPreview(const KFileItem& item, const QPixmap& pixmap)
{
m_pendingVisibleItems.remove(item);
@@ -434,6 +454,8 @@ void KFileItemModelRolesUpdater::slotGotPreview(const KFileItem& item, const QPi
m_model->setData(index, data);
connect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
this, SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
+
+ applySortProgressToModel();
}
void KFileItemModelRolesUpdater::slotPreviewFailed(const KFileItem& item)
@@ -445,6 +467,8 @@ void KFileItemModelRolesUpdater::slotPreviewFailed(const KFileItem& item)
m_clearPreviews = true;
applyResolvedRoles(item, ResolveAll);
m_clearPreviews = clearPreviews;
+
+ applySortProgressToModel();
}
void KFileItemModelRolesUpdater::slotPreviewJobFinished(KJob* job)
@@ -494,6 +518,8 @@ void KFileItemModelRolesUpdater::resolveNextPendingRoles()
m_clearPreviews = false;
}
+ applySortProgressToModel();
+
#ifdef KFILEITEMMODELROLESUPDATER_DEBUG
static int callCount = 0;
++callCount;
@@ -648,10 +674,17 @@ void KFileItemModelRolesUpdater::resolvePendingRoles()
{
int resolvedCount = 0;
- const bool hasSlowRoles = m_previewShown
- || m_roles.contains("size")
- || m_roles.contains("type")
- || m_roles.contains("isExpandable");
+ bool hasSlowRoles = m_previewShown;
+ if (!hasSlowRoles) {
+ QSetIterator<QByteArray> it(m_roles);
+ while (it.hasNext()) {
+ if (m_resolvableRoles.contains(it.next())) {
+ hasSlowRoles = true;
+ break;
+ }
+ }
+ }
+
const ResolveHint resolveHint = hasSlowRoles ? ResolveFast : ResolveAll;
// Resolving the MIME type can be expensive. Assure that not more than MaxBlockTimeout ms are
@@ -664,12 +697,12 @@ void KFileItemModelRolesUpdater::resolvePendingRoles()
QSetIterator<KFileItem> visibleIt(m_pendingVisibleItems);
while (visibleIt.hasNext()) {
const KFileItem item = visibleIt.next();
- applyResolvedRoles(item, resolveHint);
if (!hasSlowRoles) {
Q_ASSERT(!m_pendingInvisibleItems.contains(item));
- // All roles have been resolved already by applyResolvedRoles()
+ // All roles will be resolved by applyResolvedRoles()
m_pendingVisibleItems.remove(item);
}
+ applyResolvedRoles(item, resolveHint);
++resolvedCount;
if (timer.elapsed() > MaxBlockTimeout) {
@@ -720,6 +753,8 @@ void KFileItemModelRolesUpdater::resolvePendingRoles()
}
kDebug() << "[TIME] Resolved pending roles:" << timer.elapsed();
#endif
+
+ applySortProgressToModel();
}
void KFileItemModelRolesUpdater::resetPendingRoles()
@@ -812,6 +847,56 @@ void KFileItemModelRolesUpdater::sortAndResolvePendingRoles()
resolvePendingRoles();
}
+void KFileItemModelRolesUpdater::applySortProgressToModel()
+{
+ if (m_sortProgress < 0) {
+ return;
+ }
+
+ // Inform the model about the progress of the resolved items,
+ // so that it can give an indication when the sorting has been finished.
+ const int resolvedCount = m_model->count()
+ - m_pendingVisibleItems.count()
+ - m_pendingInvisibleItems.count();
+ if (resolvedCount > 0) {
+ m_model->emitSortProgress(resolvedCount);
+ if (resolvedCount == m_model->count()) {
+ m_sortProgress = -1;
+ }
+ }
+}
+
+void KFileItemModelRolesUpdater::updateSortProgress()
+{
+ const QByteArray sortRole = m_model->sortRole();
+
+ // Optimization if the sorting is done by type: In case if all MIME-types
+ // are known, the types have been resolved already by KFileItemModel and
+ // no sort-progress feedback is required.
+ const bool showProgress = (sortRole == "type")
+ ? hasUnknownMimeTypes()
+ : m_resolvableRoles.contains(sortRole);
+
+ if (m_sortProgress >= 0) {
+ // Mark the current sorting as finished
+ m_model->emitSortProgress(m_model->count());
+ }
+ m_sortProgress = showProgress ? 0 : -1;
+}
+
+bool KFileItemModelRolesUpdater::hasUnknownMimeTypes() const
+{
+ const int count = m_model->count();
+ for (int i = 0; i < count; ++i) {
+ const KFileItem item = m_model->fileItem(i);
+ if (!item.isMimeTypeKnown()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool KFileItemModelRolesUpdater::applyResolvedRoles(const KFileItem& item, ResolveHint hint)
{
if (item.isNull()) {