diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 48ea14c18e..7710ddf928 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,6 +53,7 @@ set(dolphinprivate_LIB_SRCS kitemviews/kitemlistviewaccessible.cpp kitemviews/kitemlistwidget.cpp kitemviews/kitemmodelbase.cpp + kitemviews/kitemset.cpp kitemviews/kstandarditem.cpp kitemviews/kstandarditemlistgroupheader.cpp kitemviews/kstandarditemlistwidget.cpp diff --git a/src/kitemviews/kfileitemlistview.cpp b/src/kitemviews/kfileitemlistview.cpp index 8950c9a1ee..fd01f2c4c2 100644 --- a/src/kitemviews/kfileitemlistview.cpp +++ b/src/kitemviews/kfileitemlistview.cpp @@ -119,7 +119,7 @@ QStringList KFileItemListView::enabledPlugins() const return m_modelRolesUpdater ? m_modelRolesUpdater->enabledPlugins() : QStringList(); } -QPixmap KFileItemListView::createDragPixmap(const QSet& indexes) const +QPixmap KFileItemListView::createDragPixmap(const KItemSet& indexes) const { if (!model()) { return QPixmap(); @@ -165,10 +165,8 @@ QPixmap KFileItemListView::createDragPixmap(const QSet& indexes) const QPainter painter(&dragPixmap); int x = 0; int y = 0; - QSetIterator it(indexes); - while (it.hasNext()) { - const int index = it.next(); + foreach (int index, indexes) { QPixmap pixmap = model()->data(index).value("iconPixmap").value(); if (pixmap.isNull()) { KIcon icon(model()->data(index).value("iconName").toString()); diff --git a/src/kitemviews/kfileitemlistview.h b/src/kitemviews/kfileitemlistview.h index bdc63b01bd..2fd21edbfd 100644 --- a/src/kitemviews/kfileitemlistview.h +++ b/src/kitemviews/kfileitemlistview.h @@ -73,7 +73,7 @@ public: QStringList enabledPlugins() const; /** @reimp */ - virtual QPixmap createDragPixmap(const QSet& indexes) const; + virtual QPixmap createDragPixmap(const KItemSet& indexes) const; protected: virtual KItemListWidgetCreatorBase* defaultWidgetCreator() const; diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index e2d0413a26..261b23046d 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -237,7 +237,7 @@ bool KFileItemModel::showDirectoriesOnly() const return m_dirLister->dirOnlyMode(); } -QMimeData* KFileItemModel::createMimeData(const QSet& indexes) const +QMimeData* KFileItemModel::createMimeData(const KItemSet& indexes) const { QMimeData* data = new QMimeData(); @@ -248,9 +248,7 @@ QMimeData* KFileItemModel::createMimeData(const QSet& indexes) const KUrl::List mostLocalUrls; bool canUseMostLocalUrls = true; - QSetIterator it(indexes); - while (it.hasNext()) { - const int index = it.next(); + foreach (int index, indexes) { const KFileItem item = fileItem(index); if (!item.isNull()) { urls << item.targetUrl(); diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h index 4b50477d98..c57329fc85 100644 --- a/src/kitemviews/kfileitemmodel.h +++ b/src/kitemviews/kfileitemmodel.h @@ -27,6 +27,7 @@ #include #include +#include class KFileItemModelDirLister; class QTimer; @@ -99,7 +100,7 @@ public: bool showDirectoriesOnly() const; /** @reimp */ - virtual QMimeData* createMimeData(const QSet& indexes) const; + virtual QMimeData* createMimeData(const KItemSet& indexes) const; /** @reimp */ virtual int indexForKeyboardSearch(const QString& text, int startFromIndex = 0) const; diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index befb09713e..51a1f91b91 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -364,11 +364,11 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) case Qt::Key_Enter: case Qt::Key_Return: { - const QSet selectedItems = m_selectionManager->selectedItems(); + const KItemSet selectedItems = m_selectionManager->selectedItems(); if (selectedItems.count() >= 2) { emit itemsActivated(selectedItems); } else if (selectedItems.count() == 1) { - emit itemActivated(selectedItems.toList().first()); + emit itemActivated(selectedItems.first()); } else { emit itemActivated(index); } @@ -378,14 +378,14 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) case Qt::Key_Menu: { // Emit the signal itemContextMenuRequested() in case if at least one // item is selected. Otherwise the signal viewContextMenuRequested() will be emitted. - const QSet selectedItems = m_selectionManager->selectedItems(); + const KItemSet selectedItems = m_selectionManager->selectedItems(); int index = -1; if (selectedItems.count() >= 2) { const int currentItemIndex = m_selectionManager->currentItem(); index = selectedItems.contains(currentItemIndex) - ? currentItemIndex : selectedItems.toList().first(); + ? currentItemIndex : selectedItems.first(); } else if (selectedItems.count() == 1) { - index = selectedItems.toList().first(); + index = selectedItems.first(); } if (index >= 0) { @@ -1079,7 +1079,7 @@ void KItemListController::slotRubberBandChanged() } } - QSet selectedItems; + KItemSet selectedItems; // Select all visible items that intersect with the rubberband foreach (const KItemListWidget* widget, m_view->visibleItemListWidgets()) { @@ -1127,7 +1127,7 @@ void KItemListController::slotRubberBandChanged() // Therefore, the new selection contains: // 1. All previously selected items which are not inside the rubberband, and // 2. all items inside the rubberband which have not been selected previously. - m_selectionManager->setSelectedItems((m_oldSelection - selectedItems) + (selectedItems - m_oldSelection)); + m_selectionManager->setSelectedItems(m_oldSelection ^ selectedItems); } else { m_selectionManager->setSelectedItems(selectedItems + m_oldSelection); @@ -1140,7 +1140,7 @@ void KItemListController::startDragging() return; } - const QSet selectedItems = m_selectionManager->selectedItems(); + const KItemSet selectedItems = m_selectionManager->selectedItems(); if (selectedItems.isEmpty()) { return; } diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h index bb72856e0c..e9b70cddaf 100644 --- a/src/kitemviews/kitemlistcontroller.h +++ b/src/kitemviews/kitemlistcontroller.h @@ -25,10 +25,11 @@ #include +#include "kitemset.h" + #include #include #include -#include class KItemModelBase; class KItemListKeyboardSearchManager; @@ -129,7 +130,7 @@ public: /** * If set to true, the signals itemActivated() and itemsActivated() are emitted - * after a single-click of the left mouse button. If set to false (the default), + * after a single-click of the left mouse button. If set to false (the default), * the setting from KGlobalSettings::singleClick() is used. */ void setSingleClickActivationEnforced(bool singleClick); @@ -165,7 +166,7 @@ signals: * Is emitted if more than one item has been activated by pressing Return/Enter * when having a selection. */ - void itemsActivated(const QSet& indexes); + void itemsActivated(const KItemSet& indexes); void itemMiddleClicked(int index); @@ -326,7 +327,7 @@ private: * the current selection it is remembered in m_oldSelection before the * rubberband gets activated. */ - QSet m_oldSelection; + KItemSet m_oldSelection; /** * Assuming a view is given with a vertical scroll-orientation, grouped items and diff --git a/src/kitemviews/kitemlistselectionmanager.cpp b/src/kitemviews/kitemlistselectionmanager.cpp index 833f7aad07..ebff1a30ed 100644 --- a/src/kitemviews/kitemlistselectionmanager.cpp +++ b/src/kitemviews/kitemlistselectionmanager.cpp @@ -43,7 +43,7 @@ KItemListSelectionManager::~KItemListSelectionManager() void KItemListSelectionManager::setCurrentItem(int current) { const int previous = m_currentItem; - const QSet previousSelection = selectedItems(); + const KItemSet previousSelection = selectedItems(); if (m_model && current >= 0 && current < m_model->count()) { m_currentItem = current; @@ -55,7 +55,7 @@ void KItemListSelectionManager::setCurrentItem(int current) emit currentChanged(m_currentItem, previous); if (m_isAnchoredSelectionActive) { - const QSet selection = selectedItems(); + const KItemSet selection = selectedItems(); if (selection != previousSelection) { emit selectionChanged(selection, previousSelection); } @@ -68,18 +68,18 @@ int KItemListSelectionManager::currentItem() const return m_currentItem; } -void KItemListSelectionManager::setSelectedItems(const QSet& items) +void KItemListSelectionManager::setSelectedItems(const KItemSet& items) { if (m_selectedItems != items) { - const QSet previous = m_selectedItems; + const KItemSet previous = m_selectedItems; m_selectedItems = items; emit selectionChanged(m_selectedItems, previous); } } -QSet KItemListSelectionManager::selectedItems() const +KItemSet KItemListSelectionManager::selectedItems() const { - QSet selectedItems = m_selectedItems; + KItemSet selectedItems = m_selectedItems; if (m_isAnchoredSelectionActive && m_anchorItem != m_currentItem) { Q_ASSERT(m_anchorItem >= 0); @@ -127,7 +127,7 @@ void KItemListSelectionManager::setSelected(int index, int count, SelectionMode } endAnchoredSelection(); - const QSet previous = selectedItems(); + const KItemSet previous = selectedItems(); count = qMin(count, m_model->count() - index); @@ -160,7 +160,7 @@ void KItemListSelectionManager::setSelected(int index, int count, SelectionMode break; } - const QSet selection = selectedItems(); + const KItemSet selection = selectedItems(); if (selection != previous) { emit selectionChanged(selection, previous); } @@ -168,11 +168,11 @@ void KItemListSelectionManager::setSelected(int index, int count, SelectionMode void KItemListSelectionManager::clearSelection() { - const QSet previous = selectedItems(); + const KItemSet previous = selectedItems(); if (!previous.isEmpty()) { m_selectedItems.clear(); m_isAnchoredSelectionActive = false; - emit selectionChanged(QSet(), previous); + emit selectionChanged(KItemSet(), previous); } } @@ -221,7 +221,7 @@ void KItemListSelectionManager::setModel(KItemModelBase* model) void KItemListSelectionManager::itemsInserted(const KItemRangeList& itemRanges) { // Store the current selection (needed in the selectionChanged() signal) - const QSet previousSelection = selectedItems(); + const KItemSet previousSelection = selectedItems(); // Update the current item if (m_currentItem < 0) { @@ -257,12 +257,10 @@ void KItemListSelectionManager::itemsInserted(const KItemRangeList& itemRanges) // Update the selections if (!m_selectedItems.isEmpty()) { - const QSet previous = m_selectedItems; + const KItemSet previous = m_selectedItems; m_selectedItems.clear(); - m_selectedItems.reserve(previous.count()); - QSetIterator it(previous); - while (it.hasNext()) { - const int index = it.next(); + + foreach (int index, previous) { int inc = 0; foreach (const KItemRange& itemRange, itemRanges) { if (index < itemRange.index) { @@ -274,7 +272,7 @@ void KItemListSelectionManager::itemsInserted(const KItemRangeList& itemRanges) } } - const QSet selection = selectedItems(); + const KItemSet selection = selectedItems(); if (selection != previousSelection) { emit selectionChanged(selection, previousSelection); } @@ -283,7 +281,7 @@ void KItemListSelectionManager::itemsInserted(const KItemRangeList& itemRanges) void KItemListSelectionManager::itemsRemoved(const KItemRangeList& itemRanges) { // Store the current selection (needed in the selectionChanged() signal) - const QSet previousSelection = selectedItems(); + const KItemSet previousSelection = selectedItems(); const int previousCurrent = m_currentItem; // Update the current item @@ -308,19 +306,18 @@ void KItemListSelectionManager::itemsRemoved(const KItemRangeList& itemRanges) // Update the selections and the anchor item if (!m_selectedItems.isEmpty()) { - const QSet previous = m_selectedItems; + const KItemSet previous = m_selectedItems; m_selectedItems.clear(); - m_selectedItems.reserve(previous.count()); - QSetIterator it(previous); - while (it.hasNext()) { - const int index = indexAfterRangesRemoving(it.next(), itemRanges, DiscardRemovedIndex); + + foreach (int oldIndex, previous) { + const int index = indexAfterRangesRemoving(oldIndex, itemRanges, DiscardRemovedIndex); if (index >= 0) { m_selectedItems.insert(index); } } } - const QSet selection = selectedItems(); + const KItemSet selection = selectedItems(); if (selection != previousSelection) { emit selectionChanged(selection, previousSelection); } @@ -332,7 +329,7 @@ void KItemListSelectionManager::itemsRemoved(const KItemRangeList& itemRanges) void KItemListSelectionManager::itemsMoved(const KItemRange& itemRange, const QList& movedToIndexes) { // Store the current selection (needed in the selectionChanged() signal) - const QSet previousSelection = selectedItems(); + const KItemSet previousSelection = selectedItems(); // Update the current item if (m_currentItem >= itemRange.index && m_currentItem < itemRange.index + itemRange.count) { @@ -352,12 +349,10 @@ void KItemListSelectionManager::itemsMoved(const KItemRange& itemRange, const QL // Update the selections if (!m_selectedItems.isEmpty()) { - const QSet previous = m_selectedItems; + const KItemSet previous = m_selectedItems; m_selectedItems.clear(); - m_selectedItems.reserve(previous.count()); - QSetIterator it(previous); - while (it.hasNext()) { - const int index = it.next(); + + foreach (int index, previous) { if (index >= itemRange.index && index < itemRange.index + itemRange.count) { m_selectedItems.insert(movedToIndexes.at(index - itemRange.index)); } @@ -367,7 +362,7 @@ void KItemListSelectionManager::itemsMoved(const KItemRange& itemRange, const QL } } - const QSet selection = selectedItems(); + const KItemSet selection = selectedItems(); if (selection != previousSelection) { emit selectionChanged(selection, previousSelection); } diff --git a/src/kitemviews/kitemlistselectionmanager.h b/src/kitemviews/kitemlistselectionmanager.h index c89b8a4b85..c4decd39eb 100644 --- a/src/kitemviews/kitemlistselectionmanager.h +++ b/src/kitemviews/kitemlistselectionmanager.h @@ -26,9 +26,9 @@ #include #include +#include #include -#include class KItemModelBase; @@ -57,8 +57,8 @@ public: void setCurrentItem(int current); int currentItem() const; - void setSelectedItems(const QSet& items); - QSet selectedItems() const; + void setSelectedItems(const KItemSet& items); + KItemSet selectedItems() const; bool isSelected(int index) const; bool hasSelection() const; @@ -73,7 +73,7 @@ public: signals: void currentChanged(int current, int previous); - void selectionChanged(const QSet& current, const QSet& previous); + void selectionChanged(const KItemSet& current, const KItemSet& previous); private: void setModel(KItemModelBase* model); @@ -91,7 +91,7 @@ private: private: int m_currentItem; int m_anchorItem; - QSet m_selectedItems; + KItemSet m_selectedItems; bool m_isAnchoredSelectionActive; KItemModelBase* m_model; diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index b3d805a917..7f497210cd 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -609,12 +609,12 @@ KItemListHeader* KItemListView::header() const return m_header; } -QPixmap KItemListView::createDragPixmap(const QSet& indexes) const +QPixmap KItemListView::createDragPixmap(const KItemSet& indexes) const { QPixmap pixmap; if (indexes.count() == 1) { - KItemListWidget* item = m_visibleItems.value(indexes.toList().first()); + KItemListWidget* item = m_visibleItems.value(indexes.first()); QGraphicsView* graphicsView = scene()->views()[0]; if (item && graphicsView) { pixmap = item->createDragPixmap(0, graphicsView); @@ -1305,7 +1305,7 @@ void KItemListView::slotCurrentChanged(int current, int previous) QAccessible::updateAccessibility(this, current+1, QAccessible::Focus); } -void KItemListView::slotSelectionChanged(const QSet& current, const QSet& previous) +void KItemListView::slotSelectionChanged(const KItemSet& current, const KItemSet& previous) { Q_UNUSED(previous); @@ -1502,7 +1502,7 @@ void KItemListView::setController(KItemListController* controller) if (previous) { KItemListSelectionManager* selectionManager = previous->selectionManager(); disconnect(selectionManager, SIGNAL(currentChanged(int,int)), this, SLOT(slotCurrentChanged(int,int))); - disconnect(selectionManager, SIGNAL(selectionChanged(QSet,QSet)), this, SLOT(slotSelectionChanged(QSet,QSet))); + disconnect(selectionManager, SIGNAL(selectionChanged(KItemSet,KItemSet)), this, SLOT(slotSelectionChanged(KItemSet,KItemSet))); } m_controller = controller; @@ -1510,7 +1510,7 @@ void KItemListView::setController(KItemListController* controller) if (controller) { KItemListSelectionManager* selectionManager = controller->selectionManager(); connect(selectionManager, SIGNAL(currentChanged(int,int)), this, SLOT(slotCurrentChanged(int,int))); - connect(selectionManager, SIGNAL(selectionChanged(QSet,QSet)), this, SLOT(slotSelectionChanged(QSet,QSet))); + connect(selectionManager, SIGNAL(selectionChanged(KItemSet,KItemSet)), this, SLOT(slotSelectionChanged(KItemSet,KItemSet))); } onControllerChanged(controller, previous); diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index 14360b02bb..dbe9230867 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -271,7 +271,7 @@ public: * @return Pixmap that is used for a drag operation based on the * items given by \a indexes. */ - virtual QPixmap createDragPixmap(const QSet& indexes) const; + virtual QPixmap createDragPixmap(const KItemSet& indexes) const; /** * Lets the user edit the role \a role for item with the index \a index. @@ -400,7 +400,7 @@ protected slots: virtual void slotSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous); virtual void slotSortRoleChanged(const QByteArray& current, const QByteArray& previous); virtual void slotCurrentChanged(int current, int previous); - virtual void slotSelectionChanged(const QSet& current, const QSet& previous); + virtual void slotSelectionChanged(const KItemSet& current, const KItemSet& previous); private slots: void slotAnimationFinished(QGraphicsWidget* widget, diff --git a/src/kitemviews/kitemlistviewaccessible.cpp b/src/kitemviews/kitemlistviewaccessible.cpp index 565c2151ec..d9ddd58f84 100644 --- a/src/kitemviews/kitemlistviewaccessible.cpp +++ b/src/kitemviews/kitemlistviewaccessible.cpp @@ -109,7 +109,7 @@ int KItemListViewAccessible::rowCount() const int KItemListViewAccessible::selectedCellCount() const { - return view()->controller()->selectionManager()->selectedItems().size(); + return view()->controller()->selectionManager()->selectedItems().count(); } int KItemListViewAccessible::selectedColumnCount() const diff --git a/src/kitemviews/kitemmodelbase.cpp b/src/kitemviews/kitemmodelbase.cpp index edce95ece9..4312640e41 100644 --- a/src/kitemviews/kitemmodelbase.cpp +++ b/src/kitemviews/kitemmodelbase.cpp @@ -123,7 +123,7 @@ int KItemModelBase::expandedParentsCount(int index) const return 0; } -QMimeData* KItemModelBase::createMimeData(const QSet& indexes) const +QMimeData* KItemModelBase::createMimeData(const KItemSet& indexes) const { Q_UNUSED(indexes); return 0; diff --git a/src/kitemviews/kitemmodelbase.h b/src/kitemviews/kitemmodelbase.h index c5b9a0ca5f..283cfa5523 100644 --- a/src/kitemviews/kitemmodelbase.h +++ b/src/kitemviews/kitemmodelbase.h @@ -26,10 +26,10 @@ #include #include +#include #include #include -#include #include class QMimeData; @@ -149,7 +149,7 @@ public: * caller of this method. The method must be implemented if dragging of * items should be possible. */ - virtual QMimeData* createMimeData(const QSet& indexes) const; + virtual QMimeData* createMimeData(const KItemSet& indexes) const; /** * @return Reimplement this to return the index for the first item diff --git a/src/kitemviews/kitemset.cpp b/src/kitemviews/kitemset.cpp new file mode 100644 index 0000000000..f855368c14 --- /dev/null +++ b/src/kitemviews/kitemset.cpp @@ -0,0 +1,348 @@ +/*************************************************************************** + * Copyright (C) 2013 by Frank Reininghaus * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "kitemset.h" + +#include + +#include + +KItemSet::iterator KItemSet::insert(int i) +{ + if (m_itemRanges.empty()) { + m_itemRanges.push_back(KItemRange(i, 1)); + return iterator(m_itemRanges.begin(), 0); + } + + KItemRangeList::iterator rangeBegin = m_itemRanges.begin(); + if (i < rangeBegin->index) { + // The inserted index is smaller than all existing items. + if (i == rangeBegin->index - 1) { + // Move the beginning of the first range one item to the front. + --rangeBegin->index; + ++rangeBegin->count; + } else { + // Insert a new range at the beginning. + rangeBegin = m_itemRanges.insert(rangeBegin, KItemRange(i, 1)); + } + + return iterator(rangeBegin, 0); + } + + KItemRangeList::iterator rangeEnd = m_itemRanges.end(); + KItemRangeList::iterator lastRange = rangeEnd - 1; + if (i >= lastRange->index) { + // i either belongs to the last range, or it is larger than all existing items. + const int lastItemPlus1 = lastRange->index + lastRange->count; + if (i == lastItemPlus1) { + // Move the end of the last range one item to the back. + ++lastRange->count; + } else if (i > lastItemPlus1) { + // Append a new range. + lastRange = m_itemRanges.insert(rangeEnd, KItemRange(i, 1)); + } + + return iterator(lastRange, i - lastRange->index); + } + + // We know that i is between the smallest existing item and the first item + // of the last range. Find the lowest range whose 'index' is smaller than i. + KItemRangeList::iterator low = rangeBegin; + KItemRangeList::iterator high = lastRange; + + while (low + 1 != high) { + const int span = high - low; + Q_ASSERT(span >= 2); + + KItemRangeList::iterator mid = low + span / 2; + if (mid->index > i) { + high = mid; + } else { + low = mid; + } + } + + Q_ASSERT(low->index <= i && high->index > i); + + if (i == low->index + low->count) { + // i is just one item behind the range low. + if (i == high->index - 1) { + // i closes the gap between low and high. Merge the two ranges. + const int newRangeCount = low->count + 1 + high->count; + KItemRangeList::iterator behindNewRange = m_itemRanges.erase(high); + KItemRangeList::iterator newRange = behindNewRange - 1; + newRange->count = newRangeCount; + return iterator(newRange, i - newRange->index); + } else { + // Extend low by one item. + ++low->count; + return iterator(low, low->count - 1); + } + } else if (i > low->index + low->count) { + if (i == high->index - 1) { + // Extend high by one item to the front. + --high->index; + ++high->count; + return iterator(high, 0); + } else { + // Insert a new range between low and high. + KItemRangeList::iterator newRange = m_itemRanges.insert(high, KItemRange(i, 1)); + return iterator(newRange, 0); + } + } else { + // The range low already contains i. + return iterator(low, i - low->index); + } +} + +KItemSet::iterator KItemSet::erase(iterator it) +{ + KItemRangeList::iterator rangeIt = it.m_rangeIt; + + if (it.m_offset == 0) { + // Removed index is at the beginning of a range. + if (rangeIt->count > 1) { + ++rangeIt->index; + --rangeIt->count; + } else { + // The range only contains the removed index. + rangeIt = m_itemRanges.erase(rangeIt); + } + return iterator(rangeIt, 0); + } else if (it.m_offset == rangeIt->count - 1) { + // Removed index is at the end of a range. + --rangeIt->count; + ++rangeIt; + return iterator(rangeIt, 0); + } else { + // The removed index is in the middle of a range. + const int newRangeIndex = *it + 1; + const int newRangeCount = rangeIt->count - it.m_offset - 1; + const KItemRange newRange(newRangeIndex, newRangeCount); + + rangeIt->count = it.m_offset; + ++rangeIt; + rangeIt = m_itemRanges.insert(rangeIt, newRange); + + return iterator(rangeIt, 0); + } +} + +KItemSet KItemSet::operator+(const KItemSet& other) const +{ + KItemSet sum; + + KItemRangeList::const_iterator it1 = m_itemRanges.constBegin(); + KItemRangeList::const_iterator it2 = other.m_itemRanges.constBegin(); + + const KItemRangeList::const_iterator end1 = m_itemRanges.constEnd(); + const KItemRangeList::const_iterator end2 = other.m_itemRanges.constEnd(); + + while (it1 != end1 || it2 != end2) { + if (it1 == end1) { + // We are past the end of 'this' already. Append all remaining + // item ranges from 'other'. + while (it2 != end2) { + sum.m_itemRanges.append(*it2); + ++it2; + } + } else if (it2 == end2) { + // We are past the end of 'other' already. Append all remaining + // item ranges from 'this'. + while (it1 != end1) { + sum.m_itemRanges.append(*it1); + ++it1; + } + } else { + // Find the beginning of the next range. + int index = qMin(it1->index, it2->index); + int count = 0; + + do { + if (it1 != end1 && it1->index <= index + count) { + // The next range from 'this' overlaps with the current range in the sum. + count = qMax(count, it1->index + it1->count - index); + ++it1; + } + + if (it2 != end2 && it2->index <= index + count) { + // The next range from 'other' overlaps with the current range in the sum. + count = qMax(count, it2->index + it2->count - index); + ++it2; + } + } while ((it1 != end1 && it1->index <= index + count) + || (it2 != end2 && it2->index <= index + count)); + + sum.m_itemRanges.append(KItemRange(index, count)); + } + } + + return sum; +} + +KItemSet KItemSet::operator^(const KItemSet& other) const +{ + // We are looking for all ints which are either in *this or in other, + // but not in both. + KItemSet result; + + // When we go through all integers from INT_MIN to INT_MAX and start + // in the state "do not add to result", every beginning/end of a range + // of *this and other toggles the "add/do not add to result" state. + // Therefore, we just have to put ints where any range starts/ends to + // a sorted array, and then we can calculate the result quite easily. + QVector rangeBoundaries; + rangeBoundaries.resize(2 * (m_itemRanges.count() + other.m_itemRanges.count())); + const QVector::iterator begin = rangeBoundaries.begin(); + const QVector::iterator end = rangeBoundaries.end(); + QVector::iterator it = begin; + + foreach (const KItemRange& range, m_itemRanges) { + *it++ = range.index; + *it++ = range.index + range.count; + } + + const QVector::iterator middle = it; + + foreach (const KItemRange& range, other.m_itemRanges) { + *it++ = range.index; + *it++ = range.index + range.count; + } + Q_ASSERT(it == end); + + std::inplace_merge(begin, middle, end); + + it = begin; + while (it != end) { + const int rangeBegin = *it; + ++it; + + if (*it == rangeBegin) { + // It seems that ranges from both *this and other start at + // rangeBegin. Do not start a new range, but read the next int. + // + // Example: Consider the symmetric difference of the sets + // {1, 2, 3, 4} and {1, 2}. The sorted list of range boundaries is + // 1 1 3 5. Discarding the duplicate 1 yields the result + // rangeBegin = 3, rangeEnd = 5, which corresponds to the set {3, 4}. + ++it; + } else { + // The end of the current range is the next *single* int that we + // find. If an int appears twice in rangeBoundaries, the range does + // not end. + // + // Example: Consider the symmetric difference of the sets + // {1, 2, 3, 4, 8, 9, 10} and {5, 6, 7}. The sorted list of range + // boundaries is 1 5 5 8 8 11, and discarding all duplicates yields + // the result rangeBegin = 1, rangeEnd = 11, which corresponds to + // the set {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}. + bool foundEndOfRange = false; + int rangeEnd; + do { + rangeEnd = *it; + ++it; + + if (it == end || *it != rangeEnd) { + foundEndOfRange = true; + } else { + ++it; + } + } while (!foundEndOfRange); + + result.m_itemRanges.append(KItemRange(rangeBegin, rangeEnd - rangeBegin)); + } + } + + return result; +} + +bool KItemSet::isValid() const +{ + const KItemRangeList::const_iterator begin = m_itemRanges.constBegin(); + const KItemRangeList::const_iterator end = m_itemRanges.constEnd(); + + for (KItemRangeList::const_iterator it = begin; it != end; ++it) { + if (it->count <= 0) { + return false; + } + + if (it != begin) { + const KItemRangeList::const_iterator previous = it - 1; + if (previous->index + previous->count >= it->index) { + return false; + } + } + } + + return true; +} + +KItemRangeList::iterator KItemSet::rangeForItem(int i) +{ + const KItemRangeList::iterator end = m_itemRanges.end(); + KItemRangeList::iterator low = m_itemRanges.begin(); + KItemRangeList::iterator high = end; + + if (low == end || low->index > i) { + return end; + } + + while (low != high && low + 1 != high) { + KItemRangeList::iterator mid = low + (high - low) / 2; + if (mid->index > i) { + high = mid; + } else { + low = mid; + } + } + + Q_ASSERT(low->index <= i); + if (low->index + low->count > i) { + return low; + } + + return end; +} + +KItemRangeList::const_iterator KItemSet::constRangeForItem(int i) const +{ + const KItemRangeList::const_iterator end = m_itemRanges.constEnd(); + KItemRangeList::const_iterator low = m_itemRanges.constBegin(); + KItemRangeList::const_iterator high = end; + + if (low == end || low->index > i) { + return end; + } + + while (low != high && low + 1 != high) { + KItemRangeList::const_iterator mid = low + (high - low) / 2; + if (mid->index > i) { + high = mid; + } else { + low = mid; + } + } + + Q_ASSERT(low->index <= i); + if (low->index + low->count > i) { + return low; + } + + return end; +} diff --git a/src/kitemviews/kitemset.h b/src/kitemviews/kitemset.h new file mode 100644 index 0000000000..385010f7d6 --- /dev/null +++ b/src/kitemviews/kitemset.h @@ -0,0 +1,413 @@ +/*************************************************************************** + * Copyright (C) 2013 by Frank Reininghaus * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef KITEMSET_H +#define KITEMSET_H + +#include + +/** + * @brief Stores a set of integer numbers in a space-efficient way. + * + * This class is similar to QSet, but it has the following advantages: + * + * 1. It uses less memory than a QSet if many consecutive numbers are + * stored. This is achieved by not storing each number separately, but + * "ranges" of numbers. + * + * Example: The set {1, 2, 3, 4, 5} is represented by a single range which + * starts at 1 and has the length 5. + * + * 2. When iterating through a KItemSet using KItemSet::iterator or + * KItemSet::const_iterator, the numbers are traversed in ascending order. + * + * The complexity of most operations depends on the number of ranges. + */ + +class KItemSet +{ +public: + KItemSet(); + KItemSet(const KItemSet& other); + + /** + * Returns the number of items in the set. + * Complexity: O(log(number of ranges)). + */ + int count() const; + + bool isEmpty() const; + void clear(); + + bool operator==(const KItemSet& other) const; + bool operator!=(const KItemSet& other) const; + + class iterator + { + iterator(const KItemRangeList::iterator& rangeIt, int offset) : + m_rangeIt(rangeIt), + m_offset(offset) + { + } + + public: + iterator(const iterator& other) : + m_rangeIt(other.m_rangeIt), + m_offset(other.m_offset) + { + } + + iterator& operator=(const iterator& other) + { + m_rangeIt = other.m_rangeIt; + m_offset = other.m_offset; + return *this; + } + + int operator*() const + { + return m_rangeIt->index + m_offset; + } + + inline bool operator==(const iterator& other) const + { + return m_rangeIt == other.m_rangeIt && m_offset == other.m_offset; + } + + inline bool operator!=(const iterator& other) const + { + return !(*this == other); + } + + inline iterator& operator++() + { + ++m_offset; + + if (m_offset == m_rangeIt->count) { + ++m_rangeIt; + m_offset = 0; + } + + return *this; + } + + inline iterator operator++(int) + { + iterator r = *this; + ++(*this); + return r; + } + + inline iterator& operator--() + { + if (m_offset == 0) { + --m_rangeIt; + m_offset = m_rangeIt->count - 1; + } else { + --m_offset; + } + + return *this; + } + + inline iterator operator--(int) + { + iterator r = *this; + --(*this); + return r; + } + + private: + KItemRangeList::iterator m_rangeIt; + int m_offset; + + friend class const_iterator; + friend class KItemSet; + }; + + + class const_iterator + { + const_iterator(KItemRangeList::const_iterator rangeIt, int offset) : + m_rangeIt(rangeIt), + m_offset(offset) + { + } + + public: + const_iterator(const const_iterator& other) : + m_rangeIt(other.m_rangeIt), + m_offset(other.m_offset) + { + } + + const_iterator(const iterator& other) : + m_rangeIt(other.m_rangeIt), + m_offset(other.m_offset) + { + } + + const_iterator& operator=(const const_iterator& other) + { + m_rangeIt = other.m_rangeIt; + m_offset = other.m_offset; + return *this; + } + + int operator*() const + { + return m_rangeIt->index + m_offset; + } + + inline bool operator==(const const_iterator& other) const + { + return m_rangeIt == other.m_rangeIt && m_offset == other.m_offset; + } + + inline bool operator!=(const const_iterator& other) const + { + return !(*this == other); + } + + inline const_iterator& operator++() + { + ++m_offset; + + if (m_offset == m_rangeIt->count) { + ++m_rangeIt; + m_offset = 0; + } + + return *this; + } + + inline const_iterator operator++(int) + { + const_iterator r = *this; + ++(*this); + return r; + } + + inline const_iterator& operator--() + { + if (m_offset == 0) { + --m_rangeIt; + m_offset = m_rangeIt->count - 1; + } else { + --m_offset; + } + + return *this; + } + + inline const_iterator operator--(int) + { + const_iterator r = *this; + --(*this); + return r; + } + + private: + KItemRangeList::const_iterator m_rangeIt; + int m_offset; + + friend class KItemSet; + }; + + iterator begin(); + const_iterator begin() const; + const_iterator constBegin() const; + iterator end(); + const_iterator end() const; + const_iterator constEnd() const; + + int first() const; + int last() const; + + bool contains(int i) const; + iterator insert(int i); + iterator find(int i); + const_iterator constFind(int i) const; + bool remove(int i); + iterator erase(iterator it); + + /** + * Returns a new set which contains all items that are contained in this + * KItemSet, in \a other, or in both. + */ + KItemSet operator+(const KItemSet& other) const; + + /** + * Returns a new set which contains all items that are contained either in + * this KItemSet, or in \a other, but not in both (the symmetric difference + * of both KItemSets). + */ + KItemSet operator^(const KItemSet& other) const; + + KItemSet& operator<<(int i); + +private: + /** + * Returns true if the KItemSet is valid, and false otherwise. + * A valid KItemSet must store the item ranges in ascending order, and + * the ranges must not overlap. + */ + bool isValid() const; + + /** + * This function returns an iterator that points to the KItemRange which + * contains i, or m_itemRanges.end() if no such range exists. + */ + KItemRangeList::iterator rangeForItem(int i); + + /** + * This function returns an iterator that points to the KItemRange which + * contains i, or m_itemRanges.constEnd() if no such range exists. + */ + KItemRangeList::const_iterator constRangeForItem(int i) const; + + KItemRangeList m_itemRanges; + + friend class KItemSetTest; +}; + +inline KItemSet::KItemSet() : + m_itemRanges() +{ +} + +inline KItemSet::KItemSet(const KItemSet& other) : + m_itemRanges(other.m_itemRanges) +{ +} + +inline int KItemSet::count() const +{ + int result = 0; + foreach (const KItemRange& range, m_itemRanges) { + result += range.count; + } + return result; +} + +inline bool KItemSet::isEmpty() const +{ + return m_itemRanges.isEmpty(); +} + +inline void KItemSet::clear() +{ + m_itemRanges.clear(); +} + +inline bool KItemSet::operator==(const KItemSet& other) const +{ + return m_itemRanges == other.m_itemRanges; +} + +inline bool KItemSet::operator!=(const KItemSet& other) const +{ + return m_itemRanges != other.m_itemRanges; +} + +inline bool KItemSet::contains(int i) const +{ + const KItemRangeList::const_iterator it = constRangeForItem(i); + return it != m_itemRanges.end(); +} + +inline KItemSet::iterator KItemSet::find(int i) +{ + const KItemRangeList::iterator it = rangeForItem(i); + if (it != m_itemRanges.end()) { + return iterator(it, i - it->index); + } else { + return end(); + } +} + +inline KItemSet::const_iterator KItemSet::constFind(int i) const +{ + const KItemRangeList::const_iterator it = constRangeForItem(i); + if (it != m_itemRanges.constEnd()) { + return const_iterator(it, i - it->index); + } else { + return constEnd(); + } +} + +inline bool KItemSet::remove(int i) +{ + iterator it = find(i); + if (it != end()) { + erase(it); + return true; + } else { + return false; + } +} + +inline KItemSet::iterator KItemSet::begin() +{ + return iterator(m_itemRanges.begin(), 0); +} + +inline KItemSet::const_iterator KItemSet::begin() const +{ + return const_iterator(m_itemRanges.begin(), 0); +} + +inline KItemSet::const_iterator KItemSet::constBegin() const +{ + return const_iterator(m_itemRanges.constBegin(), 0); +} + +inline KItemSet::iterator KItemSet::end() +{ + return iterator(m_itemRanges.end(), 0); +} + +inline KItemSet::const_iterator KItemSet::end() const +{ + return const_iterator(m_itemRanges.end(), 0); +} + +inline KItemSet::const_iterator KItemSet::constEnd() const +{ + return const_iterator(m_itemRanges.constEnd(), 0); +} + +inline int KItemSet::first() const +{ + return m_itemRanges.first().index; +} + +inline int KItemSet::last() const +{ + const KItemRange& lastRange = m_itemRanges.last(); + return lastRange.index + lastRange.count - 1; +} + +inline KItemSet& KItemSet::operator<<(int i) +{ + insert(i); + return *this; +} + +#endif diff --git a/src/kitemviews/kstandarditemmodel.cpp b/src/kitemviews/kstandarditemmodel.cpp index 959d62cb8a..e8c1b62042 100644 --- a/src/kitemviews/kstandarditemmodel.cpp +++ b/src/kitemviews/kstandarditemmodel.cpp @@ -175,7 +175,7 @@ bool KStandardItemModel::setData(int index, const QHash& v return true; } -QMimeData* KStandardItemModel::createMimeData(const QSet& indexes) const +QMimeData* KStandardItemModel::createMimeData(const KItemSet& indexes) const { Q_UNUSED(indexes); return 0; diff --git a/src/kitemviews/kstandarditemmodel.h b/src/kitemviews/kstandarditemmodel.h index 0debd6a6fc..721e155299 100644 --- a/src/kitemviews/kstandarditemmodel.h +++ b/src/kitemviews/kstandarditemmodel.h @@ -72,7 +72,7 @@ public: virtual int count() const; virtual QHash data(int index) const; virtual bool setData(int index, const QHash& values); - virtual QMimeData* createMimeData(const QSet& indexes) const; + virtual QMimeData* createMimeData(const KItemSet& indexes) const; virtual int indexForKeyboardSearch(const QString& text, int startFromIndex = 0) const; virtual bool supportsDropping(int index) const; virtual QString roleDescription(const QByteArray& role) const; diff --git a/src/panels/places/placesitemmodel.cpp b/src/panels/places/placesitemmodel.cpp index eae2095c99..681479dfba 100644 --- a/src/panels/places/placesitemmodel.cpp +++ b/src/panels/places/placesitemmodel.cpp @@ -377,7 +377,7 @@ void PlacesItemModel::requestStorageSetup(int index) } } -QMimeData* PlacesItemModel::createMimeData(const QSet& indexes) const +QMimeData* PlacesItemModel::createMimeData(const KItemSet& indexes) const { KUrl::List urls; QByteArray itemData; diff --git a/src/panels/places/placesitemmodel.h b/src/panels/places/placesitemmodel.h index 6938360332..cd37e73535 100644 --- a/src/panels/places/placesitemmodel.h +++ b/src/panels/places/placesitemmodel.h @@ -118,7 +118,7 @@ public: void requestStorageSetup(int index); /** @reimp */ - virtual QMimeData* createMimeData(const QSet& indexes) const; + virtual QMimeData* createMimeData(const KItemSet& indexes) const; /** @reimp */ virtual bool supportsDropping(int index) const; diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index dd761fc90b..9b152ed07d 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -3,11 +3,21 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BUILD_DIR}/. # needed on windows to correctly use the files from dolphinprivate add_definitions(-DLIBDOLPHINPRIVATE_EXPORT=) + +# KItemSetTest +set(kitemsettest_SRCS + kitemsettest.cpp + ../kitemviews/kitemset.cpp +) +kde4_add_unit_test(kitemsettest TEST ${kitemsettest_SRCS}) +target_link_libraries(kitemsettest dolphinprivate ${KDE4_KIO_LIBS} ${QT_QTTEST_LIBRARY}) + # KItemListSelectionManagerTest set(kitemlistselectionmanagertest_SRCS kitemlistselectionmanagertest.cpp ../kitemviews/kitemlistselectionmanager.cpp ../kitemviews/kitemmodelbase.cpp + ../kitemviews/kitemset.cpp ) kde4_add_unit_test(kitemlistselectionmanagertest TEST ${kitemlistselectionmanagertest_SRCS}) target_link_libraries(kitemlistselectionmanagertest dolphinprivate ${KDE4_KIO_LIBS} ${QT_QTTEST_LIBRARY}) @@ -24,6 +34,7 @@ set(kitemlistcontrollertest_SRCS ../kitemviews/kitemlistcontainer.cpp ../kitemviews/kitemlistwidget.cpp ../kitemviews/kitemlistviewaccessible.cpp + ../kitemviews/kitemset.cpp ../kitemviews/kstandarditemlistview.cpp ../kitemviews/kstandarditemlistwidget.cpp ) @@ -41,6 +52,7 @@ set(kfileitemlistviewtest_SRCS ../kitemviews/kitemlistviewaccessible.cpp ../kitemviews/kitemlistcontainer.cpp ../kitemviews/kitemlistwidget.cpp + ../kitemviews/kitemset.cpp ../kitemviews/kstandarditemlistview.cpp ../kitemviews/kstandarditemlistwidget.cpp ) diff --git a/src/tests/kitemlistcontrollertest.cpp b/src/tests/kitemlistcontrollertest.cpp index 60e93e539a..7dd37bf0a3 100644 --- a/src/tests/kitemlistcontrollertest.cpp +++ b/src/tests/kitemlistcontrollertest.cpp @@ -41,7 +41,7 @@ namespace { Q_DECLARE_METATYPE(KFileItemListView::ItemLayout); Q_DECLARE_METATYPE(Qt::Orientation); Q_DECLARE_METATYPE(KItemListController::SelectionBehavior); -Q_DECLARE_METATYPE(QSet); +Q_DECLARE_METATYPE(KItemSet); class KItemListControllerTest : public QObject { @@ -81,7 +81,7 @@ private: */ void KItemListControllerTest::initTestCase() { - qRegisterMetaType >("QSet"); + qRegisterMetaType("KItemSet"); m_testDir = new TestDir(); m_model = new KFileItemModel(); @@ -159,14 +159,14 @@ struct KeyPress { */ struct ViewState { - ViewState(int current, const QSet selection, bool activated = false) : + ViewState(int current, const KItemSet selection, bool activated = false) : m_current(current), m_selection(selection), m_activated(activated) {} int m_current; - QSet m_selection; + KItemSet m_selection; bool m_activated; }; @@ -262,34 +262,34 @@ void KItemListControllerTest::testKeyboardNavigation_data() // First, key presses which should have the same effect // for any layout and any number of columns. testList - << qMakePair(KeyPress(nextItemKey), ViewState(1, QSet() << 1)) - << qMakePair(KeyPress(Qt::Key_Return), ViewState(1, QSet() << 1, true)) - << qMakePair(KeyPress(Qt::Key_Enter), ViewState(1, QSet() << 1, true)) - << qMakePair(KeyPress(nextItemKey), ViewState(2, QSet() << 2)) - << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(3, QSet() << 2 << 3)) - << qMakePair(KeyPress(Qt::Key_Return), ViewState(3, QSet() << 2 << 3, true)) - << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(2, QSet() << 2)) - << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(3, QSet() << 2 << 3)) - << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(4, QSet() << 2 << 3)) - << qMakePair(KeyPress(Qt::Key_Return), ViewState(4, QSet() << 2 << 3, true)) - << qMakePair(KeyPress(previousItemKey), ViewState(3, QSet() << 3)) - << qMakePair(KeyPress(Qt::Key_Home, Qt::ShiftModifier), ViewState(0, QSet() << 0 << 1 << 2 << 3)) - << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(1, QSet() << 0 << 1 << 2 << 3)) - << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(1, QSet() << 0 << 2 << 3)) - << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(1, QSet() << 0 << 1 << 2 << 3)) - << qMakePair(KeyPress(Qt::Key_End), ViewState(19, QSet() << 19)) - << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(18, QSet() << 18 << 19)) - << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet() << 0)) - << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, QSet())) - << qMakePair(KeyPress(Qt::Key_Enter), ViewState(0, QSet(), true)) - << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, QSet() << 0)) - << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, QSet())) - << qMakePair(KeyPress(Qt::Key_Space), ViewState(0, QSet() << 0)) - << qMakePair(KeyPress(Qt::Key_E), ViewState(13, QSet() << 13)) - << qMakePair(KeyPress(Qt::Key_Space), ViewState(14, QSet() << 14)) - << qMakePair(KeyPress(Qt::Key_3), ViewState(15, QSet() << 15)) - << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet() << 0)) - << qMakePair(KeyPress(Qt::Key_Escape), ViewState(0, QSet())); + << qMakePair(KeyPress(nextItemKey), ViewState(1, KItemSet() << 1)) + << qMakePair(KeyPress(Qt::Key_Return), ViewState(1, KItemSet() << 1, true)) + << qMakePair(KeyPress(Qt::Key_Enter), ViewState(1, KItemSet() << 1, true)) + << qMakePair(KeyPress(nextItemKey), ViewState(2, KItemSet() << 2)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(3, KItemSet() << 2 << 3)) + << qMakePair(KeyPress(Qt::Key_Return), ViewState(3, KItemSet() << 2 << 3, true)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(2, KItemSet() << 2)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(3, KItemSet() << 2 << 3)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(4, KItemSet() << 2 << 3)) + << qMakePair(KeyPress(Qt::Key_Return), ViewState(4, KItemSet() << 2 << 3, true)) + << qMakePair(KeyPress(previousItemKey), ViewState(3, KItemSet() << 3)) + << qMakePair(KeyPress(Qt::Key_Home, Qt::ShiftModifier), ViewState(0, KItemSet() << 0 << 1 << 2 << 3)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(1, KItemSet() << 0 << 1 << 2 << 3)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(1, KItemSet() << 0 << 2 << 3)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(1, KItemSet() << 0 << 1 << 2 << 3)) + << qMakePair(KeyPress(Qt::Key_End), ViewState(19, KItemSet() << 19)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(18, KItemSet() << 18 << 19)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 0)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, KItemSet())) + << qMakePair(KeyPress(Qt::Key_Enter), ViewState(0, KItemSet(), true)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, KItemSet() << 0)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, KItemSet())) + << qMakePair(KeyPress(Qt::Key_Space), ViewState(0, KItemSet() << 0)) + << qMakePair(KeyPress(Qt::Key_E), ViewState(13, KItemSet() << 13)) + << qMakePair(KeyPress(Qt::Key_Space), ViewState(14, KItemSet() << 14)) + << qMakePair(KeyPress(Qt::Key_3), ViewState(15, KItemSet() << 15)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 0)) + << qMakePair(KeyPress(Qt::Key_Escape), ViewState(0, KItemSet())); // Next, we test combinations of key presses which only work for a // particular number of columns and either enabled or disabled grouping. @@ -297,12 +297,12 @@ void KItemListControllerTest::testKeyboardNavigation_data() // One column. if (columnCount == 1) { testList - << qMakePair(KeyPress(nextRowKey), ViewState(1, QSet() << 1)) - << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(2, QSet() << 1 << 2)) - << qMakePair(KeyPress(nextRowKey, Qt::ControlModifier), ViewState(3, QSet() << 1 << 2)) - << qMakePair(KeyPress(previousRowKey), ViewState(2, QSet() << 2)) - << qMakePair(KeyPress(previousItemKey), ViewState(1, QSet() << 1)) - << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet() << 0)); + << qMakePair(KeyPress(nextRowKey), ViewState(1, KItemSet() << 1)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(2, KItemSet() << 1 << 2)) + << qMakePair(KeyPress(nextRowKey, Qt::ControlModifier), ViewState(3, KItemSet() << 1 << 2)) + << qMakePair(KeyPress(previousRowKey), ViewState(2, KItemSet() << 2)) + << qMakePair(KeyPress(previousItemKey), ViewState(1, KItemSet() << 1)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 0)); } // Multiple columns: we test both 3 and 5 columns with grouping @@ -321,26 +321,26 @@ void KItemListControllerTest::testKeyboardNavigation_data() // e3 e4 e5 | 15 16 17 // e6 e7 | 18 19 testList - << qMakePair(KeyPress(nextRowKey), ViewState(3, QSet() << 3)) - << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(4, QSet() << 3)) - << qMakePair(KeyPress(nextRowKey), ViewState(7, QSet() << 7)) - << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(8, QSet() << 7 << 8)) - << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(9, QSet() << 7 << 8 << 9)) - << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(8, QSet() << 7 << 8)) - << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(7, QSet() << 7)) - << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(6, QSet() << 6 << 7)) - << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(5, QSet() << 5 << 6 << 7)) - << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(6, QSet() << 6 << 7)) - << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(7, QSet() << 7)) - << qMakePair(KeyPress(nextRowKey), ViewState(10, QSet() << 10)) - << qMakePair(KeyPress(nextItemKey), ViewState(11, QSet() << 11)) - << qMakePair(KeyPress(nextRowKey), ViewState(14, QSet() << 14)) - << qMakePair(KeyPress(nextRowKey), ViewState(17, QSet() << 17)) - << qMakePair(KeyPress(nextRowKey), ViewState(19, QSet() << 19)) - << qMakePair(KeyPress(previousRowKey), ViewState(17, QSet() << 17)) - << qMakePair(KeyPress(Qt::Key_End), ViewState(19, QSet() << 19)) - << qMakePair(KeyPress(previousRowKey), ViewState(16, QSet() << 16)) - << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet() << 0)); + << qMakePair(KeyPress(nextRowKey), ViewState(3, KItemSet() << 3)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(4, KItemSet() << 3)) + << qMakePair(KeyPress(nextRowKey), ViewState(7, KItemSet() << 7)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(8, KItemSet() << 7 << 8)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(9, KItemSet() << 7 << 8 << 9)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(8, KItemSet() << 7 << 8)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(7, KItemSet() << 7)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(6, KItemSet() << 6 << 7)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(5, KItemSet() << 5 << 6 << 7)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(6, KItemSet() << 6 << 7)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(7, KItemSet() << 7)) + << qMakePair(KeyPress(nextRowKey), ViewState(10, KItemSet() << 10)) + << qMakePair(KeyPress(nextItemKey), ViewState(11, KItemSet() << 11)) + << qMakePair(KeyPress(nextRowKey), ViewState(14, KItemSet() << 14)) + << qMakePair(KeyPress(nextRowKey), ViewState(17, KItemSet() << 17)) + << qMakePair(KeyPress(nextRowKey), ViewState(19, KItemSet() << 19)) + << qMakePair(KeyPress(previousRowKey), ViewState(17, KItemSet() << 17)) + << qMakePair(KeyPress(Qt::Key_End), ViewState(19, KItemSet() << 19)) + << qMakePair(KeyPress(previousRowKey), ViewState(16, KItemSet() << 16)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 0)); } if (columnCount == 5 && !groupingEnabled) { @@ -351,17 +351,17 @@ void KItemListControllerTest::testKeyboardNavigation_data() // d2 d3 d4 e1 e2 | 10 11 12 13 14 // e3 e4 e5 e6 e7 | 15 16 17 18 19 testList - << qMakePair(KeyPress(nextRowKey), ViewState(5, QSet() << 5)) - << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(6, QSet() << 5)) - << qMakePair(KeyPress(nextRowKey), ViewState(11, QSet() << 11)) - << qMakePair(KeyPress(nextItemKey), ViewState(12, QSet() << 12)) - << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(17, QSet() << 12 << 13 << 14 << 15 << 16 << 17)) - << qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(12, QSet() << 12)) - << qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(7, QSet() << 7 << 8 << 9 << 10 << 11 << 12)) - << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(12, QSet() << 12)) - << qMakePair(KeyPress(Qt::Key_End, Qt::ControlModifier), ViewState(19, QSet() << 12)) - << qMakePair(KeyPress(previousRowKey), ViewState(14, QSet() << 14)) - << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet() << 0)); + << qMakePair(KeyPress(nextRowKey), ViewState(5, KItemSet() << 5)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(6, KItemSet() << 5)) + << qMakePair(KeyPress(nextRowKey), ViewState(11, KItemSet() << 11)) + << qMakePair(KeyPress(nextItemKey), ViewState(12, KItemSet() << 12)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(17, KItemSet() << 12 << 13 << 14 << 15 << 16 << 17)) + << qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(12, KItemSet() << 12)) + << qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(7, KItemSet() << 7 << 8 << 9 << 10 << 11 << 12)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(12, KItemSet() << 12)) + << qMakePair(KeyPress(Qt::Key_End, Qt::ControlModifier), ViewState(19, KItemSet() << 12)) + << qMakePair(KeyPress(previousRowKey), ViewState(14, KItemSet() << 14)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 0)); } if (columnCount == 3 && groupingEnabled) { @@ -377,19 +377,19 @@ void KItemListControllerTest::testKeyboardNavigation_data() // e4 e5 e6 | 16 17 18 // e7 | 19 testList - << qMakePair(KeyPress(nextItemKey), ViewState(1, QSet() << 1)) - << qMakePair(KeyPress(nextItemKey), ViewState(2, QSet() << 2)) - << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(3, QSet() << 2 << 3)) - << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(6, QSet() << 2 << 3 << 4 << 5 << 6)) - << qMakePair(KeyPress(nextRowKey), ViewState(8, QSet() << 8)) - << qMakePair(KeyPress(nextRowKey), ViewState(11, QSet() << 11)) - << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(12, QSet() << 11)) - << qMakePair(KeyPress(nextRowKey), ViewState(13, QSet() << 13)) - << qMakePair(KeyPress(nextRowKey), ViewState(16, QSet() << 16)) - << qMakePair(KeyPress(nextItemKey), ViewState(17, QSet() << 17)) - << qMakePair(KeyPress(nextRowKey), ViewState(19, QSet() << 19)) - << qMakePair(KeyPress(previousRowKey), ViewState(17, QSet() << 17)) - << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet() << 0)); + << qMakePair(KeyPress(nextItemKey), ViewState(1, KItemSet() << 1)) + << qMakePair(KeyPress(nextItemKey), ViewState(2, KItemSet() << 2)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(3, KItemSet() << 2 << 3)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(6, KItemSet() << 2 << 3 << 4 << 5 << 6)) + << qMakePair(KeyPress(nextRowKey), ViewState(8, KItemSet() << 8)) + << qMakePair(KeyPress(nextRowKey), ViewState(11, KItemSet() << 11)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(12, KItemSet() << 11)) + << qMakePair(KeyPress(nextRowKey), ViewState(13, KItemSet() << 13)) + << qMakePair(KeyPress(nextRowKey), ViewState(16, KItemSet() << 16)) + << qMakePair(KeyPress(nextItemKey), ViewState(17, KItemSet() << 17)) + << qMakePair(KeyPress(nextRowKey), ViewState(19, KItemSet() << 19)) + << qMakePair(KeyPress(previousRowKey), ViewState(17, KItemSet() << 17)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 0)); } if (columnCount == 5 && groupingEnabled) { @@ -402,19 +402,19 @@ void KItemListControllerTest::testKeyboardNavigation_data() // e1 e2 e3 e4 e5 | 13 14 15 16 17 // e6 e7 | 18 19 testList - << qMakePair(KeyPress(nextItemKey), ViewState(1, QSet() << 1)) - << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(3, QSet() << 1 << 2 << 3)) - << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(5, QSet() << 1 << 2 << 3 << 4 << 5)) - << qMakePair(KeyPress(nextItemKey), ViewState(6, QSet() << 6)) - << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(7, QSet() << 6)) - << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(8, QSet() << 6)) - << qMakePair(KeyPress(nextRowKey), ViewState(12, QSet() << 12)) - << qMakePair(KeyPress(nextRowKey), ViewState(17, QSet() << 17)) - << qMakePair(KeyPress(nextRowKey), ViewState(19, QSet() << 19)) - << qMakePair(KeyPress(previousRowKey), ViewState(17, QSet() << 17)) - << qMakePair(KeyPress(Qt::Key_End, Qt::ShiftModifier), ViewState(19, QSet() << 17 << 18 << 19)) - << qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(14, QSet() << 14 << 15 << 16 << 17)) - << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet() << 0)); + << qMakePair(KeyPress(nextItemKey), ViewState(1, KItemSet() << 1)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(3, KItemSet() << 1 << 2 << 3)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(5, KItemSet() << 1 << 2 << 3 << 4 << 5)) + << qMakePair(KeyPress(nextItemKey), ViewState(6, KItemSet() << 6)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(7, KItemSet() << 6)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(8, KItemSet() << 6)) + << qMakePair(KeyPress(nextRowKey), ViewState(12, KItemSet() << 12)) + << qMakePair(KeyPress(nextRowKey), ViewState(17, KItemSet() << 17)) + << qMakePair(KeyPress(nextRowKey), ViewState(19, KItemSet() << 19)) + << qMakePair(KeyPress(previousRowKey), ViewState(17, KItemSet() << 17)) + << qMakePair(KeyPress(Qt::Key_End, Qt::ShiftModifier), ViewState(19, KItemSet() << 17 << 18 << 19)) + << qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(14, KItemSet() << 14 << 15 << 16 << 17)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 0)); } const QString testName = @@ -470,14 +470,14 @@ void KItemListControllerTest::testKeyboardNavigation() QCOMPARE(m_view->m_layouter->m_columnCount, columnCount); QSignalSpy spySingleItemActivated(m_controller, SIGNAL(itemActivated(int))); - QSignalSpy spyMultipleItemsActivated(m_controller, SIGNAL(itemsActivated(QSet))); + QSignalSpy spyMultipleItemsActivated(m_controller, SIGNAL(itemsActivated(KItemSet))); while (!testList.isEmpty()) { const QPair test = testList.takeFirst(); const Qt::Key key = test.first.m_key; const Qt::KeyboardModifiers modifier = test.first.m_modifier; const int current = test.second.m_current; - const QSet selection = test.second.m_selection; + const KItemSet selection = test.second.m_selection; const bool activated = test.second.m_activated; QTest::keyClick(m_container, key, modifier); @@ -485,7 +485,7 @@ void KItemListControllerTest::testKeyboardNavigation() QCOMPARE(m_selectionManager->currentItem(), current); switch (selectionBehavior) { case KItemListController::NoSelection: QVERIFY(m_selectionManager->selectedItems().isEmpty()); break; - case KItemListController::SingleSelection: QCOMPARE(m_selectionManager->selectedItems(), QSet() << current); break; + case KItemListController::SingleSelection: QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << current); break; case KItemListController::MultiSelection: QCOMPARE(m_selectionManager->selectedItems(), selection); break; } @@ -496,12 +496,12 @@ void KItemListControllerTest::testKeyboardNavigation() // The selected items should be activated. if (selection.count() == 1) { QVERIFY(!spySingleItemActivated.isEmpty()); - QCOMPARE(qvariant_cast(spySingleItemActivated.takeFirst().at(0)), selection.toList().at(0)); + QCOMPARE(qvariant_cast(spySingleItemActivated.takeFirst().at(0)), selection.first()); QVERIFY(spyMultipleItemsActivated.isEmpty()); } else { QVERIFY(spySingleItemActivated.isEmpty()); QVERIFY(!spyMultipleItemsActivated.isEmpty()); - QCOMPARE(qvariant_cast >(spyMultipleItemsActivated.takeFirst().at(0)), selection); + QCOMPARE(qvariant_cast(spyMultipleItemsActivated.takeFirst().at(0)), selection); } break; } @@ -641,7 +641,7 @@ void KItemListControllerTest::testMouseClickActivation() group.writeEntry("SingleClick", restoreKGlobalSettingsSingleClick, KConfig::Persistent|KConfig::Global); config.sync(); KGlobalSettings::self()->emitChange(KGlobalSettings::SettingsChanged, KGlobalSettings::SETTINGS_MOUSE); - + iterations = 0; while (KGlobalSettings::singleClick() != restoreKGlobalSettingsSingleClick && iterations < maxIterations) { QTest::qWait(50); diff --git a/src/tests/kitemlistselectionmanagertest.cpp b/src/tests/kitemlistselectionmanagertest.cpp index 302985a5f4..af2610d8c2 100644 --- a/src/tests/kitemlistselectionmanagertest.cpp +++ b/src/tests/kitemlistselectionmanagertest.cpp @@ -80,7 +80,7 @@ private slots: void testDeleteCurrentItem(); private: - void verifySelectionChange(QSignalSpy& spy, const QSet& currentSelection, const QSet& previousSelection) const; + void verifySelectionChange(QSignalSpy& spy, const KItemSet& currentSelection, const KItemSet& previousSelection) const; KItemListSelectionManager* m_selectionManager; DummyModel* m_model; @@ -127,7 +127,7 @@ void KItemListSelectionManagerTest::testCurrentItemAnchorItem() QCOMPARE(m_selectionManager->m_anchorItem, 5); // Items between current and anchor should be selected now - QCOMPARE(m_selectionManager->selectedItems(), QSet() << 4 << 5); + QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 4 << 5); QVERIFY(m_selectionManager->hasSelection()); // Change current item again and check the selection @@ -138,7 +138,7 @@ void KItemListSelectionManagerTest::testCurrentItemAnchorItem() QCOMPARE(qvariant_cast(spyCurrent.at(0).at(1)), 4); spyCurrent.takeFirst(); - QCOMPARE(m_selectionManager->selectedItems(), QSet() << 2 << 3 << 4 << 5); + QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 2 << 3 << 4 << 5); QVERIFY(m_selectionManager->hasSelection()); // Inserting items should update current item and anchor item. @@ -155,7 +155,7 @@ void KItemListSelectionManagerTest::testCurrentItemAnchorItem() QCOMPARE(m_selectionManager->m_anchorItem, 8); - QCOMPARE(m_selectionManager->selectedItems(), QSet() << 5 << 6 << 7 << 8); + QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 5 << 6 << 7 << 8); QVERIFY(m_selectionManager->hasSelection()); // Removing items should update current item and anchor item. @@ -172,12 +172,12 @@ void KItemListSelectionManagerTest::testCurrentItemAnchorItem() QCOMPARE(m_selectionManager->m_anchorItem, 5); - QCOMPARE(m_selectionManager->selectedItems(), QSet() << 2 << 3 << 4 << 5); + QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 2 << 3 << 4 << 5); QVERIFY(m_selectionManager->hasSelection()); // Verify that clearSelection() also clears the anchored selection. m_selectionManager->clearSelection(); - QCOMPARE(m_selectionManager->selectedItems(), QSet()); + QCOMPARE(m_selectionManager->selectedItems(), KItemSet()); QVERIFY(!m_selectionManager->hasSelection()); m_selectionManager->endAnchoredSelection(); @@ -212,7 +212,7 @@ void KItemListSelectionManagerTest::testItemsInserted() { // Select items 10 to 12 m_selectionManager->setSelected(10, 3); - QSet selectedItems = m_selectionManager->selectedItems(); + KItemSet selectedItems = m_selectionManager->selectedItems(); QCOMPARE(selectedItems.count(), 3); QVERIFY(selectedItems.contains(10)); QVERIFY(selectedItems.contains(11)); @@ -242,7 +242,7 @@ void KItemListSelectionManagerTest::testItemsRemoved() { // Select items 10 to 15 m_selectionManager->setSelected(10, 6); - QSet selectedItems = m_selectionManager->selectedItems(); + KItemSet selectedItems = m_selectionManager->selectedItems(); QCOMPARE(selectedItems.count(), 6); for (int i = 10; i <= 15; ++i) { QVERIFY(selectedItems.contains(i)); @@ -276,20 +276,20 @@ void KItemListSelectionManagerTest::testAnchoredSelection() m_selectionManager->setCurrentItem(6); QCOMPARE(m_selectionManager->currentItem(), 6); - QCOMPARE(m_selectionManager->selectedItems(), QSet() << 5 << 6); + QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 5 << 6); m_selectionManager->setCurrentItem(4); QCOMPARE(m_selectionManager->currentItem(), 4); - QCOMPARE(m_selectionManager->selectedItems(), QSet() << 4 << 5); + QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 4 << 5); m_selectionManager->setCurrentItem(7); QCOMPARE(m_selectionManager->currentItem(), 7); - QCOMPARE(m_selectionManager->selectedItems(), QSet() << 5 << 6 << 7); + QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 5 << 6 << 7); // Ending the anchored selection should not change the selected items. m_selectionManager->endAnchoredSelection(); QVERIFY(!m_selectionManager->isAnchoredSelectionActive()); - QCOMPARE(m_selectionManager->selectedItems(), QSet() << 5 << 6 << 7); + QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 5 << 6 << 7); // Start a new anchored selection that overlaps the previous one m_selectionManager->beginAnchoredSelection(9); @@ -298,15 +298,15 @@ void KItemListSelectionManagerTest::testAnchoredSelection() m_selectionManager->setCurrentItem(6); QCOMPARE(m_selectionManager->currentItem(), 6); - QCOMPARE(m_selectionManager->selectedItems(), QSet() << 5 << 6 << 7 << 8 << 9); + QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 5 << 6 << 7 << 8 << 9); m_selectionManager->setCurrentItem(10); QCOMPARE(m_selectionManager->currentItem(), 10); - QCOMPARE(m_selectionManager->selectedItems(), QSet() << 5 << 6 << 7 << 9 << 10); + QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 5 << 6 << 7 << 9 << 10); m_selectionManager->endAnchoredSelection(); QVERIFY(!m_selectionManager->isAnchoredSelectionActive()); - QCOMPARE(m_selectionManager->selectedItems(), QSet() << 5 << 6 << 7 << 9 << 10); + QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 5 << 6 << 7 << 9 << 10); } namespace { @@ -320,7 +320,7 @@ namespace { }; } -Q_DECLARE_METATYPE(QSet); +Q_DECLARE_METATYPE(KItemSet); Q_DECLARE_METATYPE(ChangeType); Q_DECLARE_METATYPE(KItemRange); Q_DECLARE_METATYPE(KItemRangeList); @@ -355,86 +355,86 @@ Q_DECLARE_METATYPE(QList); void KItemListSelectionManagerTest::testChangeSelection_data() { - QTest::addColumn >("initialSelection"); + QTest::addColumn("initialSelection"); QTest::addColumn("anchor"); QTest::addColumn("current"); - QTest::addColumn >("expectedSelection"); + QTest::addColumn("expectedSelection"); QTest::addColumn("changeType"); QTest::addColumn >("data"); - QTest::addColumn >("finalSelection"); + QTest::addColumn("finalSelection"); QTest::newRow("No change") - << (QSet() << 5 << 6) + << (KItemSet() << 5 << 6) << 2 << 3 - << (QSet() << 2 << 3 << 5 << 6) + << (KItemSet() << 2 << 3 << 5 << 6) << NoChange << QList() - << (QSet() << 2 << 3 << 5 << 6); + << (KItemSet() << 2 << 3 << 5 << 6); QTest::newRow("Insert Items") - << (QSet() << 5 << 6) + << (KItemSet() << 5 << 6) << 2 << 3 - << (QSet() << 2 << 3 << 5 << 6) + << (KItemSet() << 2 << 3 << 5 << 6) << InsertItems << (QList() << QVariant::fromValue(KItemRangeList() << KItemRange(1, 1) << KItemRange(5, 2) << KItemRange(10, 5))) - << (QSet() << 3 << 4 << 8 << 9); + << (KItemSet() << 3 << 4 << 8 << 9); QTest::newRow("Remove Items") - << (QSet() << 5 << 6) + << (KItemSet() << 5 << 6) << 2 << 3 - << (QSet() << 2 << 3 << 5 << 6) + << (KItemSet() << 2 << 3 << 5 << 6) << RemoveItems << (QList() << QVariant::fromValue(KItemRangeList() << KItemRange(1, 1) << KItemRange(3, 1) << KItemRange(10, 5))) - << (QSet() << 1 << 2 << 3 << 4); + << (KItemSet() << 1 << 2 << 3 << 4); QTest::newRow("Empty Anchored Selection") - << QSet() + << KItemSet() << 2 << 2 - << QSet() + << KItemSet() << EndAnchoredSelection << QList() - << QSet(); + << KItemSet(); QTest::newRow("Toggle selection") - << (QSet() << 1 << 3 << 4) + << (KItemSet() << 1 << 3 << 4) << 6 << 8 - << (QSet() << 1 << 3 << 4 << 6 << 7 << 8) + << (KItemSet() << 1 << 3 << 4 << 6 << 7 << 8) << SetSelected << (QList() << 0 << 10 << QVariant::fromValue(KItemListSelectionManager::Toggle)) - << (QSet() << 0 << 2 << 5 << 9); + << (KItemSet() << 0 << 2 << 5 << 9); // Swap items 2, 3 and 4, 5 QTest::newRow("Move items") - << (QSet() << 0 << 1 << 2 << 3) + << (KItemSet() << 0 << 1 << 2 << 3) << -1 << -1 - << (QSet() << 0 << 1 << 2 << 3) + << (KItemSet() << 0 << 1 << 2 << 3) << MoveItems << (QList() << QVariant::fromValue(KItemRange(2, 4)) << QVariant::fromValue(QList() << 4 << 5 << 2 << 3)) - << (QSet() << 0 << 1 << 4 << 5); + << (KItemSet() << 0 << 1 << 4 << 5); // Revert sort order QTest::newRow("Revert sort order") - << (QSet() << 0 << 1) + << (KItemSet() << 0 << 1) << 3 << 4 - << (QSet() << 0 << 1 << 3 << 4) + << (KItemSet() << 0 << 1 << 3 << 4) << MoveItems << (QList() << QVariant::fromValue(KItemRange(0, 10)) << QVariant::fromValue(QList() << 9 << 8 << 7 << 6 << 5 << 4 << 3 << 2 << 1 << 0)) - << (QSet() << 5 << 6 << 8 << 9); + << (KItemSet() << 5 << 6 << 8 << 9); } void KItemListSelectionManagerTest::testChangeSelection() { - QFETCH(QSet, initialSelection); + QFETCH(KItemSet, initialSelection); QFETCH(int, anchor); QFETCH(int, current); - QFETCH(QSet, expectedSelection); + QFETCH(KItemSet, expectedSelection); QFETCH(ChangeType, changeType); QFETCH(QList, data); - QFETCH(QSet, finalSelection); + QFETCH(KItemSet, finalSelection); - QSignalSpy spySelectionChanged(m_selectionManager, SIGNAL(selectionChanged(QSet,QSet))); + QSignalSpy spySelectionChanged(m_selectionManager, SIGNAL(selectionChanged(KItemSet,KItemSet))); // Initial selection should be empty QVERIFY(!m_selectionManager->hasSelection()); @@ -443,7 +443,7 @@ void KItemListSelectionManagerTest::testChangeSelection() // Perform the initial selectiion m_selectionManager->setSelectedItems(initialSelection); - verifySelectionChange(spySelectionChanged, initialSelection, QSet()); + verifySelectionChange(spySelectionChanged, initialSelection, KItemSet()); // Perform an anchored selection. // Note that current and anchor index are equal first because this is the case in typical uses of the @@ -486,7 +486,7 @@ void KItemListSelectionManagerTest::testChangeSelection() // Finally, clear the selection m_selectionManager->clearSelection(); - verifySelectionChange(spySelectionChanged, QSet(), finalSelection); + verifySelectionChange(spySelectionChanged, KItemSet(), finalSelection); } void KItemListSelectionManagerTest::testDeleteCurrentItem_data() @@ -520,8 +520,8 @@ void KItemListSelectionManagerTest::testDeleteCurrentItem() } void KItemListSelectionManagerTest::verifySelectionChange(QSignalSpy& spy, - const QSet& currentSelection, - const QSet& previousSelection) const + const KItemSet& currentSelection, + const KItemSet& previousSelection) const { QCOMPARE(m_selectionManager->selectedItems(), currentSelection); QCOMPARE(m_selectionManager->hasSelection(), !currentSelection.isEmpty()); @@ -540,8 +540,8 @@ void KItemListSelectionManagerTest::verifySelectionChange(QSignalSpy& spy, else { QCOMPARE(spy.count(), 1); QList arguments = spy.takeFirst(); - QCOMPARE(qvariant_cast >(arguments.at(0)), currentSelection); - QCOMPARE(qvariant_cast >(arguments.at(1)), previousSelection); + QCOMPARE(qvariant_cast(arguments.at(0)), currentSelection); + QCOMPARE(qvariant_cast(arguments.at(1)), previousSelection); } } diff --git a/src/tests/kitemsettest.cpp b/src/tests/kitemsettest.cpp new file mode 100644 index 0000000000..2832596ba6 --- /dev/null +++ b/src/tests/kitemsettest.cpp @@ -0,0 +1,612 @@ +/*************************************************************************** + * Copyright (C) 2013 by Frank Reininghaus * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include + +#include "kitemviews/kitemset.h" + +#include + +Q_DECLARE_METATYPE(KItemRangeList); + +/** + * Converts a KItemRangeList to a KItemSet. + */ +KItemSet KItemRangeList2KItemSet(const KItemRangeList& itemRanges) +{ + KItemSet result; + foreach (const KItemRange& range, itemRanges) { + for (int i = range.index; i < range.index + range.count; ++i) { + result.insert(i); + } + } + return result; +} + +/** + * Converts a KItemRangeList to a QSet. + */ +QSet KItemRangeList2QSet(const KItemRangeList& itemRanges) +{ + QSet result; + foreach (const KItemRange& range, itemRanges) { + for (int i = range.index; i < range.index + range.count; ++i) { + result.insert(i); + } + } + return result; +} + +/** + * Converts a KItemRangeList to a QVector. + */ +QVector KItemRangeList2QVector(const KItemRangeList& itemRanges) +{ + QVector result; + foreach (const KItemRange& range, itemRanges) { + for (int i = range.index; i < range.index + range.count; ++i) { + result.append(i); + } + } + return result; +} + +/** + * Converts a KItemSet to a QSet. + */ +static QSet KItemSet2QSet(const KItemSet& itemSet) +{ + QSet result; + foreach (int i, itemSet) { + result.insert(i); + } + + // Check that the conversion was successful. + Q_ASSERT(itemSet.count() == result.count()); + + foreach (int i, itemSet) { + Q_ASSERT(result.contains(i)); + } + + foreach (int i, result) { + Q_ASSERT(itemSet.contains(i)); + } + + return result; +} + + +/** + * The main test class. + */ +class KItemSetTest : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + + void testConstruction_data(); + void testConstruction(); + void testIterators_data(); + void testIterators(); + void testFind_data(); + void testFind(); + void testChangingOneItem_data(); + void testChangingOneItem(); + void testAddSets_data(); + void testAddSets(); + /* + void testSubtractSets_data(); + void testSubtractSets(); + */ + void testSymmetricDifference_data(); + void testSymmetricDifference(); + +private: + QHash m_testCases; +}; + +void KItemSetTest::initTestCase() +{ + m_testCases.insert("empty", KItemRangeList()); + m_testCases.insert("[0]", KItemRangeList() << KItemRange(0, 1)); + m_testCases.insert("[1]", KItemRangeList() << KItemRange(1, 1)); + m_testCases.insert("[1, 2]", KItemRangeList() << KItemRange(1, 2)); + m_testCases.insert("[1, 2] [5]", KItemRangeList() << KItemRange(1, 2) << KItemRange(5, 1)); + m_testCases.insert("[1] [4, 5]", KItemRangeList() << KItemRange(1, 1) << KItemRange(4, 2)); + m_testCases.insert("[1, 2] [4, 5]", KItemRangeList() << KItemRange(1, 2) << KItemRange(4, 2)); + m_testCases.insert("[1, 5]", KItemRangeList() << KItemRange(1, 5)); + m_testCases.insert("[1, 2] [4, 5] [7] [9, 10] [13] [20, 25] [30]", + KItemRangeList() << KItemRange(1, 2) << KItemRange(4, 2) << KItemRange(7, 1) << KItemRange(9, 2) << KItemRange(20, 6) << KItemRange(30, 1)); + m_testCases.insert("[-10, -1]", KItemRangeList() << KItemRange(-10, 10)); + m_testCases.insert("[-10, 0]", KItemRangeList() << KItemRange(-10, 11)); + m_testCases.insert("[-10, 1]", KItemRangeList() << KItemRange(-10, 12)); + m_testCases.insert("[0, 9]", KItemRangeList() << KItemRange(0, 10)); + m_testCases.insert("[0, 19]", KItemRangeList() << KItemRange(0, 10)); +} + +void KItemSetTest::testConstruction_data() +{ + QTest::addColumn("itemRanges"); + + QHash::const_iterator it = m_testCases.constBegin(); + const QHash::const_iterator end = m_testCases.constEnd(); + + while (it != end) { + QTest::newRow(it.key()) << it.value(); + ++it; + } +} + +void KItemSetTest::testConstruction() +{ + QFETCH(KItemRangeList, itemRanges); + + KItemSet itemSet = KItemRangeList2KItemSet(itemRanges); + QSet itemsQSet = KItemRangeList2QSet(itemRanges); + + QVERIFY(itemSet.isValid()); + QVERIFY(itemSet.count() == itemsQSet.count()); + QCOMPARE(KItemSet2QSet(itemSet), itemsQSet); + + // Test copy constructor. + KItemSet copy(itemSet); + QCOMPARE(itemSet, copy); + copy.clear(); + QVERIFY(itemSet != copy || itemSet.isEmpty()); + + // Clear the set. + itemSet.clear(); + QVERIFY(itemSet.isEmpty()); + QCOMPARE(itemSet.count(), 0); +} + +void KItemSetTest::testIterators_data() +{ + QTest::addColumn("itemRanges"); + + QHash::const_iterator it = m_testCases.constBegin(); + const QHash::const_iterator end = m_testCases.constEnd(); + + while (it != end) { + QTest::newRow(it.key()) << it.value(); + ++it; + } +} + +/** + * Verify that the iterators work exactly like their counterparts for the + * equivalent QVector. + */ +void KItemSetTest::testIterators() +{ + QFETCH(KItemRangeList, itemRanges); + + KItemSet itemSet = KItemRangeList2KItemSet(itemRanges); + QVector itemsQVector = KItemRangeList2QVector(itemRanges); + + QVERIFY(itemSet.isValid()); + QVERIFY(itemSet.count() == itemsQVector.count()); + + if (itemSet.count() == 0) { + QVERIFY(itemSet.isEmpty()); + QVERIFY(itemSet.begin() == itemSet.end()); + QVERIFY(itemSet.constBegin() == itemSet.constEnd()); + } else { + QVERIFY(!itemSet.isEmpty()); + QVERIFY(itemSet.begin() != itemSet.end()); + QVERIFY(itemSet.constBegin() != itemSet.constEnd()); + + const int min = itemsQVector.first(); + const int max = itemsQVector.last(); + + QCOMPARE(*itemSet.begin(), min); + QCOMPARE(*itemSet.constBegin(), min); + QCOMPARE(itemSet.first(), min); + + QCOMPARE(*(--itemSet.end()), max); + QCOMPARE(*(--itemSet.constEnd()), max); + QCOMPARE(itemSet.last(), max); + } + + // Test iterating using the different iterators. + QVector testQVector; + for (KItemSet::iterator it = itemSet.begin(), end = itemSet.end(); it != end; ++it) { + testQVector.append(*it); + } + QCOMPARE(testQVector, itemsQVector); + + testQVector.clear(); + for (KItemSet::const_iterator it = itemSet.constBegin(), end = itemSet.constEnd(); it != end; ++it) { + testQVector.append(*it); + } + QCOMPARE(testQVector, itemsQVector); + + testQVector.clear(); + foreach (int i, itemSet) { + testQVector.append(i); + } + QCOMPARE(testQVector, itemsQVector); + + // Verify that both variants of the (const)iterator's operator++ and + // operator-- functions behave exactly like their QVector equivalents. + KItemSet::iterator it1 = itemSet.begin(); + KItemSet::iterator it2 = itemSet.begin(); + KItemSet::const_iterator constIt1 = itemSet.constBegin(); + KItemSet::const_iterator constIt2 = itemSet.constBegin(); + QVector::iterator vectorIt1 = itemsQVector.begin(); + QVector::iterator vectorIt2 = itemsQVector.begin(); + QVector::const_iterator vectorConstIt1 = itemsQVector.constBegin(); + QVector::const_iterator vectorConstIt2 = itemsQVector.constBegin(); + + while (it1 != itemSet.end()) { + if (it1 != --itemSet.end()) { + QCOMPARE(*(++it1), *(++vectorIt1)); + QCOMPARE(*(++constIt1), *(++vectorConstIt1)); + } else { + QCOMPARE(++it1, itemSet.end()); + QCOMPARE(++vectorIt1, itemsQVector.end()); + QCOMPARE(++constIt1, itemSet.constEnd()); + QCOMPARE(++vectorConstIt1, itemsQVector.constEnd()); + } + + QCOMPARE(*(it2++), *(vectorIt2++)); + QCOMPARE(*(constIt2++), *(vectorConstIt2++)); + + QCOMPARE(it1, it2); + QCOMPARE(constIt1, constIt2); + QCOMPARE(KItemSet::const_iterator(it1), constIt1); + } + + QCOMPARE(it1, itemSet.end()); + QCOMPARE(it2, itemSet.end()); + QCOMPARE(constIt1, itemSet.constEnd()); + QCOMPARE(constIt2, itemSet.constEnd()); + QCOMPARE(vectorIt1, itemsQVector.end()); + QCOMPARE(vectorIt2, itemsQVector.end()); + QCOMPARE(vectorConstIt1, itemsQVector.constEnd()); + QCOMPARE(vectorConstIt2, itemsQVector.constEnd()); + + while (it1 != itemSet.begin()) { + QCOMPARE(*(--it1), *(--vectorIt1)); + QCOMPARE(*(--constIt1), *(--vectorConstIt1)); + + if (it2 != itemSet.end()) { + QCOMPARE(*(it2--), *(vectorIt2--)); + QCOMPARE(*(constIt2--), *(vectorConstIt2--)); + } else { + QCOMPARE(it2--, itemSet.end()); + QCOMPARE(vectorIt2--, itemsQVector.end()); + QCOMPARE(constIt2--, itemSet.constEnd()); + QCOMPARE(vectorConstIt2--, itemsQVector.constEnd()); + } + + QCOMPARE(it1, it2); + QCOMPARE(constIt1, constIt2); + QCOMPARE(KItemSet::const_iterator(it1), constIt1); + } + + QCOMPARE(it1, itemSet.begin()); + QCOMPARE(it2, itemSet.begin()); + QCOMPARE(constIt1, itemSet.constBegin()); + QCOMPARE(constIt2, itemSet.constBegin()); + QCOMPARE(vectorIt1, itemsQVector.begin()); + QCOMPARE(vectorIt2, itemsQVector.begin()); + QCOMPARE(vectorConstIt1, itemsQVector.constBegin()); + QCOMPARE(vectorConstIt2, itemsQVector.constBegin()); +} + +void KItemSetTest::testFind_data() +{ + QTest::addColumn("itemRanges"); + + QHash::const_iterator it = m_testCases.constBegin(); + const QHash::const_iterator end = m_testCases.constEnd(); + + while (it != end) { + QTest::newRow(it.key()) << it.value(); + ++it; + } +} + +/** + * Test all functions that find items: + * contais(int), find(int), constFind(int) + */ +void KItemSetTest::testFind() +{ + QFETCH(KItemRangeList, itemRanges); + + KItemSet itemSet = KItemRangeList2KItemSet(itemRanges); + QSet itemsQSet = KItemRangeList2QSet(itemRanges); + + QVERIFY(itemSet.isValid()); + QVERIFY(itemSet.count() == itemsQSet.count()); + + // Find the minimum and maximum items. + int min; + int max; + + if (itemSet.count() == 0) { + // Use some arbitrary values for the upcoming tests. + min = 0; + max = 5; + } else { + min = *itemSet.begin(); + max = *(--itemSet.end()); + } + + // Test contains(int), find(int), and constFind(int) + // for items between min - 2 and max + 2. + for (int i = min - 2; i <= max + 2; ++i) { + const KItemSet::iterator it = itemSet.find(i); + const KItemSet::const_iterator constIt = itemSet.constFind(i); + QCOMPARE(KItemSet::const_iterator(it), constIt); + + if (itemsQSet.contains(i)) { + QVERIFY(itemSet.contains(i)); + QCOMPARE(*it, i); + QCOMPARE(*constIt, i); + } else { + QVERIFY(!itemSet.contains(i)); + QCOMPARE(it, itemSet.end()); + QCOMPARE(constIt, itemSet.constEnd()); + } + } +} + +void KItemSetTest::testChangingOneItem_data() +{ + QTest::addColumn("itemRanges"); + + QHash::const_iterator it = m_testCases.constBegin(); + const QHash::const_iterator end = m_testCases.constEnd(); + + while (it != end) { + QTest::newRow(it.key()) << it.value(); + ++it; + } +} + +/** + * Test all functions that change a single item: + * insert(int), remove(int), erase(KItemSet::iterator) + */ +void KItemSetTest::testChangingOneItem() +{ + QFETCH(KItemRangeList, itemRanges); + + KItemSet itemSet = KItemRangeList2KItemSet(itemRanges); + QSet itemsQSet = KItemRangeList2QSet(itemRanges); + + QVERIFY(itemSet.isValid()); + QVERIFY(itemSet.count() == itemsQSet.count()); + + // Find the minimum and maximum items. + int min; + int max; + + if (itemSet.count() == 0) { + // Use some arbitrary values for the upcoming tests. + min = 0; + max = 5; + } else { + min = *itemSet.begin(); + max = *(--itemSet.end()); + } + + // Test insert(int), remove(int), and erase(KItemSet::iterator) + // for items between min - 2 and max + 2. + for (int i = min - 2; i <= max + 2; ++i) { + + // Test insert(int). + { + KItemSet tmp(itemSet); + const KItemSet::iterator insertedIt = tmp.insert(i); + QCOMPARE(*insertedIt, i); + + QVERIFY(tmp.isValid()); + QVERIFY(tmp.contains(i)); + + QSet expectedQSet = itemsQSet; + expectedQSet.insert(i); + QCOMPARE(KItemSet2QSet(tmp), expectedQSet); + + if (!itemSet.contains(i)) { + QVERIFY(itemSet != tmp); + QCOMPARE(tmp.count(), itemSet.count() + 1); + } else { + QCOMPARE(itemSet, tmp); + } + + QCOMPARE(i, *tmp.find(i)); + QCOMPARE(i, *tmp.constFind(i)); + + // Erase the new item and check that we get the old KItemSet back. + tmp.erase(tmp.find(i)); + QVERIFY(tmp.isValid()); + QVERIFY(!tmp.contains(i)); + + if (!itemSet.contains(i)) { + QCOMPARE(itemSet, tmp); + } + + expectedQSet.remove(i); + QCOMPARE(KItemSet2QSet(tmp), expectedQSet); + } + + // Test remove(int). + { + KItemSet tmp(itemSet); + const bool removed = tmp.remove(i); + + QCOMPARE(removed, itemSet.contains(i)); + + QVERIFY(tmp.isValid()); + QVERIFY(!tmp.contains(i)); + + QSet expectedQSet = itemsQSet; + expectedQSet.remove(i); + QCOMPARE(KItemSet2QSet(tmp), expectedQSet); + + if (itemSet.contains(i)) { + QVERIFY(itemSet != tmp); + QCOMPARE(tmp.count(), itemSet.count() - 1); + } else { + QCOMPARE(itemSet, tmp); + } + + QCOMPARE(tmp.end(), tmp.find(i)); + QCOMPARE(tmp.constEnd(), tmp.constFind(i)); + } + + // Test erase(KItemSet::iterator). + if (itemSet.contains(i)) { + KItemSet tmp(itemSet); + KItemSet::iterator it = tmp.find(i); + it = tmp.erase(it); + + QVERIFY(tmp.isValid()); + QVERIFY(!tmp.contains(i)); + + QSet expectedQSet = itemsQSet; + expectedQSet.remove(i); + QCOMPARE(KItemSet2QSet(tmp), expectedQSet); + + if (itemSet.contains(i)) { + QVERIFY(itemSet != tmp); + QCOMPARE(tmp.count(), itemSet.count() - 1); + } else { + QCOMPARE(itemSet, tmp); + } + + QCOMPARE(tmp.end(), tmp.find(i)); + QCOMPARE(tmp.constEnd(), tmp.constFind(i)); + + // Check the returen value, now contained in 'it'. + if (i == max) { + QCOMPARE(it, tmp.end()); + } else { + // it now points to the next item. + QVERIFY(tmp.contains(*it)); + for (int j = i; j < *it; ++j) { + QVERIFY(!tmp.contains(j)); + } + } + } + } + + // Clear the set. + itemSet.clear(); + QVERIFY(itemSet.isEmpty()); + QCOMPARE(itemSet.count(), 0); +} + +void KItemSetTest::testAddSets_data() +{ + QTest::addColumn("itemRanges1"); + QTest::addColumn("itemRanges2"); + + QHash::const_iterator it1 = m_testCases.constBegin(); + const QHash::const_iterator end = m_testCases.constEnd(); + + while (it1 != end) { + QHash::const_iterator it2 = m_testCases.constBegin(); + + while (it2 != end) { + QByteArray name = it1.key() + QByteArray(" + ") + it2.key(); + QTest::newRow(name) << it1.value() << it2.value(); + ++it2; + } + + ++it1; + } +} + +void KItemSetTest::testAddSets() +{ + QFETCH(KItemRangeList, itemRanges1); + QFETCH(KItemRangeList, itemRanges2); + + KItemSet itemSet1 = KItemRangeList2KItemSet(itemRanges1); + QSet itemsQSet1 = KItemRangeList2QSet(itemRanges1); + + KItemSet itemSet2 = KItemRangeList2KItemSet(itemRanges2); + QSet itemsQSet2 = KItemRangeList2QSet(itemRanges2); + + KItemSet sum = itemSet1 + itemSet2; + QSet sumQSet = itemsQSet1 + itemsQSet2; + + QCOMPARE(sum.count(), sumQSet.count()); + QCOMPARE(KItemSet2QSet(sum), sumQSet); +} + +void KItemSetTest::testSymmetricDifference_data() +{ + QTest::addColumn("itemRanges1"); + QTest::addColumn("itemRanges2"); + + QHash::const_iterator it1 = m_testCases.constBegin(); + const QHash::const_iterator end = m_testCases.constEnd(); + + while (it1 != end) { + QHash::const_iterator it2 = m_testCases.constBegin(); + + while (it2 != end) { + QByteArray name = it1.key() + QByteArray(" ^ ") + it2.key(); + QTest::newRow(name) << it1.value() << it2.value(); + ++it2; + } + + ++it1; + } +} + +void KItemSetTest::testSymmetricDifference() +{ + QFETCH(KItemRangeList, itemRanges1); + QFETCH(KItemRangeList, itemRanges2); + + KItemSet itemSet1 = KItemRangeList2KItemSet(itemRanges1); + QSet itemsQSet1 = KItemRangeList2QSet(itemRanges1); + + KItemSet itemSet2 = KItemRangeList2KItemSet(itemRanges2); + QSet itemsQSet2 = KItemRangeList2QSet(itemRanges2); + + KItemSet symmetricDifference = itemSet1 ^ itemSet2; + QSet symmetricDifferenceQSet = (itemsQSet1 - itemsQSet2) + (itemsQSet2 - itemsQSet1); + + QCOMPARE(symmetricDifference.count(), symmetricDifferenceQSet.count()); + QCOMPARE(KItemSet2QSet(symmetricDifference), symmetricDifferenceQSet); + + // Check commutativity. + QCOMPARE(itemSet2 ^ itemSet1, symmetricDifference); + + // Some more checks: + // itemSet1 ^ symmetricDifference == itemSet2, + // itemSet2 ^ symmetricDifference == itemSet1. + QCOMPARE(itemSet1 ^ symmetricDifference, itemSet2); + QCOMPARE(itemSet2 ^ symmetricDifference, itemSet1); +} + + +QTEST_KDEMAIN(KItemSetTest, NoGUI) + +#include "kitemsettest.moc" diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index fd149e0f6a..d0a85b3e26 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -145,7 +145,7 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) : controller->setSelectionBehavior(KItemListController::MultiSelection); connect(controller, SIGNAL(itemActivated(int)), this, SLOT(slotItemActivated(int))); - connect(controller, SIGNAL(itemsActivated(QSet)), this, SLOT(slotItemsActivated(QSet))); + connect(controller, SIGNAL(itemsActivated(KItemSet)), this, SLOT(slotItemsActivated(KItemSet))); connect(controller, SIGNAL(itemMiddleClicked(int)), this, SLOT(slotItemMiddleClicked(int))); connect(controller, SIGNAL(itemContextMenuRequested(int,QPointF)), this, SLOT(slotItemContextMenuRequested(int,QPointF))); connect(controller, SIGNAL(viewContextMenuRequested(QPointF)), this, SLOT(slotViewContextMenuRequested(QPointF))); @@ -184,8 +184,8 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) : this, SLOT(slotHeaderColumnWidthChanged(QByteArray,qreal,qreal))); KItemListSelectionManager* selectionManager = controller->selectionManager(); - connect(selectionManager, SIGNAL(selectionChanged(QSet,QSet)), - this, SLOT(slotSelectionChanged(QSet,QSet))); + connect(selectionManager, SIGNAL(selectionChanged(KItemSet,KItemSet)), + this, SLOT(slotSelectionChanged(KItemSet,KItemSet))); m_toolTipManager = new ToolTipManager(this); @@ -350,14 +350,9 @@ int DolphinView::itemsCount() const KFileItemList DolphinView::selectedItems() const { const KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager(); - QList selectedIndexes = selectionManager->selectedItems().toList(); - - qSort(selectedIndexes); KFileItemList selectedItems; - QListIterator it(selectedIndexes); - while (it.hasNext()) { - const int index = it.next(); + foreach (int index, selectionManager->selectedItems()) { selectedItems.append(m_model->fileItem(index)); } return selectedItems; @@ -390,9 +385,9 @@ void DolphinView::selectItems(const QRegExp& pattern, bool enabled) for (int index = 0; index < m_model->count(); index++) { const KFileItem item = m_model->fileItem(index); if (pattern.exactMatch(item.text())) { - // An alternative approach would be to store the matching items in a QSet and + // An alternative approach would be to store the matching items in a KItemSet and // select them in one go after the loop, but we'd need a new function - // KItemListSelectionManager::setSelected(QSet, SelectionMode mode) + // KItemListSelectionManager::setSelected(KItemSet, SelectionMode mode) // for that. selectionManager->setSelected(index, 1, mode); } @@ -803,7 +798,7 @@ void DolphinView::slotItemActivated(int index) } } -void DolphinView::slotItemsActivated(const QSet& indexes) +void DolphinView::slotItemsActivated(const KItemSet& indexes) { Q_ASSERT(indexes.count() >= 2); @@ -818,9 +813,7 @@ void DolphinView::slotItemsActivated(const QSet& indexes) KFileItemList items; items.reserve(indexes.count()); - QSetIterator it(indexes); - while (it.hasNext()) { - const int index = it.next(); + foreach (int index, indexes) { KFileItem item = m_model->fileItem(index); const KUrl& url = openItemAsFolderUrl(item); @@ -1104,7 +1097,7 @@ void DolphinView::slotAboutToCreate(const KUrl::List& urls) } } -void DolphinView::slotSelectionChanged(const QSet& current, const QSet& previous) +void DolphinView::slotSelectionChanged(const KItemSet& current, const KItemSet& previous) { const int currentCount = current.count(); const int previousCount = previous.count(); @@ -1323,7 +1316,7 @@ void DolphinView::updateViewState() m_clearSelectionBeforeSelectingNewItems = false; } - QSet selectedItems = selectionManager->selectedItems(); + KItemSet selectedItems = selectionManager->selectedItems(); QList::iterator it = m_selectedUrls.begin(); while (it != m_selectedUrls.end()) { @@ -1659,7 +1652,7 @@ KUrl::List DolphinView::simplifiedSelectedUrls() const QMimeData* DolphinView::selectionMimeData() const { const KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager(); - const QSet selectedIndexes = selectionManager->selectedItems(); + const KItemSet selectedIndexes = selectionManager->selectedItems(); return m_model->createMimeData(selectedIndexes); } diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h index a6f969bc1b..b43957f226 100644 --- a/src/views/dolphinview.h +++ b/src/views/dolphinview.h @@ -34,7 +34,6 @@ #include #include #include -#include #include typedef KIO::FileUndoManager::CommandType CommandType; @@ -45,6 +44,7 @@ class KActionCollection; class KFileItemModel; class KItemListContainer; class KItemModelBase; +class KItemSet; class KUrl; class ToolTipManager; class VersionControlObserver; @@ -563,7 +563,7 @@ private slots: void activate(); void slotItemActivated(int index); - void slotItemsActivated(const QSet& indexes); + void slotItemsActivated(const KItemSet& indexes); void slotItemMiddleClicked(int index); void slotItemContextMenuRequested(int index, const QPointF& pos); void slotViewContextMenuRequested(const QPointF& pos); @@ -587,7 +587,7 @@ private slots: * the signal is emitted only after no selection change has been done * within a small delay. */ - void slotSelectionChanged(const QSet& current, const QSet& previous); + void slotSelectionChanged(const KItemSet& current, const KItemSet& previous); /** * Is called by emitDelayedSelectionChangedSignal() and emits the