┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/kitemviews/kfileitemmodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/kitemviews/kfileitemmodel.cpp')
-rw-r--r--src/kitemviews/kfileitemmodel.cpp141
1 files changed, 78 insertions, 63 deletions
diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp
index 87006718a..fd773e1e9 100644
--- a/src/kitemviews/kfileitemmodel.cpp
+++ b/src/kitemviews/kfileitemmodel.cpp
@@ -21,7 +21,6 @@
#include "kfileitemmodel.h"
-#include <KDirModel>
#include <KGlobalSettings>
#include <KLocale>
#include <KStringHandler>
@@ -76,7 +75,6 @@ KFileItemModel::KFileItemModel(QObject* parent) :
connect(m_dirLister, SIGNAL(itemsDeleted(KFileItemList)), this, SLOT(slotItemsDeleted(KFileItemList)));
connect(m_dirLister, SIGNAL(refreshItems(QList<QPair<KFileItem,KFileItem> >)), this, SLOT(slotRefreshItems(QList<QPair<KFileItem,KFileItem> >)));
connect(m_dirLister, SIGNAL(clear()), this, SLOT(slotClear()));
- connect(m_dirLister, SIGNAL(clear(KUrl)), this, SLOT(slotClear(KUrl)));
connect(m_dirLister, SIGNAL(infoMessage(QString)), this, SIGNAL(infoMessage(QString)));
connect(m_dirLister, SIGNAL(errorMessage(QString)), this, SIGNAL(errorMessage(QString)));
connect(m_dirLister, SIGNAL(redirection(KUrl,KUrl)), this, SIGNAL(directoryRedirection(KUrl,KUrl)));
@@ -247,9 +245,23 @@ QMimeData* KFileItemModel::createMimeData(const KItemSet& indexes) const
KUrl::List urls;
KUrl::List mostLocalUrls;
bool canUseMostLocalUrls = true;
+ const ItemData* lastAddedItem = 0;
foreach (int index, indexes) {
- const KFileItem item = fileItem(index);
+ const ItemData* itemData = m_itemData.at(index);
+ const ItemData* parent = itemData->parent;
+
+ while (parent && parent != lastAddedItem) {
+ parent = parent->parent;
+ }
+
+ if (parent && parent == lastAddedItem) {
+ // A parent of 'itemData' has been added already.
+ continue;
+ }
+
+ lastAddedItem = itemData;
+ const KFileItem& item = itemData->item;
if (!item.isNull()) {
urls << item.targetUrl();
@@ -262,9 +274,7 @@ QMimeData* KFileItemModel::createMimeData(const KItemSet& indexes) const
}
const bool different = canUseMostLocalUrls && mostLocalUrls != urls;
- urls = KDirModel::simplifiedUrlList(urls); // TODO: Check if we still need KDirModel for this in KDE 5.0
if (different) {
- mostLocalUrls = KDirModel::simplifiedUrlList(mostLocalUrls);
urls.populateMimeData(mostLocalUrls, data);
} else {
urls.populateMimeData(data);
@@ -344,27 +354,50 @@ KFileItem KFileItemModel::fileItem(int index) const
KFileItem KFileItemModel::fileItem(const KUrl& url) const
{
- const int index = m_items.value(url, -1);
- if (index >= 0) {
- return m_itemData.at(index)->item;
+ const int indexForUrl = index(url);
+ if (indexForUrl >= 0) {
+ return m_itemData.at(indexForUrl)->item;
}
return KFileItem();
}
int KFileItemModel::index(const KFileItem& item) const
{
- if (item.isNull()) {
- return -1;
- }
-
- return m_items.value(item.url(), -1);
+ return index(item.url());
}
int KFileItemModel::index(const KUrl& url) const
{
KUrl urlToFind = url;
urlToFind.adjustPath(KUrl::RemoveTrailingSlash);
- return m_items.value(urlToFind, -1);
+
+ const int itemCount = m_itemData.count();
+ int itemsInHash = m_items.count();
+
+ int index = m_items.value(urlToFind, -1);
+ while (index < 0 && itemsInHash < itemCount) {
+ // Not all URLs are stored yet in m_items. We grow m_items until either
+ // urlToFind is found, or all URLs have been stored in m_items.
+ // Note that we do not add the URLs to m_items one by one, but in
+ // larger blocks. After each block, we check if urlToFind is in
+ // m_items. We could in principle compare urlToFind with each URL while
+ // we are going through m_itemData, but comparing two QUrls will,
+ // unlike calling qHash for the URLs, trigger a parsing of the URLs
+ // which costs both CPU cycles and memory.
+ const int blockSize = 1000;
+ const int currentBlockEnd = qMin(itemsInHash + blockSize, itemCount);
+ for (int i = itemsInHash; i < currentBlockEnd; ++i) {
+ const KUrl nextUrl = m_itemData.at(i)->item.url();
+ m_items.insert(nextUrl, i);
+ }
+
+ itemsInHash = currentBlockEnd;
+ index = m_items.value(urlToFind, -1);
+ }
+
+ Q_ASSERT(index >= 0 || m_items.count() == m_itemData.count());
+
+ return index;
}
KFileItem KFileItemModel::rootItem() const
@@ -662,7 +695,7 @@ QList<KFileItemModel::RoleInfo> KFileItemModel::rolesInformation()
// menus tries to put the actions into sub menus otherwise.
info.group = QString();
}
- info.requiresNepomuk = map[i].requiresNepomuk;
+ info.requiresBaloo = map[i].requiresBaloo;
info.requiresIndexer = map[i].requiresIndexer;
rolesInfo.append(info);
}
@@ -725,6 +758,7 @@ void KFileItemModel::resortAllItems()
}
m_items.clear();
+ m_items.reserve(itemCount);
// Resort the items
sort(m_itemData.begin(), m_itemData.end());
@@ -787,10 +821,10 @@ void KFileItemModel::slotCompleted()
// Therefore, some URLs in m_restoredExpandedUrls might not be visible yet
// -> we expand the first visible URL we find in m_restoredExpandedUrls.
foreach (const KUrl& url, m_urlsToExpand) {
- const int index = m_items.value(url, -1);
- if (index >= 0) {
+ const int indexForUrl = index(url);
+ if (indexForUrl >= 0) {
m_urlsToExpand.remove(url);
- if (setExpanded(index, true)) {
+ if (setExpanded(indexForUrl, true)) {
// The dir lister has been triggered. This slot will be called
// again after the directory has been expanded.
return;
@@ -827,15 +861,12 @@ void KFileItemModel::slotItemsAdded(const KUrl& directoryUrl, const KFileItemLis
}
if (m_requestRole[ExpandedParentsCountRole]) {
- KFileItem item = items.first();
-
// If the expanding of items is enabled, the call
// dirLister->openUrl(url, KDirLister::Keep) in KFileItemModel::setExpanded()
// might result in emitting the same items twice due to the Keep-parameter.
// This case happens if an item gets expanded, collapsed and expanded again
// before the items could be loaded for the first expansion.
- const int index = m_items.value(item.url(), -1);
- if (index >= 0) {
+ if (index(items.first().url()) >= 0) {
// The items are already part of the model.
return;
}
@@ -849,7 +880,7 @@ void KFileItemModel::slotItemsAdded(const KUrl& directoryUrl, const KFileItemLis
// KDirLister keeps the children of items that got expanded once even if
// they got collapsed again with KFileItemModel::setExpanded(false). So it must be
// checked whether the parent for new items is still expanded.
- const int parentIndex = m_items.value(parentUrl, -1);
+ const int parentIndex = index(parentUrl);
if (parentIndex >= 0 && !m_itemData[parentIndex]->values.value("isExpanded").toBool()) {
// The parent is not expanded.
return;
@@ -888,10 +919,9 @@ void KFileItemModel::slotItemsDeleted(const KFileItemList& items)
indexesToRemove.reserve(items.count());
foreach (const KFileItem& item, items) {
- const KUrl url = item.url();
- const int index = m_items.value(url, -1);
- if (index >= 0) {
- indexesToRemove.append(index);
+ const int indexForItem = index(item);
+ if (indexForItem >= 0) {
+ indexesToRemove.append(indexForItem);
} else {
// Probably the item has been filtered.
QHash<KFileItem, ItemData*>::iterator it = m_filteredItems.find(item);
@@ -907,7 +937,7 @@ void KFileItemModel::slotItemsDeleted(const KFileItemList& items)
if (m_requestRole[ExpandedParentsCountRole] && !m_expandedDirs.isEmpty()) {
// Assure that removing a parent item also results in removing all children
QVector<int> indexesToRemoveWithChildren;
- indexesToRemoveWithChildren.reserve(m_items.count());
+ indexesToRemoveWithChildren.reserve(m_itemData.count());
const int itemCount = m_itemData.count();
foreach (int index, indexesToRemove) {
@@ -947,14 +977,14 @@ void KFileItemModel::slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >&
const QPair<KFileItem, KFileItem>& itemPair = it.next();
const KFileItem& oldItem = itemPair.first;
const KFileItem& newItem = itemPair.second;
- const int index = m_items.value(oldItem.url(), -1);
- if (index >= 0) {
- m_itemData[index]->item = newItem;
+ const int indexForItem = index(oldItem);
+ if (indexForItem >= 0) {
+ m_itemData[indexForItem]->item = newItem;
// Keep old values as long as possible if they could not retrieved synchronously yet.
// The update of the values will be done asynchronously by KFileItemModelRolesUpdater.
- QHashIterator<QByteArray, QVariant> it(retrieveData(newItem, m_itemData.at(index)->parent));
- QHash<QByteArray, QVariant>& values = m_itemData[index]->values;
+ QHashIterator<QByteArray, QVariant> it(retrieveData(newItem, m_itemData.at(indexForItem)->parent));
+ QHash<QByteArray, QVariant>& values = m_itemData[indexForItem]->values;
while (it.hasNext()) {
it.next();
const QByteArray& role = it.key();
@@ -965,8 +995,8 @@ void KFileItemModel::slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >&
}
m_items.remove(oldItem.url());
- m_items.insert(newItem.url(), index);
- indexes.append(index);
+ m_items.insert(newItem.url(), indexForItem);
+ indexes.append(indexForItem);
} else {
// Check if 'oldItem' is one of the filtered items.
QHash<KFileItem, ItemData*>::iterator it = m_filteredItems.find(oldItem);
@@ -1023,11 +1053,6 @@ void KFileItemModel::slotClear()
m_expandedDirs.clear();
}
-void KFileItemModel::slotClear(const KUrl& url)
-{
- Q_UNUSED(url);
-}
-
void KFileItemModel::slotNaturalSortingChanged()
{
m_naturalSorting = KGlobalSettings::naturalSorting();
@@ -1088,7 +1113,7 @@ void KFileItemModel::insertItems(QList<ItemData*>& newItems)
m_itemData.append(0);
}
- // We build the new list m_items in reverse order to minimize
+ // We build the new list m_itemData in reverse order to minimize
// the number of moves and guarantee O(N) complexity.
int targetIndex = totalItemCount - 1;
int sourceIndexExistingItems = existingItemCount - 1;
@@ -1126,11 +1151,9 @@ void KFileItemModel::insertItems(QList<ItemData*>& newItems)
std::reverse(itemRanges.begin(), itemRanges.end());
}
- // The indexes starting from the first inserted item must be adjusted.
- m_items.reserve(totalItemCount);
- for (int i = itemRanges.front().index; i < totalItemCount; ++i) {
- m_items.insert(m_itemData.at(i)->item.url(), i);
- }
+ // 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 KUrl&) is called.
+ m_items.clear();
emit itemsInserted(itemRanges);
@@ -1147,19 +1170,12 @@ void KFileItemModel::removeItems(const KItemRangeList& itemRanges, RemoveItemsBe
m_groups.clear();
- // Step 1: Remove the items from the hash m_items, and free the ItemData.
+ // Step 1: Remove the items from m_itemData, and free the ItemData.
int removedItemsCount = 0;
foreach (const KItemRange& range, itemRanges) {
removedItemsCount += range.count;
for (int index = range.index; index < range.index + range.count; ++index) {
- const KUrl url = m_itemData.at(index)->item.url();
-
- // Prevent repeated expensive rehashing by using QHash::erase(),
- // rather than QHash::remove().
- QHash<KUrl, int>::iterator it = m_items.find(url);
- m_items.erase(it);
-
if (behavior == DeleteItemData) {
delete m_itemData.at(index);
}
@@ -1188,12 +1204,9 @@ void KFileItemModel::removeItems(const KItemRangeList& itemRanges, RemoveItemsBe
m_itemData.erase(m_itemData.end() - removedItemsCount, m_itemData.end());
- // Step 3: Adjust indexes in the hash m_items, starting from the
- // index of the first removed item.
- const int newItemDataCount = m_itemData.count();
- for (int i = itemRanges.front().index; i < newItemDataCount; ++i) {
- m_items.insert(m_itemData.at(i)->item.url(), i);
- }
+ // 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 KUrl&) is called.
+ m_items.clear();
emit itemsRemoved(itemRanges);
}
@@ -1207,7 +1220,7 @@ QList<KFileItemModel::ItemData*> KFileItemModel::createItemDataList(const KUrl&
determineMimeTypes(items, 200);
}
- const int parentIndex = m_items.value(parentUrl, -1);
+ const int parentIndex = index(parentUrl);
ItemData* parentItem = parentIndex < 0 ? 0 : m_itemData.at(parentIndex);
QList<ItemData*> itemDataList;
@@ -2070,7 +2083,7 @@ void KFileItemModel::emitSortProgress(int resolvedCount)
const KFileItemModel::RoleInfoMap* KFileItemModel::rolesInfoMap(int& count)
{
static const RoleInfoMap rolesInfoMap[] = {
- // | role | roleType | role translation | group translation | requires Nepomuk | requires indexer
+ // | role | roleType | role translation | group translation | requires Baloo | requires indexer
{ 0, NoRole, 0, 0, 0, 0, false, false },
{ "text", NameRole, I18N_NOOP2_NOSTRIP("@label", "Name"), 0, 0, false, false },
{ "size", SizeRole, I18N_NOOP2_NOSTRIP("@label", "Size"), 0, 0, false, false },
@@ -2136,7 +2149,9 @@ QByteArray KFileItemModel::sharedValue(const QByteArray& value)
bool KFileItemModel::isConsistent() const
{
- if (m_items.count() != m_itemData.count()) {
+ // m_items may contain less items than m_itemData because m_items
+ // is populated lazily, see KFileItemModel::index(const KUrl& url).
+ if (m_items.count() > m_itemData.count()) {
return false;
}