When a selection has been done with non-linear ranges, it was possible that
the anchor item pointed to an invalid index that resulted into an invalid
selection.
As part of this fix the sorting for DolphinView::selectedItems() has been
disabled (if the caller assumes a sorted selection he must manually adjust it).
BUG: 288908
FIXED-IN: 4.8.0
// Update the current item
if (m_currentItem >= 0) {
const int previousCurrent = m_currentItem;
// Update the current item
if (m_currentItem >= 0) {
const int previousCurrent = m_currentItem;
- int currentItem = m_currentItem;
- foreach (const KItemRange& itemRange, itemRanges) {
- if (currentItem < itemRange.index) {
- break;
- }
-
- if (currentItem >= itemRange.index + itemRange.count) {
- currentItem -= itemRange.count;
- }
-
- if (currentItem >= m_model->count()) {
- currentItem = m_model->count() - 1;
- }
- }
- // Calling setCurrentItem would trigger the selectionChanged signal, but we want to
+ // Calling setCurrentItem() would trigger the selectionChanged signal, but we want to
// emit it only once in this function -> change the current item manually and emit currentChanged
// emit it only once in this function -> change the current item manually and emit currentChanged
- m_currentItem = currentItem;
- Q_ASSERT(m_currentItem < m_model->count());
- emit currentChanged(m_currentItem, previousCurrent);
+ m_currentItem = indexAfterRangesRemoving(m_currentItem, itemRanges);
+ if (m_currentItem < 0) {
+ m_currentItem = qMin(previousCurrent, m_model->count() - 1);
+ }
+ if (m_currentItem != previousCurrent) {
+ emit currentChanged(m_currentItem, previousCurrent);
+ }
}
// Update the anchor item
if (m_anchorItem >= 0) {
}
// Update the anchor item
if (m_anchorItem >= 0) {
- int anchorItem = m_anchorItem;
- foreach (const KItemRange& itemRange, itemRanges) {
- if (anchorItem < itemRange.index) {
- break;
- }
- if (anchorItem >= itemRange.index + itemRange.count) {
- anchorItem -= itemRange.count;
- } else if (anchorItem >= m_model->count()) {
- anchorItem = m_model->count() - 1;
- }
- }
- m_anchorItem = anchorItem;
+ m_anchorItem = indexAfterRangesRemoving(m_anchorItem, itemRanges);
if (m_anchorItem < 0) {
m_isAnchoredSelectionActive = false;
}
}
if (m_anchorItem < 0) {
m_isAnchoredSelectionActive = false;
}
}
- // Update the selections
+ // Update the selections and the anchor item
if (!m_selectedItems.isEmpty()) {
const QSet<int> previous = m_selectedItems;
m_selectedItems.clear();
m_selectedItems.reserve(previous.count());
QSetIterator<int> it(previous);
while (it.hasNext()) {
if (!m_selectedItems.isEmpty()) {
const QSet<int> previous = m_selectedItems;
m_selectedItems.clear();
m_selectedItems.reserve(previous.count());
QSetIterator<int> it(previous);
while (it.hasNext()) {
- int index = it.next();
- int dec = 0;
- foreach (const KItemRange& itemRange, itemRanges) {
- if (index < itemRange.index) {
- break;
- }
-
- if (index < itemRange.index + itemRange.count) {
- // The selection is part of the removed range
- // and will get deleted
- index = -1;
- break;
- }
-
- dec += itemRange.count;
- }
- index -= dec;
+ const int index = indexAfterRangesRemoving(it.next(), itemRanges);
if (index >= 0) {
m_selectedItems.insert(index);
}
if (index >= 0) {
m_selectedItems.insert(index);
}
if (selection != previousSelection) {
emit selectionChanged(selection, previousSelection);
}
if (selection != previousSelection) {
emit selectionChanged(selection, previousSelection);
}
+
+ Q_ASSERT(m_currentItem < m_model->count());
+ Q_ASSERT(m_anchorItem < m_model->count());
}
void KItemListSelectionManager::itemsMoved(const KItemRange& itemRange, const QList<int>& movedToIndexes)
}
void KItemListSelectionManager::itemsMoved(const KItemRange& itemRange, const QList<int>& movedToIndexes)
+int KItemListSelectionManager::indexAfterRangesRemoving(int index, const KItemRangeList& itemRanges) const
+{
+ int dec = 0;
+ foreach (const KItemRange& itemRange, itemRanges) {
+ if (index < itemRange.index) {
+ break;
+ }
+
+ if (index < itemRange.index + itemRange.count) {
+ // The index is part of the removed range
+ return -1;
+ }
+
+ dec += itemRange.count;
+ }
+ return index - dec;
+}
#include "kitemlistselectionmanager.moc"
#include "kitemlistselectionmanager.moc"
void itemsRemoved(const KItemRangeList& itemRanges);
void itemsMoved(const KItemRange& itemRange, const QList<int>& movedToIndexes);
void itemsRemoved(const KItemRangeList& itemRanges);
void itemsMoved(const KItemRange& itemRange, const QList<int>& movedToIndexes);
+
+ /**
+ * Helper method for itemsRemoved. Returns the changed index after removing
+ * the given range. If the index is part of the range, -1 will be returned.
+ */
+ int indexAfterRangesRemoving(int index, const KItemRangeList& itemRanges) const;
+
private:
int m_currentItem;
int m_anchorItem;
private:
int m_currentItem;
int m_anchorItem;
const KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager();
const QSet<int> selectedIndexes = selectionManager->selectedItems();
const KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager();
const QSet<int> selectedIndexes = selectionManager->selectedItems();
- QList<int> sortedIndexes = selectedIndexes.toList();
- qSort(sortedIndexes);
-
KFileItemList selectedItems;
KFileItemList selectedItems;
- QListIterator<int> it(sortedIndexes);
+ QSetIterator<int> it(selectedIndexes);
while (it.hasNext()) {
const int index = it.next();
selectedItems.append(model->fileItem(index));
while (it.hasNext()) {
const int index = it.next();
selectedItems.append(model->fileItem(index));