#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"
if (!m_headerWidget->automaticColumnResizing()) {
// The column-width of new roles are still 0. Apply the preferred
// column-width as default with.
- for (const QByteArray &role : qAsConst(m_visibleRoles)) {
+ for (const QByteArray &role : std::as_const(m_visibleRoles)) {
if (m_headerWidget->columnWidth(role) == 0) {
const qreal width = m_headerWidget->preferredColumnWidth(role);
m_headerWidget->setColumnWidth(role, width);
std::optional<int> KItemListView::itemAt(const QPointF &pos) const
{
+ if (headerBoundaries().contains(pos)) {
+ return std::nullopt;
+ }
+
QHashIterator<int, KItemListWidget *> it(m_visibleItems);
while (it.hasNext()) {
it.next();
return m_sizeHintResolver->isElided(index);
}
-void KItemListView::scrollToItem(int index)
+void KItemListView::scrollToItem(int index, ViewItemPosition viewItemPosition)
{
QRectF viewGeometry = geometry();
if (m_headerWidget->isVisible()) {
}
QRectF currentRect = itemRect(index);
- // Fix for Bug 311099 - View the underscore when using Ctrl + PagDown
+ 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);
- if (!viewGeometry.contains(currentRect)) {
- qreal newOffset = scrollOffset();
- if (scrollOrientation() == Qt::Vertical) {
- if (currentRect.top() < viewGeometry.top()) {
- newOffset += currentRect.top() - viewGeometry.top();
- } else if (currentRect.bottom() > viewGeometry.bottom()) {
- newOffset += currentRect.bottom() - viewGeometry.bottom();
+ 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();
}
- } else {
- if (currentRect.left() < viewGeometry.left()) {
- newOffset += currentRect.left() - viewGeometry.left();
- } else if (currentRect.right() > viewGeometry.right()) {
- 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();
+ }
- if (newOffset != scrollOffset()) {
- Q_EMIT scrollTo(newOffset);
- return;
- }
+ if (!qFuzzyIsNull(offset)) {
+ Q_EMIT scrollTo(scrollOffset() + offset);
+ return;
}
Q_EMIT scrollingStopped();
{
QGraphicsWidget::paint(painter, option, widget);
- for (auto animation : qAsConst(m_rubberBandAnimations)) {
+ for (auto animation : std::as_const(m_rubberBandAnimations)) {
QRectF rubberBandRect = animation->property(RubberPropertyName).toRectF();
const QPointF topLeft = rubberBandRect.topLeft();
void KItemListView::updatePalette()
{
- if (scene() && !scene()->views().isEmpty()) {
- KItemListStyleOption option = styleOption();
- option.palette = scene()->views().first()->palette();
-
- setStyleOption(option);
- }
+ KItemListStyleOption option = styleOption();
+ option.palette = palette();
+ setStyleOption(option);
}
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<KItemListViewAccessible *>(QAccessible::queryAccessibleInterface(this))->announceDescriptionChange();
+ }
+#endif
}
void KItemListView::slotItemsRemoved(const KItemRangeList &itemRanges)
// after the deleted items. It is important to update them in ascending
// order to prevent overlaps when setting the new index.
std::sort(itemsToMove.begin(), itemsToMove.end());
- for (int i : qAsConst(itemsToMove)) {
+ for (int i : std::as_const(itemsToMove)) {
KItemListWidget *widget = m_visibleItems.value(i);
Q_ASSERT(widget);
const int newIndex = i - count;
if (useAlternateBackgrounds()) {
updateAlternateBackgrounds();
}
+#ifndef QT_NO_ACCESSIBILITY
+ if (QAccessible::isActive()) { // Announce that the count of items has changed.
+ static_cast<KItemListViewAccessible *>(QAccessible::queryAccessibleInterface(this))->announceDescriptionChange();
+ }
+#endif
}
void KItemListView::slotItemsMoved(const KItemRange &itemRange, const QList<int> &movedToIndexes)
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);
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) {
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<KItemListViewAccessible *>(QAccessible::queryAccessibleInterface(this))->announceDescriptionChange();
+ }
+#endif
}
void KItemListView::slotSelectionChanged(const KItemSet ¤t, const KItemSet &previous)
{
- Q_UNUSED(previous)
-
QHashIterator<int, KItemListWidget *> 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<KItemListViewAccessible *>(QAccessible::queryAccessibleInterface(this))->announceDescriptionChange();
+#else
}
+ Q_UNUSED(previous)
+#endif
}
void KItemListView::slotAnimationFinished(QGraphicsWidget *widget, KItemListViewAnimation::AnimationType type)
}
// Delete invisible KItemListWidget instances that have not been reused
- for (int index : qAsConst(reusableItems)) {
+ for (int index : std::as_const(reusableItems)) {
recycleWidget(m_visibleItems.value(index));
}
const QFontMetricsF fontMetrics(m_headerWidget->font());
const int gripMargin = m_headerWidget->style()->pixelMetric(QStyle::PM_HeaderGripMargin);
const int headerMargin = m_headerWidget->style()->pixelMetric(QStyle::PM_HeaderMargin);
- for (const QByteArray &visibleRole : qAsConst(m_visibleRoles)) {
+ for (const QByteArray &visibleRole : std::as_const(m_visibleRoles)) {
const QString headerText = m_model->roleDescription(visibleRole);
const qreal headerWidth = fontMetrics.horizontalAdvance(headerText) + gripMargin + headerMargin * 2;
widths.insert(visibleRole, headerWidth);
const int endIndex = startIndex + itemRange.count - 1;
for (int i = startIndex; i <= endIndex; ++i) {
- for (const QByteArray &visibleRole : qAsConst(m_visibleRoles)) {
+ for (const QByteArray &visibleRole : std::as_const(m_visibleRoles)) {
qreal maxWidth = widths.value(visibleRole, 0);
const qreal width = creator->preferredRoleColumnWidth(visibleRole, i, this);
maxWidth = qMax(width, maxWidth);
void KItemListView::updateWidgetColumnWidths(KItemListWidget *widget)
{
- for (const QByteArray &role : qAsConst(m_visibleRoles)) {
+ for (const QByteArray &role : std::as_const(m_visibleRoles)) {
widget->setColumnWidth(role, m_headerWidget->columnWidth(role));
}
widget->setSidePadding(m_headerWidget->sidePadding());
if (itemCount == rangesItemCount) {
const QHash<QByteArray, qreal> preferredWidths = preferredColumnWidths(itemRanges);
- for (const QByteArray &role : qAsConst(m_visibleRoles)) {
+ for (const QByteArray &role : std::as_const(m_visibleRoles)) {
m_headerWidget->setPreferredColumnWidth(role, preferredWidths.value(role));
}
} else {
// size does not use the available view-size the size of the
// first role will get stretched.
- for (const QByteArray &role : qAsConst(m_visibleRoles)) {
+ for (const QByteArray &role : std::as_const(m_visibleRoles)) {
const qreal preferredWidth = m_headerWidget->preferredColumnWidth(role);
m_headerWidget->setColumnWidth(role, preferredWidth);
}
qreal KItemListView::columnWidthsSum() const
{
qreal widthsSum = 0;
- for (const QByteArray &role : qAsConst(m_visibleRoles)) {
+ for (const QByteArray &role : std::as_const(m_visibleRoles)) {
widthsSum += m_headerWidget->columnWidth(role);
}
return widthsSum;