mirror of
https://invent.kde.org/system/dolphin
synced 2024-09-12 12:54:29 +00:00
Store the selected items in a more efficient way
Since Dolphin 2.0, we have stored the selected items in a QSet<int>, which is neither space-efficient nor particularly fast when inserting many items which are in a consecutive range. This commit replaces the QSet<int> by a new class "KItemSet", which stores the items in a sorted list of ranges. For each range, we only store the first index and the length of the range, so we need a lot less memory for most common selection patterns, and we also save quite a few CPU cycles in many situations, because adding an item to the KItemSet will in many cases not need a memory allocation at all, and it's particularly easy when inserting sorted items into the KItemSet in a row. KItemSet contains a minimal subset of QSet's API which makes it suitable as a drop-in replacement for our needs. It also has iterators, such that the items can be iterated through easily, also with foreach. One advantage of KItemSet compared to QSet<int> is that the items are always iterated through in ascending order. REVIEW: 113488
This commit is contained in:
parent
903381a898
commit
fc2ab47898
|
@ -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
|
||||
|
|
|
@ -119,7 +119,7 @@ QStringList KFileItemListView::enabledPlugins() const
|
|||
return m_modelRolesUpdater ? m_modelRolesUpdater->enabledPlugins() : QStringList();
|
||||
}
|
||||
|
||||
QPixmap KFileItemListView::createDragPixmap(const QSet<int>& indexes) const
|
||||
QPixmap KFileItemListView::createDragPixmap(const KItemSet& indexes) const
|
||||
{
|
||||
if (!model()) {
|
||||
return QPixmap();
|
||||
|
@ -165,10 +165,8 @@ QPixmap KFileItemListView::createDragPixmap(const QSet<int>& indexes) const
|
|||
QPainter painter(&dragPixmap);
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
QSetIterator<int> it(indexes);
|
||||
while (it.hasNext()) {
|
||||
const int index = it.next();
|
||||
|
||||
foreach (int index, indexes) {
|
||||
QPixmap pixmap = model()->data(index).value("iconPixmap").value<QPixmap>();
|
||||
if (pixmap.isNull()) {
|
||||
KIcon icon(model()->data(index).value("iconName").toString());
|
||||
|
|
|
@ -73,7 +73,7 @@ public:
|
|||
QStringList enabledPlugins() const;
|
||||
|
||||
/** @reimp */
|
||||
virtual QPixmap createDragPixmap(const QSet<int>& indexes) const;
|
||||
virtual QPixmap createDragPixmap(const KItemSet& indexes) const;
|
||||
|
||||
protected:
|
||||
virtual KItemListWidgetCreatorBase* defaultWidgetCreator() const;
|
||||
|
|
|
@ -237,7 +237,7 @@ bool KFileItemModel::showDirectoriesOnly() const
|
|||
return m_dirLister->dirOnlyMode();
|
||||
}
|
||||
|
||||
QMimeData* KFileItemModel::createMimeData(const QSet<int>& indexes) const
|
||||
QMimeData* KFileItemModel::createMimeData(const KItemSet& indexes) const
|
||||
{
|
||||
QMimeData* data = new QMimeData();
|
||||
|
||||
|
@ -248,9 +248,7 @@ QMimeData* KFileItemModel::createMimeData(const QSet<int>& indexes) const
|
|||
KUrl::List mostLocalUrls;
|
||||
bool canUseMostLocalUrls = true;
|
||||
|
||||
QSetIterator<int> 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();
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <kitemviews/private/kfileitemmodelfilter.h>
|
||||
|
||||
#include <QHash>
|
||||
#include <QSet>
|
||||
|
||||
class KFileItemModelDirLister;
|
||||
class QTimer;
|
||||
|
@ -99,7 +100,7 @@ public:
|
|||
bool showDirectoriesOnly() const;
|
||||
|
||||
/** @reimp */
|
||||
virtual QMimeData* createMimeData(const QSet<int>& indexes) const;
|
||||
virtual QMimeData* createMimeData(const KItemSet& indexes) const;
|
||||
|
||||
/** @reimp */
|
||||
virtual int indexForKeyboardSearch(const QString& text, int startFromIndex = 0) const;
|
||||
|
|
|
@ -364,11 +364,11 @@ bool KItemListController::keyPressEvent(QKeyEvent* event)
|
|||
|
||||
case Qt::Key_Enter:
|
||||
case Qt::Key_Return: {
|
||||
const QSet<int> 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<int> 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<int> 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<int> selectedItems = m_selectionManager->selectedItems();
|
||||
const KItemSet selectedItems = m_selectionManager->selectedItems();
|
||||
if (selectedItems.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -25,10 +25,11 @@
|
|||
|
||||
#include <libdolphin_export.h>
|
||||
|
||||
#include "kitemset.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QPixmap>
|
||||
#include <QPointF>
|
||||
#include <QSet>
|
||||
|
||||
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<int>& 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<int> m_oldSelection;
|
||||
KItemSet m_oldSelection;
|
||||
|
||||
/**
|
||||
* Assuming a view is given with a vertical scroll-orientation, grouped items and
|
||||
|
|
|
@ -43,7 +43,7 @@ KItemListSelectionManager::~KItemListSelectionManager()
|
|||
void KItemListSelectionManager::setCurrentItem(int current)
|
||||
{
|
||||
const int previous = m_currentItem;
|
||||
const QSet<int> 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<int> 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<int>& items)
|
||||
void KItemListSelectionManager::setSelectedItems(const KItemSet& items)
|
||||
{
|
||||
if (m_selectedItems != items) {
|
||||
const QSet<int> previous = m_selectedItems;
|
||||
const KItemSet previous = m_selectedItems;
|
||||
m_selectedItems = items;
|
||||
emit selectionChanged(m_selectedItems, previous);
|
||||
}
|
||||
}
|
||||
|
||||
QSet<int> KItemListSelectionManager::selectedItems() const
|
||||
KItemSet KItemListSelectionManager::selectedItems() const
|
||||
{
|
||||
QSet<int> 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<int> 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<int> 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<int> previous = selectedItems();
|
||||
const KItemSet previous = selectedItems();
|
||||
if (!previous.isEmpty()) {
|
||||
m_selectedItems.clear();
|
||||
m_isAnchoredSelectionActive = false;
|
||||
emit selectionChanged(QSet<int>(), 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<int> 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<int> previous = m_selectedItems;
|
||||
const KItemSet previous = m_selectedItems;
|
||||
m_selectedItems.clear();
|
||||
m_selectedItems.reserve(previous.count());
|
||||
QSetIterator<int> 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<int> 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<int> 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<int> previous = m_selectedItems;
|
||||
const KItemSet previous = m_selectedItems;
|
||||
m_selectedItems.clear();
|
||||
m_selectedItems.reserve(previous.count());
|
||||
QSetIterator<int> 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<int> 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<int>& movedToIndexes)
|
||||
{
|
||||
// Store the current selection (needed in the selectionChanged() signal)
|
||||
const QSet<int> 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<int> previous = m_selectedItems;
|
||||
const KItemSet previous = m_selectedItems;
|
||||
m_selectedItems.clear();
|
||||
m_selectedItems.reserve(previous.count());
|
||||
QSetIterator<int> 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<int> selection = selectedItems();
|
||||
const KItemSet selection = selectedItems();
|
||||
if (selection != previousSelection) {
|
||||
emit selectionChanged(selection, previousSelection);
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@
|
|||
#include <libdolphin_export.h>
|
||||
|
||||
#include <kitemviews/kitemmodelbase.h>
|
||||
#include <kitemviews/kitemset.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
|
||||
class KItemModelBase;
|
||||
|
||||
|
@ -57,8 +57,8 @@ public:
|
|||
void setCurrentItem(int current);
|
||||
int currentItem() const;
|
||||
|
||||
void setSelectedItems(const QSet<int>& items);
|
||||
QSet<int> 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<int>& current, const QSet<int>& 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<int> m_selectedItems;
|
||||
KItemSet m_selectedItems;
|
||||
bool m_isAnchoredSelectionActive;
|
||||
|
||||
KItemModelBase* m_model;
|
||||
|
|
|
@ -609,12 +609,12 @@ KItemListHeader* KItemListView::header() const
|
|||
return m_header;
|
||||
}
|
||||
|
||||
QPixmap KItemListView::createDragPixmap(const QSet<int>& 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<int>& current, const QSet<int>& 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<int>,QSet<int>)), this, SLOT(slotSelectionChanged(QSet<int>,QSet<int>)));
|
||||
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<int>,QSet<int>)), this, SLOT(slotSelectionChanged(QSet<int>,QSet<int>)));
|
||||
connect(selectionManager, SIGNAL(selectionChanged(KItemSet,KItemSet)), this, SLOT(slotSelectionChanged(KItemSet,KItemSet)));
|
||||
}
|
||||
|
||||
onControllerChanged(controller, previous);
|
||||
|
|
|
@ -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<int>& 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<int>& current, const QSet<int>& previous);
|
||||
virtual void slotSelectionChanged(const KItemSet& current, const KItemSet& previous);
|
||||
|
||||
private slots:
|
||||
void slotAnimationFinished(QGraphicsWidget* widget,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -123,7 +123,7 @@ int KItemModelBase::expandedParentsCount(int index) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
QMimeData* KItemModelBase::createMimeData(const QSet<int>& indexes) const
|
||||
QMimeData* KItemModelBase::createMimeData(const KItemSet& indexes) const
|
||||
{
|
||||
Q_UNUSED(indexes);
|
||||
return 0;
|
||||
|
|
|
@ -26,10 +26,10 @@
|
|||
#include <libdolphin_export.h>
|
||||
|
||||
#include <kitemviews/kitemrange.h>
|
||||
#include <kitemviews/kitemset.h>
|
||||
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QVariant>
|
||||
|
||||
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<int>& indexes) const;
|
||||
virtual QMimeData* createMimeData(const KItemSet& indexes) const;
|
||||
|
||||
/**
|
||||
* @return Reimplement this to return the index for the first item
|
||||
|
|
348
src/kitemviews/kitemset.cpp
Normal file
348
src/kitemviews/kitemset.cpp
Normal file
|
@ -0,0 +1,348 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2013 by Frank Reininghaus <frank78ac@googlemail.com> *
|
||||
* *
|
||||
* 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 <QVector>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
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<int> rangeBoundaries;
|
||||
rangeBoundaries.resize(2 * (m_itemRanges.count() + other.m_itemRanges.count()));
|
||||
const QVector<int>::iterator begin = rangeBoundaries.begin();
|
||||
const QVector<int>::iterator end = rangeBoundaries.end();
|
||||
QVector<int>::iterator it = begin;
|
||||
|
||||
foreach (const KItemRange& range, m_itemRanges) {
|
||||
*it++ = range.index;
|
||||
*it++ = range.index + range.count;
|
||||
}
|
||||
|
||||
const QVector<int>::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;
|
||||
}
|
413
src/kitemviews/kitemset.h
Normal file
413
src/kitemviews/kitemset.h
Normal file
|
@ -0,0 +1,413 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2013 by Frank Reininghaus <frank78ac@googlemail.com> *
|
||||
* *
|
||||
* 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 <kitemviews/kitemrange.h>
|
||||
|
||||
/**
|
||||
* @brief Stores a set of integer numbers in a space-efficient way.
|
||||
*
|
||||
* This class is similar to QSet<int>, but it has the following advantages:
|
||||
*
|
||||
* 1. It uses less memory than a QSet<int> 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
|
|
@ -175,7 +175,7 @@ bool KStandardItemModel::setData(int index, const QHash<QByteArray, QVariant>& v
|
|||
return true;
|
||||
}
|
||||
|
||||
QMimeData* KStandardItemModel::createMimeData(const QSet<int>& indexes) const
|
||||
QMimeData* KStandardItemModel::createMimeData(const KItemSet& indexes) const
|
||||
{
|
||||
Q_UNUSED(indexes);
|
||||
return 0;
|
||||
|
|
|
@ -72,7 +72,7 @@ public:
|
|||
virtual int count() const;
|
||||
virtual QHash<QByteArray, QVariant> data(int index) const;
|
||||
virtual bool setData(int index, const QHash<QByteArray, QVariant>& values);
|
||||
virtual QMimeData* createMimeData(const QSet<int>& 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;
|
||||
|
|
|
@ -377,7 +377,7 @@ void PlacesItemModel::requestStorageSetup(int index)
|
|||
}
|
||||
}
|
||||
|
||||
QMimeData* PlacesItemModel::createMimeData(const QSet<int>& indexes) const
|
||||
QMimeData* PlacesItemModel::createMimeData(const KItemSet& indexes) const
|
||||
{
|
||||
KUrl::List urls;
|
||||
QByteArray itemData;
|
||||
|
|
|
@ -118,7 +118,7 @@ public:
|
|||
void requestStorageSetup(int index);
|
||||
|
||||
/** @reimp */
|
||||
virtual QMimeData* createMimeData(const QSet<int>& indexes) const;
|
||||
virtual QMimeData* createMimeData(const KItemSet& indexes) const;
|
||||
|
||||
/** @reimp */
|
||||
virtual bool supportsDropping(int index) const;
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace {
|
|||
Q_DECLARE_METATYPE(KFileItemListView::ItemLayout);
|
||||
Q_DECLARE_METATYPE(Qt::Orientation);
|
||||
Q_DECLARE_METATYPE(KItemListController::SelectionBehavior);
|
||||
Q_DECLARE_METATYPE(QSet<int>);
|
||||
Q_DECLARE_METATYPE(KItemSet);
|
||||
|
||||
class KItemListControllerTest : public QObject
|
||||
{
|
||||
|
@ -81,7 +81,7 @@ private:
|
|||
*/
|
||||
void KItemListControllerTest::initTestCase()
|
||||
{
|
||||
qRegisterMetaType<QSet<int> >("QSet<int>");
|
||||
qRegisterMetaType<KItemSet>("KItemSet");
|
||||
|
||||
m_testDir = new TestDir();
|
||||
m_model = new KFileItemModel();
|
||||
|
@ -159,14 +159,14 @@ struct KeyPress {
|
|||
*/
|
||||
struct ViewState {
|
||||
|
||||
ViewState(int current, const QSet<int> 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<int> 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<int>() << 1))
|
||||
<< qMakePair(KeyPress(Qt::Key_Return), ViewState(1, QSet<int>() << 1, true))
|
||||
<< qMakePair(KeyPress(Qt::Key_Enter), ViewState(1, QSet<int>() << 1, true))
|
||||
<< qMakePair(KeyPress(nextItemKey), ViewState(2, QSet<int>() << 2))
|
||||
<< qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(3, QSet<int>() << 2 << 3))
|
||||
<< qMakePair(KeyPress(Qt::Key_Return), ViewState(3, QSet<int>() << 2 << 3, true))
|
||||
<< qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(2, QSet<int>() << 2))
|
||||
<< qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(3, QSet<int>() << 2 << 3))
|
||||
<< qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(4, QSet<int>() << 2 << 3))
|
||||
<< qMakePair(KeyPress(Qt::Key_Return), ViewState(4, QSet<int>() << 2 << 3, true))
|
||||
<< qMakePair(KeyPress(previousItemKey), ViewState(3, QSet<int>() << 3))
|
||||
<< qMakePair(KeyPress(Qt::Key_Home, Qt::ShiftModifier), ViewState(0, QSet<int>() << 0 << 1 << 2 << 3))
|
||||
<< qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(1, QSet<int>() << 0 << 1 << 2 << 3))
|
||||
<< qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(1, QSet<int>() << 0 << 2 << 3))
|
||||
<< qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(1, QSet<int>() << 0 << 1 << 2 << 3))
|
||||
<< qMakePair(KeyPress(Qt::Key_End), ViewState(19, QSet<int>() << 19))
|
||||
<< qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(18, QSet<int>() << 18 << 19))
|
||||
<< qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet<int>() << 0))
|
||||
<< qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, QSet<int>()))
|
||||
<< qMakePair(KeyPress(Qt::Key_Enter), ViewState(0, QSet<int>(), true))
|
||||
<< qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, QSet<int>() << 0))
|
||||
<< qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, QSet<int>()))
|
||||
<< qMakePair(KeyPress(Qt::Key_Space), ViewState(0, QSet<int>() << 0))
|
||||
<< qMakePair(KeyPress(Qt::Key_E), ViewState(13, QSet<int>() << 13))
|
||||
<< qMakePair(KeyPress(Qt::Key_Space), ViewState(14, QSet<int>() << 14))
|
||||
<< qMakePair(KeyPress(Qt::Key_3), ViewState(15, QSet<int>() << 15))
|
||||
<< qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet<int>() << 0))
|
||||
<< qMakePair(KeyPress(Qt::Key_Escape), ViewState(0, QSet<int>()));
|
||||
<< 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<int>() << 1))
|
||||
<< qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(2, QSet<int>() << 1 << 2))
|
||||
<< qMakePair(KeyPress(nextRowKey, Qt::ControlModifier), ViewState(3, QSet<int>() << 1 << 2))
|
||||
<< qMakePair(KeyPress(previousRowKey), ViewState(2, QSet<int>() << 2))
|
||||
<< qMakePair(KeyPress(previousItemKey), ViewState(1, QSet<int>() << 1))
|
||||
<< qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet<int>() << 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<int>() << 3))
|
||||
<< qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(4, QSet<int>() << 3))
|
||||
<< qMakePair(KeyPress(nextRowKey), ViewState(7, QSet<int>() << 7))
|
||||
<< qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(8, QSet<int>() << 7 << 8))
|
||||
<< qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(9, QSet<int>() << 7 << 8 << 9))
|
||||
<< qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(8, QSet<int>() << 7 << 8))
|
||||
<< qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(7, QSet<int>() << 7))
|
||||
<< qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(6, QSet<int>() << 6 << 7))
|
||||
<< qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(5, QSet<int>() << 5 << 6 << 7))
|
||||
<< qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(6, QSet<int>() << 6 << 7))
|
||||
<< qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(7, QSet<int>() << 7))
|
||||
<< qMakePair(KeyPress(nextRowKey), ViewState(10, QSet<int>() << 10))
|
||||
<< qMakePair(KeyPress(nextItemKey), ViewState(11, QSet<int>() << 11))
|
||||
<< qMakePair(KeyPress(nextRowKey), ViewState(14, QSet<int>() << 14))
|
||||
<< qMakePair(KeyPress(nextRowKey), ViewState(17, QSet<int>() << 17))
|
||||
<< qMakePair(KeyPress(nextRowKey), ViewState(19, QSet<int>() << 19))
|
||||
<< qMakePair(KeyPress(previousRowKey), ViewState(17, QSet<int>() << 17))
|
||||
<< qMakePair(KeyPress(Qt::Key_End), ViewState(19, QSet<int>() << 19))
|
||||
<< qMakePair(KeyPress(previousRowKey), ViewState(16, QSet<int>() << 16))
|
||||
<< qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet<int>() << 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<int>() << 5))
|
||||
<< qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(6, QSet<int>() << 5))
|
||||
<< qMakePair(KeyPress(nextRowKey), ViewState(11, QSet<int>() << 11))
|
||||
<< qMakePair(KeyPress(nextItemKey), ViewState(12, QSet<int>() << 12))
|
||||
<< qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(17, QSet<int>() << 12 << 13 << 14 << 15 << 16 << 17))
|
||||
<< qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(12, QSet<int>() << 12))
|
||||
<< qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(7, QSet<int>() << 7 << 8 << 9 << 10 << 11 << 12))
|
||||
<< qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(12, QSet<int>() << 12))
|
||||
<< qMakePair(KeyPress(Qt::Key_End, Qt::ControlModifier), ViewState(19, QSet<int>() << 12))
|
||||
<< qMakePair(KeyPress(previousRowKey), ViewState(14, QSet<int>() << 14))
|
||||
<< qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet<int>() << 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<int>() << 1))
|
||||
<< qMakePair(KeyPress(nextItemKey), ViewState(2, QSet<int>() << 2))
|
||||
<< qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(3, QSet<int>() << 2 << 3))
|
||||
<< qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(6, QSet<int>() << 2 << 3 << 4 << 5 << 6))
|
||||
<< qMakePair(KeyPress(nextRowKey), ViewState(8, QSet<int>() << 8))
|
||||
<< qMakePair(KeyPress(nextRowKey), ViewState(11, QSet<int>() << 11))
|
||||
<< qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(12, QSet<int>() << 11))
|
||||
<< qMakePair(KeyPress(nextRowKey), ViewState(13, QSet<int>() << 13))
|
||||
<< qMakePair(KeyPress(nextRowKey), ViewState(16, QSet<int>() << 16))
|
||||
<< qMakePair(KeyPress(nextItemKey), ViewState(17, QSet<int>() << 17))
|
||||
<< qMakePair(KeyPress(nextRowKey), ViewState(19, QSet<int>() << 19))
|
||||
<< qMakePair(KeyPress(previousRowKey), ViewState(17, QSet<int>() << 17))
|
||||
<< qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet<int>() << 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<int>() << 1))
|
||||
<< qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(3, QSet<int>() << 1 << 2 << 3))
|
||||
<< qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(5, QSet<int>() << 1 << 2 << 3 << 4 << 5))
|
||||
<< qMakePair(KeyPress(nextItemKey), ViewState(6, QSet<int>() << 6))
|
||||
<< qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(7, QSet<int>() << 6))
|
||||
<< qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(8, QSet<int>() << 6))
|
||||
<< qMakePair(KeyPress(nextRowKey), ViewState(12, QSet<int>() << 12))
|
||||
<< qMakePair(KeyPress(nextRowKey), ViewState(17, QSet<int>() << 17))
|
||||
<< qMakePair(KeyPress(nextRowKey), ViewState(19, QSet<int>() << 19))
|
||||
<< qMakePair(KeyPress(previousRowKey), ViewState(17, QSet<int>() << 17))
|
||||
<< qMakePair(KeyPress(Qt::Key_End, Qt::ShiftModifier), ViewState(19, QSet<int>() << 17 << 18 << 19))
|
||||
<< qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(14, QSet<int>() << 14 << 15 << 16 << 17))
|
||||
<< qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet<int>() << 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<int>)));
|
||||
QSignalSpy spyMultipleItemsActivated(m_controller, SIGNAL(itemsActivated(KItemSet)));
|
||||
|
||||
while (!testList.isEmpty()) {
|
||||
const QPair<KeyPress, ViewState> 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<int> 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<int>() << 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<int>(spySingleItemActivated.takeFirst().at(0)), selection.toList().at(0));
|
||||
QCOMPARE(qvariant_cast<int>(spySingleItemActivated.takeFirst().at(0)), selection.first());
|
||||
QVERIFY(spyMultipleItemsActivated.isEmpty());
|
||||
} else {
|
||||
QVERIFY(spySingleItemActivated.isEmpty());
|
||||
QVERIFY(!spyMultipleItemsActivated.isEmpty());
|
||||
QCOMPARE(qvariant_cast<QSet<int> >(spyMultipleItemsActivated.takeFirst().at(0)), selection);
|
||||
QCOMPARE(qvariant_cast<KItemSet>(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);
|
||||
|
|
|
@ -80,7 +80,7 @@ private slots:
|
|||
void testDeleteCurrentItem();
|
||||
|
||||
private:
|
||||
void verifySelectionChange(QSignalSpy& spy, const QSet<int>& currentSelection, const QSet<int>& 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<int>() << 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<int>(spyCurrent.at(0).at(1)), 4);
|
||||
spyCurrent.takeFirst();
|
||||
|
||||
QCOMPARE(m_selectionManager->selectedItems(), QSet<int>() << 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<int>() << 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<int>() << 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<int>());
|
||||
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<int> 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<int> 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<int>() << 5 << 6);
|
||||
QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 5 << 6);
|
||||
|
||||
m_selectionManager->setCurrentItem(4);
|
||||
QCOMPARE(m_selectionManager->currentItem(), 4);
|
||||
QCOMPARE(m_selectionManager->selectedItems(), QSet<int>() << 4 << 5);
|
||||
QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 4 << 5);
|
||||
|
||||
m_selectionManager->setCurrentItem(7);
|
||||
QCOMPARE(m_selectionManager->currentItem(), 7);
|
||||
QCOMPARE(m_selectionManager->selectedItems(), QSet<int>() << 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<int>() << 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<int>() << 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<int>() << 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<int>() << 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<int>);
|
||||
Q_DECLARE_METATYPE(KItemSet);
|
||||
Q_DECLARE_METATYPE(ChangeType);
|
||||
Q_DECLARE_METATYPE(KItemRange);
|
||||
Q_DECLARE_METATYPE(KItemRangeList);
|
||||
|
@ -355,86 +355,86 @@ Q_DECLARE_METATYPE(QList<int>);
|
|||
|
||||
void KItemListSelectionManagerTest::testChangeSelection_data()
|
||||
{
|
||||
QTest::addColumn<QSet<int> >("initialSelection");
|
||||
QTest::addColumn<KItemSet>("initialSelection");
|
||||
QTest::addColumn<int>("anchor");
|
||||
QTest::addColumn<int>("current");
|
||||
QTest::addColumn<QSet<int> >("expectedSelection");
|
||||
QTest::addColumn<KItemSet>("expectedSelection");
|
||||
QTest::addColumn<ChangeType>("changeType");
|
||||
QTest::addColumn<QList<QVariant> >("data");
|
||||
QTest::addColumn<QSet<int> >("finalSelection");
|
||||
QTest::addColumn<KItemSet>("finalSelection");
|
||||
|
||||
QTest::newRow("No change")
|
||||
<< (QSet<int>() << 5 << 6)
|
||||
<< (KItemSet() << 5 << 6)
|
||||
<< 2 << 3
|
||||
<< (QSet<int>() << 2 << 3 << 5 << 6)
|
||||
<< (KItemSet() << 2 << 3 << 5 << 6)
|
||||
<< NoChange
|
||||
<< QList<QVariant>()
|
||||
<< (QSet<int>() << 2 << 3 << 5 << 6);
|
||||
<< (KItemSet() << 2 << 3 << 5 << 6);
|
||||
|
||||
QTest::newRow("Insert Items")
|
||||
<< (QSet<int>() << 5 << 6)
|
||||
<< (KItemSet() << 5 << 6)
|
||||
<< 2 << 3
|
||||
<< (QSet<int>() << 2 << 3 << 5 << 6)
|
||||
<< (KItemSet() << 2 << 3 << 5 << 6)
|
||||
<< InsertItems
|
||||
<< (QList<QVariant>() << QVariant::fromValue(KItemRangeList() << KItemRange(1, 1) << KItemRange(5, 2) << KItemRange(10, 5)))
|
||||
<< (QSet<int>() << 3 << 4 << 8 << 9);
|
||||
<< (KItemSet() << 3 << 4 << 8 << 9);
|
||||
|
||||
QTest::newRow("Remove Items")
|
||||
<< (QSet<int>() << 5 << 6)
|
||||
<< (KItemSet() << 5 << 6)
|
||||
<< 2 << 3
|
||||
<< (QSet<int>() << 2 << 3 << 5 << 6)
|
||||
<< (KItemSet() << 2 << 3 << 5 << 6)
|
||||
<< RemoveItems
|
||||
<< (QList<QVariant>() << QVariant::fromValue(KItemRangeList() << KItemRange(1, 1) << KItemRange(3, 1) << KItemRange(10, 5)))
|
||||
<< (QSet<int>() << 1 << 2 << 3 << 4);
|
||||
<< (KItemSet() << 1 << 2 << 3 << 4);
|
||||
|
||||
QTest::newRow("Empty Anchored Selection")
|
||||
<< QSet<int>()
|
||||
<< KItemSet()
|
||||
<< 2 << 2
|
||||
<< QSet<int>()
|
||||
<< KItemSet()
|
||||
<< EndAnchoredSelection
|
||||
<< QList<QVariant>()
|
||||
<< QSet<int>();
|
||||
<< KItemSet();
|
||||
|
||||
QTest::newRow("Toggle selection")
|
||||
<< (QSet<int>() << 1 << 3 << 4)
|
||||
<< (KItemSet() << 1 << 3 << 4)
|
||||
<< 6 << 8
|
||||
<< (QSet<int>() << 1 << 3 << 4 << 6 << 7 << 8)
|
||||
<< (KItemSet() << 1 << 3 << 4 << 6 << 7 << 8)
|
||||
<< SetSelected
|
||||
<< (QList<QVariant>() << 0 << 10 << QVariant::fromValue(KItemListSelectionManager::Toggle))
|
||||
<< (QSet<int>() << 0 << 2 << 5 << 9);
|
||||
<< (KItemSet() << 0 << 2 << 5 << 9);
|
||||
|
||||
// Swap items 2, 3 and 4, 5
|
||||
QTest::newRow("Move items")
|
||||
<< (QSet<int>() << 0 << 1 << 2 << 3)
|
||||
<< (KItemSet() << 0 << 1 << 2 << 3)
|
||||
<< -1 << -1
|
||||
<< (QSet<int>() << 0 << 1 << 2 << 3)
|
||||
<< (KItemSet() << 0 << 1 << 2 << 3)
|
||||
<< MoveItems
|
||||
<< (QList<QVariant>() << QVariant::fromValue(KItemRange(2, 4))
|
||||
<< QVariant::fromValue(QList<int>() << 4 << 5 << 2 << 3))
|
||||
<< (QSet<int>() << 0 << 1 << 4 << 5);
|
||||
<< (KItemSet() << 0 << 1 << 4 << 5);
|
||||
|
||||
// Revert sort order
|
||||
QTest::newRow("Revert sort order")
|
||||
<< (QSet<int>() << 0 << 1)
|
||||
<< (KItemSet() << 0 << 1)
|
||||
<< 3 << 4
|
||||
<< (QSet<int>() << 0 << 1 << 3 << 4)
|
||||
<< (KItemSet() << 0 << 1 << 3 << 4)
|
||||
<< MoveItems
|
||||
<< (QList<QVariant>() << QVariant::fromValue(KItemRange(0, 10))
|
||||
<< QVariant::fromValue(QList<int>() << 9 << 8 << 7 << 6 << 5 << 4 << 3 << 2 << 1 << 0))
|
||||
<< (QSet<int>() << 5 << 6 << 8 << 9);
|
||||
<< (KItemSet() << 5 << 6 << 8 << 9);
|
||||
}
|
||||
|
||||
void KItemListSelectionManagerTest::testChangeSelection()
|
||||
{
|
||||
QFETCH(QSet<int>, initialSelection);
|
||||
QFETCH(KItemSet, initialSelection);
|
||||
QFETCH(int, anchor);
|
||||
QFETCH(int, current);
|
||||
QFETCH(QSet<int>, expectedSelection);
|
||||
QFETCH(KItemSet, expectedSelection);
|
||||
QFETCH(ChangeType, changeType);
|
||||
QFETCH(QList<QVariant>, data);
|
||||
QFETCH(QSet<int>, finalSelection);
|
||||
QFETCH(KItemSet, finalSelection);
|
||||
|
||||
QSignalSpy spySelectionChanged(m_selectionManager, SIGNAL(selectionChanged(QSet<int>,QSet<int>)));
|
||||
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<int>());
|
||||
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<int>(), finalSelection);
|
||||
verifySelectionChange(spySelectionChanged, KItemSet(), finalSelection);
|
||||
}
|
||||
|
||||
void KItemListSelectionManagerTest::testDeleteCurrentItem_data()
|
||||
|
@ -520,8 +520,8 @@ void KItemListSelectionManagerTest::testDeleteCurrentItem()
|
|||
}
|
||||
|
||||
void KItemListSelectionManagerTest::verifySelectionChange(QSignalSpy& spy,
|
||||
const QSet<int>& currentSelection,
|
||||
const QSet<int>& 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<QVariant> arguments = spy.takeFirst();
|
||||
QCOMPARE(qvariant_cast<QSet<int> >(arguments.at(0)), currentSelection);
|
||||
QCOMPARE(qvariant_cast<QSet<int> >(arguments.at(1)), previousSelection);
|
||||
QCOMPARE(qvariant_cast<KItemSet>(arguments.at(0)), currentSelection);
|
||||
QCOMPARE(qvariant_cast<KItemSet>(arguments.at(1)), previousSelection);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
612
src/tests/kitemsettest.cpp
Normal file
612
src/tests/kitemsettest.cpp
Normal file
|
@ -0,0 +1,612 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2013 by Frank Reininghaus <frank78ac@googlemail.com> *
|
||||
* *
|
||||
* 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 <qtest_kde.h>
|
||||
|
||||
#include "kitemviews/kitemset.h"
|
||||
|
||||
#include <QVector>
|
||||
|
||||
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<int>.
|
||||
*/
|
||||
QSet<int> KItemRangeList2QSet(const KItemRangeList& itemRanges)
|
||||
{
|
||||
QSet<int> 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<int>.
|
||||
*/
|
||||
QVector<int> KItemRangeList2QVector(const KItemRangeList& itemRanges)
|
||||
{
|
||||
QVector<int> 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<int>.
|
||||
*/
|
||||
static QSet<int> KItemSet2QSet(const KItemSet& itemSet)
|
||||
{
|
||||
QSet<int> 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<const char*, KItemRangeList> 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<KItemRangeList>("itemRanges");
|
||||
|
||||
QHash<const char*, KItemRangeList>::const_iterator it = m_testCases.constBegin();
|
||||
const QHash<const char*, KItemRangeList>::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<int> 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<KItemRangeList>("itemRanges");
|
||||
|
||||
QHash<const char*, KItemRangeList>::const_iterator it = m_testCases.constBegin();
|
||||
const QHash<const char*, KItemRangeList>::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<int>.
|
||||
*/
|
||||
void KItemSetTest::testIterators()
|
||||
{
|
||||
QFETCH(KItemRangeList, itemRanges);
|
||||
|
||||
KItemSet itemSet = KItemRangeList2KItemSet(itemRanges);
|
||||
QVector<int> 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<int> 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<int>::iterator vectorIt1 = itemsQVector.begin();
|
||||
QVector<int>::iterator vectorIt2 = itemsQVector.begin();
|
||||
QVector<int>::const_iterator vectorConstIt1 = itemsQVector.constBegin();
|
||||
QVector<int>::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<KItemRangeList>("itemRanges");
|
||||
|
||||
QHash<const char*, KItemRangeList>::const_iterator it = m_testCases.constBegin();
|
||||
const QHash<const char*, KItemRangeList>::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<int> 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<KItemRangeList>("itemRanges");
|
||||
|
||||
QHash<const char*, KItemRangeList>::const_iterator it = m_testCases.constBegin();
|
||||
const QHash<const char*, KItemRangeList>::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<int> 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<int> 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<int> 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<int> 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<KItemRangeList>("itemRanges1");
|
||||
QTest::addColumn<KItemRangeList>("itemRanges2");
|
||||
|
||||
QHash<const char*, KItemRangeList>::const_iterator it1 = m_testCases.constBegin();
|
||||
const QHash<const char*, KItemRangeList>::const_iterator end = m_testCases.constEnd();
|
||||
|
||||
while (it1 != end) {
|
||||
QHash<const char*, KItemRangeList>::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<int> itemsQSet1 = KItemRangeList2QSet(itemRanges1);
|
||||
|
||||
KItemSet itemSet2 = KItemRangeList2KItemSet(itemRanges2);
|
||||
QSet<int> itemsQSet2 = KItemRangeList2QSet(itemRanges2);
|
||||
|
||||
KItemSet sum = itemSet1 + itemSet2;
|
||||
QSet<int> sumQSet = itemsQSet1 + itemsQSet2;
|
||||
|
||||
QCOMPARE(sum.count(), sumQSet.count());
|
||||
QCOMPARE(KItemSet2QSet(sum), sumQSet);
|
||||
}
|
||||
|
||||
void KItemSetTest::testSymmetricDifference_data()
|
||||
{
|
||||
QTest::addColumn<KItemRangeList>("itemRanges1");
|
||||
QTest::addColumn<KItemRangeList>("itemRanges2");
|
||||
|
||||
QHash<const char*, KItemRangeList>::const_iterator it1 = m_testCases.constBegin();
|
||||
const QHash<const char*, KItemRangeList>::const_iterator end = m_testCases.constEnd();
|
||||
|
||||
while (it1 != end) {
|
||||
QHash<const char*, KItemRangeList>::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<int> itemsQSet1 = KItemRangeList2QSet(itemRanges1);
|
||||
|
||||
KItemSet itemSet2 = KItemRangeList2KItemSet(itemRanges2);
|
||||
QSet<int> itemsQSet2 = KItemRangeList2QSet(itemRanges2);
|
||||
|
||||
KItemSet symmetricDifference = itemSet1 ^ itemSet2;
|
||||
QSet<int> 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"
|
|
@ -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<int>)), this, SLOT(slotItemsActivated(QSet<int>)));
|
||||
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<int>,QSet<int>)),
|
||||
this, SLOT(slotSelectionChanged(QSet<int>,QSet<int>)));
|
||||
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<int> selectedIndexes = selectionManager->selectedItems().toList();
|
||||
|
||||
qSort(selectedIndexes);
|
||||
|
||||
KFileItemList selectedItems;
|
||||
QListIterator<int> 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<int> 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<int>, 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<int>& indexes)
|
||||
void DolphinView::slotItemsActivated(const KItemSet& indexes)
|
||||
{
|
||||
Q_ASSERT(indexes.count() >= 2);
|
||||
|
||||
|
@ -818,9 +813,7 @@ void DolphinView::slotItemsActivated(const QSet<int>& indexes)
|
|||
KFileItemList items;
|
||||
items.reserve(indexes.count());
|
||||
|
||||
QSetIterator<int> 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<int>& current, const QSet<int>& 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<int> selectedItems = selectionManager->selectedItems();
|
||||
KItemSet selectedItems = selectionManager->selectedItems();
|
||||
|
||||
QList<KUrl>::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<int> selectedIndexes = selectionManager->selectedItems();
|
||||
const KItemSet selectedIndexes = selectionManager->selectedItems();
|
||||
|
||||
return m_model->createMimeData(selectedIndexes);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <QBoxLayout>
|
||||
#include <QKeyEvent>
|
||||
#include <QLinkedList>
|
||||
#include <QSet>
|
||||
#include <QWidget>
|
||||
|
||||
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<int>& 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<int>& current, const QSet<int>& previous);
|
||||
void slotSelectionChanged(const KItemSet& current, const KItemSet& previous);
|
||||
|
||||
/**
|
||||
* Is called by emitDelayedSelectionChangedSignal() and emits the
|
||||
|
|
Loading…
Reference in a new issue