┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dolphinviewcontainer.cpp15
-rw-r--r--src/dolphinviewcontainer.h4
-rw-r--r--src/kitemviews/kfileitemmodel.cpp50
-rw-r--r--src/kitemviews/kfileitemmodel.h21
-rw-r--r--src/kitemviews/kfileitemmodelrolesupdater.cpp99
-rw-r--r--src/kitemviews/kfileitemmodelrolesupdater.h21
-rw-r--r--src/kitemviews/knepomukrolesprovider.cpp4
-rw-r--r--src/kitemviews/knepomukrolesprovider_p.h4
-rw-r--r--src/statusbar/dolphinstatusbar.cpp2
-rw-r--r--src/views/dolphinview.cpp1
-rw-r--r--src/views/dolphinview.h4
11 files changed, 207 insertions, 18 deletions
diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp
index 28bf5250c..1c15c88a9 100644
--- a/src/dolphinviewcontainer.cpp
+++ b/src/dolphinviewcontainer.cpp
@@ -102,7 +102,8 @@ DolphinViewContainer::DolphinViewContainer(const KUrl& url, QWidget* parent) :
connect(m_view, SIGNAL(startedPathLoading(KUrl)), this, SLOT(slotStartedPathLoading()));
connect(m_view, SIGNAL(finishedPathLoading(KUrl)), this, SLOT(slotFinishedPathLoading()));
connect(m_view, SIGNAL(itemCountChanged()), this, SLOT(delayedStatusBarUpdate()));
- connect(m_view, SIGNAL(pathLoadingProgress(int)), this, SLOT(updateProgress(int)));
+ connect(m_view, SIGNAL(pathLoadingProgress(int)), this, SLOT(updateLoadingProgress(int)));
+ connect(m_view, SIGNAL(sortProgress(int)), this, SLOT(updateSortProgress(int)));
connect(m_view, SIGNAL(infoMessage(QString)), this, SLOT(showInfoMessage(QString)));
connect(m_view, SIGNAL(errorMessage(QString)), this, SLOT(showErrorMessage(QString)));
connect(m_view, SIGNAL(urlIsFileError(KUrl)), this, SLOT(openFile(KUrl)));
@@ -332,7 +333,7 @@ void DolphinViewContainer::updateStatusBar()
}
}
-void DolphinViewContainer::updateProgress(int percent)
+void DolphinViewContainer::updateLoadingProgress(int percent)
{
if (m_statusBar->progressText().isEmpty()) {
m_statusBar->setProgressText(i18nc("@info:progress", "Loading folder..."));
@@ -340,6 +341,14 @@ void DolphinViewContainer::updateProgress(int percent)
m_statusBar->setProgress(percent);
}
+void DolphinViewContainer::updateSortProgress(int percent)
+{
+ if (m_statusBar->progressText().isEmpty()) {
+ m_statusBar->setProgressText(i18nc("@info:progress", "Sorting..."));
+ }
+ m_statusBar->setProgress(percent);
+}
+
void DolphinViewContainer::slotStartedPathLoading()
{
if (isSearchUrl(url())) {
@@ -352,7 +361,7 @@ void DolphinViewContainer::slotStartedPathLoading()
// Trigger an undetermined progress indication. The progress
// information in percent will be triggered by the percent() signal
// of the directory lister later.
- updateProgress(-1);
+ updateLoadingProgress(-1);
}
}
diff --git a/src/dolphinviewcontainer.h b/src/dolphinviewcontainer.h
index 59b3c79ed..734021aa9 100644
--- a/src/dolphinviewcontainer.h
+++ b/src/dolphinviewcontainer.h
@@ -154,7 +154,9 @@ private slots:
*/
void updateStatusBar();
- void updateProgress(int percent);
+ void updateLoadingProgress(int percent);
+
+ void updateSortProgress(int percent);
/**
* Updates the statusbar to show an undetermined progress with the correct
diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp
index 7644ae5ef..685af8972 100644
--- a/src/kitemviews/kfileitemmodel.cpp
+++ b/src/kitemviews/kfileitemmodel.cpp
@@ -38,6 +38,7 @@ KFileItemModel::KFileItemModel(KDirLister* dirLister, QObject* parent) :
m_naturalSorting(KGlobalSettings::naturalSorting()),
m_sortFoldersFirst(true),
m_sortRole(NameRole),
+ m_sortProgressPercent(-1),
m_roles(),
m_caseSensitivity(Qt::CaseInsensitive),
m_itemData(),
@@ -878,6 +879,13 @@ void KFileItemModel::insertItems(const KFileItemList& items)
return;
}
+ if (m_sortRole == TypeRole) {
+ // Try to resolve the MIME-types synchronously to prevent a reordering of
+ // the items when sorting by type (per default MIME-types are resolved
+ // asynchronously by KFileItemModelRolesUpdater).
+ determineMimeTypes(items, 200);
+ }
+
#ifdef KFILEITEMMODEL_DEBUG
QElapsedTimer timer;
timer.start();
@@ -1829,6 +1837,34 @@ KFileItemList KFileItemModel::childItems(const KFileItem& item) const
return items;
}
+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_sortProgressPercent = -1;
+ if (m_resortAllItemsTimer->isActive()) {
+ m_resortAllItemsTimer->stop();
+ resortAllItems();
+ }
+
+ emit sortProgress(100);
+ } else if (itemCount > 0) {
+ resolvedCount = qBound(0, resolvedCount, itemCount);
+
+ const int progress = resolvedCount * 100 / itemCount;
+ if (m_sortProgressPercent != progress) {
+ m_sortProgressPercent = progress;
+ emit sortProgress(progress);
+ }
+ }
+}
+
const KFileItemModel::RoleInfoMap* KFileItemModel::rolesInfoMap(int& count)
{
static const RoleInfoMap rolesInfoMap[] = {
@@ -1861,4 +1897,18 @@ const KFileItemModel::RoleInfoMap* KFileItemModel::rolesInfoMap(int& count)
return rolesInfoMap;
}
+void KFileItemModel::determineMimeTypes(const KFileItemList& items, int timeout)
+{
+ QElapsedTimer timer;
+ timer.start();
+ foreach (KFileItem item, items) {
+ item.determineMimeType();
+ if (timer.elapsed() > timeout) {
+ // Don't block the user interface, let the remaining items
+ // be resolved asynchronously.
+ return;
+ }
+ }
+}
+
#include "kfileitemmodel.moc"
diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h
index 42cb15403..eaf35fecd 100644
--- a/src/kitemviews/kfileitemmodel.h
+++ b/src/kitemviews/kfileitemmodel.h
@@ -184,6 +184,13 @@ signals:
*/
void loadingCompleted();
+ /**
+ * Is emitted if the sort-role gets resolved asynchronously and provides
+ * the progress-information of the sorting in percent. It is assured
+ * that the last sortProgress-signal contains 100 as value.
+ */
+ void sortProgress(int percent);
+
protected:
virtual void onGroupedSortingChanged(bool current);
virtual void onSortRoleChanged(const QByteArray& current, const QByteArray& previous);
@@ -317,6 +324,12 @@ private:
KFileItemList childItems(const KFileItem& item) const;
/**
+ * Is invoked by KFileItemModelRolesUpdater and results in emitting the
+ * sortProgress signal with a percent-value of the progress.
+ */
+ void emitSortProgress(int resolvedCount);
+
+ /**
* Maps the QByteArray-roles to RoleTypes and provides translation- and
* group-contexts.
*/
@@ -337,6 +350,12 @@ private:
*/
static const RoleInfoMap* rolesInfoMap(int& count);
+ /**
+ * Determines the MIME-types of all items that can be done within
+ * the given timeout.
+ */
+ static void determineMimeTypes(const KFileItemList& items, int timeout);
+
private:
QWeakPointer<KDirLister> m_dirLister;
@@ -344,6 +363,7 @@ private:
bool m_sortFoldersFirst;
RoleType m_sortRole;
+ int m_sortProgressPercent; // Value of sortProgress() signal
QSet<QByteArray> m_roles;
Qt::CaseSensitivity m_caseSensitivity;
@@ -385,6 +405,7 @@ private:
QSet<KUrl> m_urlsToExpand;
friend class KFileItemModelSortAlgorithm; // Accesses lessThan() method
+ friend class KFileItemModelRolesUpdater; // Accesses emitSortProgress() method
friend class KFileItemModelTest; // For unit testing
};
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()) {
diff --git a/src/kitemviews/kfileitemmodelrolesupdater.h b/src/kitemviews/kfileitemmodelrolesupdater.h
index e5e105e04..ce8cf1c73 100644
--- a/src/kitemviews/kfileitemmodelrolesupdater.h
+++ b/src/kitemviews/kfileitemmodelrolesupdater.h
@@ -128,6 +128,8 @@ private slots:
void slotItemsRemoved(const KItemRangeList& itemRanges);
void slotItemsChanged(const KItemRangeList& itemRanges,
const QSet<QByteArray>& roles);
+ void slotSortRoleChanged(const QByteArray& current,
+ const QByteArray& previous);
/**
* Is invoked after a preview has been received successfully.
@@ -180,6 +182,22 @@ private:
void resetPendingRoles();
void sortAndResolveAllRoles();
void sortAndResolvePendingRoles();
+ void applySortProgressToModel();
+
+ /**
+ * Updates m_sortProgress to be 0 if the sort-role
+ * needs to get resolved asynchronously and hence a
+ * progress is required. Otherwise m_sortProgress
+ * will be set to -1 which means that no progress
+ * will be provided.
+ */
+ void updateSortProgress();
+
+ /**
+ * @return True, if at least one item from the model
+ * has an unknown MIME-type.
+ */
+ bool hasUnknownMimeTypes() const;
enum ResolveHint {
ResolveFast,
@@ -222,11 +240,14 @@ private:
// during the roles-updater has been paused by setPaused().
bool m_clearPreviews;
+ int m_sortProgress;
+
KFileItemModel* m_model;
QSize m_iconSize;
int m_firstVisibleIndex;
int m_lastVisibleIndex;
QSet<QByteArray> m_roles;
+ QSet<QByteArray> m_resolvableRoles;
QStringList m_enabledPlugins;
QSet<KFileItem> m_pendingVisibleItems;
diff --git a/src/kitemviews/knepomukrolesprovider.cpp b/src/kitemviews/knepomukrolesprovider.cpp
index ac371e189..25fb16121 100644
--- a/src/kitemviews/knepomukrolesprovider.cpp
+++ b/src/kitemviews/knepomukrolesprovider.cpp
@@ -44,9 +44,9 @@ KNepomukRolesProvider::~KNepomukRolesProvider()
{
}
-bool KNepomukRolesProvider::isNepomukRole(const QByteArray& role) const
+QSet<QByteArray> KNepomukRolesProvider::roles() const
{
- return m_roles.contains(role);
+ return m_roles;
}
QHash<QByteArray, QVariant> KNepomukRolesProvider::roleValues(const Nepomuk::Resource& resource,
diff --git a/src/kitemviews/knepomukrolesprovider_p.h b/src/kitemviews/knepomukrolesprovider_p.h
index c7781cd00..46a78d4ee 100644
--- a/src/kitemviews/knepomukrolesprovider_p.h
+++ b/src/kitemviews/knepomukrolesprovider_p.h
@@ -44,9 +44,9 @@ public:
virtual ~KNepomukRolesProvider();
/**
- * @return True if the values of the role can be determined by Nepomuk.
+ * @return Roles that can be provided by KNepomukRolesProvider.
*/
- bool isNepomukRole(const QByteArray& role) const;
+ QSet<QByteArray> roles() const;
/**
* @return Values for the roles \a roles that can be determined from the file
diff --git a/src/statusbar/dolphinstatusbar.cpp b/src/statusbar/dolphinstatusbar.cpp
index b01f6042c..71e86dd60 100644
--- a/src/statusbar/dolphinstatusbar.cpp
+++ b/src/statusbar/dolphinstatusbar.cpp
@@ -96,7 +96,7 @@ DolphinStatusBar::DolphinStatusBar(QWidget* parent, DolphinView* view) :
m_progressBar->hide();
m_showProgressBarTimer = new QTimer(this);
- m_showProgressBarTimer->setInterval(1000);
+ m_showProgressBarTimer->setInterval(200);
m_showProgressBarTimer->setSingleShot(true);
connect(m_showProgressBarTimer, SIGNAL(timeout()), this, SLOT(updateProgressInfo()));
diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp
index 872853642..2ffc33e08 100644
--- a/src/views/dolphinview.cpp
+++ b/src/views/dolphinview.cpp
@@ -158,6 +158,7 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) :
KFileItemModel* model = fileItemModel();
if (model) {
connect(model, SIGNAL(loadingCompleted()), this, SLOT(slotLoadingCompleted()));
+ connect(model, SIGNAL(sortProgress(int)), this, SIGNAL(sortProgress(int)));
}
KItemListView* view = controller->view();
diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h
index 130657b16..b1d057e6f 100644
--- a/src/views/dolphinview.h
+++ b/src/views/dolphinview.h
@@ -492,6 +492,8 @@ signals:
*/
void pathLoadingProgress(int percent);
+ void sortProgress(int percent);
+
/**
* Is emitted if the DolphinView::setUrl() is invoked but the URL is not
* a directory.
@@ -670,8 +672,6 @@ private slots:
void hideToolTip();
- //void slotUrlChangeRequested(const KUrl& url);
-
private:
KFileItemModel* fileItemModel() const;