X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/1826f905d706925456763394de17294bcb6d1c35..6c55cf4b6a89d0d58ee7a29122ac68ac70fad65c:/src/kitemviews/kitemlistview.cpp diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index cf1483659..38ec6841a 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -8,12 +8,16 @@ #include "kitemlistview.h" +#ifndef QT_NO_ACCESSIBILITY +#include "accessibility/kitemlistcontaineraccessible.h" +#include "accessibility/kitemlistdelegateaccessible.h" +#include "accessibility/kitemlistviewaccessible.h" +#endif #include "dolphindebug.h" #include "kitemlistcontainer.h" #include "kitemlistcontroller.h" #include "kitemlistheader.h" #include "kitemlistselectionmanager.h" -#include "kitemlistviewaccessible.h" #include "kstandarditemlistwidget.h" #include "private/kitemlistheaderwidget.h" @@ -402,6 +406,10 @@ qreal KItemListView::verticalPageStep() const std::optional KItemListView::itemAt(const QPointF &pos) const { + if (headerBoundaries().contains(pos)) { + return std::nullopt; + } + QHashIterator it(m_visibleItems); while (it.hasNext()) { it.next(); @@ -546,64 +554,88 @@ void KItemListView::scrollToItem(int index, ViewItemPosition viewItemPosition) } QRectF currentRect = itemRect(index); + if (layoutDirection() == Qt::RightToLeft && scrollOrientation() == Qt::Horizontal) { + currentRect.moveLeft(m_layouter->size().width() - currentRect.right()); + } + // Fix for Bug 311099 - View the underscore when using Ctrl + PageDown currentRect.adjust(-m_styleOption.horizontalMargin, -m_styleOption.verticalMargin, m_styleOption.horizontalMargin, m_styleOption.verticalMargin); - qreal newOffset = scrollOffset(); - if (scrollOrientation() == Qt::Vertical && (currentRect.top() < viewGeometry.top() || currentRect.bottom() > viewGeometry.bottom())) { - switch (viewItemPosition) { - case Beginning: - newOffset += currentRect.top() - viewGeometry.top(); - break; - case Middle: - newOffset += 0.5 * (currentRect.top() + currentRect.bottom() - (viewGeometry.top() + viewGeometry.bottom())); - break; - case End: - newOffset += currentRect.bottom() - viewGeometry.bottom(); - break; - case Nearest: - if (currentRect.top() < viewGeometry.top()) { - newOffset += currentRect.top() - viewGeometry.top(); - } else { - newOffset += currentRect.bottom() - viewGeometry.bottom(); - } - break; - default: - Q_UNREACHABLE(); - } - } else if (scrollOrientation() == Qt::Horizontal && (currentRect.left() < viewGeometry.left() || currentRect.right() > viewGeometry.right())) { - switch (viewItemPosition) { - case Beginning: - if (layoutDirection() == Qt::RightToLeft) { - newOffset += currentRect.right() - viewGeometry.right(); - } else { - newOffset += currentRect.left() - viewGeometry.left(); - } - break; - case Middle: - newOffset += 0.5 * (currentRect.left() + currentRect.right() - (viewGeometry.left() + viewGeometry.right())); - break; - case End: - if (layoutDirection() == Qt::RightToLeft) { - newOffset += currentRect.left() - viewGeometry.left(); - } else { - newOffset += currentRect.right() - viewGeometry.right(); + qreal offset = 0; + switch (scrollOrientation()) { + case Qt::Vertical: + if (currentRect.top() < viewGeometry.top() || currentRect.bottom() > viewGeometry.bottom()) { + switch (viewItemPosition) { + case Beginning: + offset = currentRect.top() - viewGeometry.top(); + break; + case Middle: + offset = 0.5 * (currentRect.top() + currentRect.bottom() - (viewGeometry.top() + viewGeometry.bottom())); + break; + case End: + offset = currentRect.bottom() - viewGeometry.bottom(); + break; + case Nearest: + if (currentRect.top() < viewGeometry.top()) { + offset = currentRect.top() - viewGeometry.top(); + } + if (currentRect.bottom() > viewGeometry.bottom() + offset) { + offset += currentRect.bottom() - viewGeometry.bottom() - offset; + } + break; + default: + Q_UNREACHABLE(); } - break; - case Nearest: - if (currentRect.left() < viewGeometry.left()) { - newOffset += currentRect.left() - viewGeometry.left(); - } else { - newOffset += currentRect.right() - viewGeometry.right(); + } + break; + case Qt::Horizontal: + if (currentRect.left() < viewGeometry.left() || currentRect.right() > viewGeometry.right()) { + switch (viewItemPosition) { + case Beginning: + if (layoutDirection() == Qt::RightToLeft) { + offset = currentRect.right() - viewGeometry.right(); + } else { + offset = currentRect.left() - viewGeometry.left(); + } + break; + case Middle: + offset = 0.5 * (currentRect.left() + currentRect.right() - (viewGeometry.left() + viewGeometry.right())); + break; + case End: + if (layoutDirection() == Qt::RightToLeft) { + offset = currentRect.left() - viewGeometry.left(); + } else { + offset = currentRect.right() - viewGeometry.right(); + } + break; + case Nearest: + if (layoutDirection() == Qt::RightToLeft) { + if (currentRect.left() < viewGeometry.left()) { + offset = currentRect.left() - viewGeometry.left(); + } + if (currentRect.right() > viewGeometry.right() + offset) { + offset += currentRect.right() - viewGeometry.right() - offset; + } + } else { + if (currentRect.right() > viewGeometry.right()) { + offset = currentRect.right() - viewGeometry.right(); + } + if (currentRect.left() < viewGeometry.left() + offset) { + offset += currentRect.left() - viewGeometry.left() - offset; + } + } + break; + default: + Q_UNREACHABLE(); } - break; - default: - Q_UNREACHABLE(); } + break; + default: + Q_UNREACHABLE(); } - if (newOffset != scrollOffset()) { - Q_EMIT scrollTo(newOffset); + if (!qFuzzyIsNull(offset)) { + Q_EMIT scrollTo(scrollOffset() + offset); return; } @@ -1212,6 +1244,11 @@ void KItemListView::slotItemsInserted(const KItemRangeList &itemRanges) if (useAlternateBackgrounds()) { updateAlternateBackgrounds(); } +#ifndef QT_NO_ACCESSIBILITY + if (QAccessible::isActive()) { // Announce that the count of items has changed. + static_cast(QAccessible::queryAccessibleInterface(this))->announceDescriptionChange(); + } +#endif } void KItemListView::slotItemsRemoved(const KItemRangeList &itemRanges) @@ -1330,6 +1367,11 @@ void KItemListView::slotItemsRemoved(const KItemRangeList &itemRanges) if (useAlternateBackgrounds()) { updateAlternateBackgrounds(); } +#ifndef QT_NO_ACCESSIBILITY + if (QAccessible::isActive()) { // Announce that the count of items has changed. + static_cast(QAccessible::queryAccessibleInterface(this))->announceDescriptionChange(); + } +#endif } void KItemListView::slotItemsMoved(const KItemRange &itemRange, const QList &movedToIndexes) @@ -1388,10 +1430,12 @@ void KItemListView::slotItemsChanged(const KItemRangeList &itemRanges, const QSe doLayout(NoAnimation); } +#ifndef QT_NO_ACCESSIBILITY QAccessibleTableModelChangeEvent ev(this, QAccessibleTableModelChangeEvent::DataChanged); ev.setFirstRow(itemRange.index); ev.setLastRow(itemRange.index + itemRange.count); QAccessible::updateAccessibility(&ev); +#endif } doLayout(NoAnimation); @@ -1455,8 +1499,6 @@ void KItemListView::slotSortRoleChanged(const QByteArray ¤t, const QByteAr void KItemListView::slotCurrentChanged(int current, int previous) { - Q_UNUSED(previous) - // In SingleSelection mode (e.g., in the Places Panel), the current item is // always the selected item. It is not necessary to highlight the current item then. if (m_controller->selectionBehavior() != KItemListController::SingleSelection) { @@ -1468,25 +1510,52 @@ void KItemListView::slotCurrentChanged(int current, int previous) KItemListWidget *currentWidget = m_visibleItems.value(current, nullptr); if (currentWidget) { currentWidget->setCurrent(true); + if (hasFocus() || (previousWidget && previousWidget->hasFocus())) { + currentWidget->setFocus(); // Mostly for accessibility, because keyboard events are handled correctly either way. + } } } - - QAccessibleEvent ev(this, QAccessible::Focus); - ev.setChild(current); - QAccessible::updateAccessibility(&ev); +#ifndef QT_NO_ACCESSIBILITY + if (QAccessible::isActive()) { + if (current >= 0) { + QAccessibleEvent accessibleFocusCurrentItemEvent(this, QAccessible::Focus); + accessibleFocusCurrentItemEvent.setChild(current); + QAccessible::updateAccessibility(&accessibleFocusCurrentItemEvent); + } + static_cast(QAccessible::queryAccessibleInterface(this))->announceDescriptionChange(); + } +#endif } void KItemListView::slotSelectionChanged(const KItemSet ¤t, const KItemSet &previous) { - Q_UNUSED(previous) - QHashIterator it(m_visibleItems); while (it.hasNext()) { it.next(); const int index = it.key(); KItemListWidget *widget = it.value(); - widget->setSelected(current.contains(index)); + const bool isSelected(current.contains(index)); + widget->setSelected(isSelected); + +#ifndef QT_NO_ACCESSIBILITY + if (!QAccessible::isActive()) { + continue; + } + // Let the screen reader announce "selected" or "not selected" for the active item. + const bool wasSelected(previous.contains(index)); + if (isSelected != wasSelected) { + QAccessibleEvent accessibleSelectionChangedEvent(this, QAccessible::Selection); + accessibleSelectionChangedEvent.setChild(index); + QAccessible::updateAccessibility(&accessibleSelectionChangedEvent); + } + } + // Usually the below does not have an effect because the view will not have focus at this moment but one of its list items. Still we announce the + // change of the accessibility description just in case the user manually moved focus up by one. + static_cast(QAccessible::queryAccessibleInterface(this))->announceDescriptionChange(); +#else } + Q_UNUSED(previous) +#endif } void KItemListView::slotAnimationFinished(QGraphicsWidget *widget, KItemListViewAnimation::AnimationType type) @@ -1539,10 +1608,10 @@ void KItemListView::slotRubberBandActivationChanged(bool active) curve.addCubicBezierSegment(QPointF(0.4, 0.0), QPointF(1.0, 1.0), QPointF(1.0, 1.0)); animation->setEasingCurve(curve); - connect(animation, &QVariantAnimation::valueChanged, this, [=](const QVariant &) { + connect(animation, &QVariantAnimation::valueChanged, this, [=, this](const QVariant &) { update(); }); - connect(animation, &QVariantAnimation::finished, this, [=]() { + connect(animation, &QVariantAnimation::finished, this, [=, this]() { m_rubberBandAnimations.removeAll(animation); delete animation; });