+QRect DolphinDetailsView::nameColumnRect(const QModelIndex& index) const
+{
+ // TODO: The code guesses the width of the name, but it is defined
+ // by KFileItemDelegate. Find a way to tell the item delegate to
+ // use a specified width.
+ QRect guessedItemContentRect = visualRect(index);
+ const KFileItem fileItem = m_controller->itemForIndex(index);
+ if (!fileItem.isNull()) {
+ QStyleOptionViewItem itemStyle = viewOptions();
+ QFontMetrics fontMetrics(itemStyle.font);
+ const int itemContentWidth = itemStyle.decorationSize.width() + fontMetrics.width(fileItem.name());
+ guessedItemContentRect.setWidth(itemContentWidth);
+ }
+
+ return guessedItemContentRect;
+}
+
+void DolphinDetailsView::setSelectionRecursive(const QModelIndex& startIndex,
+ const QRect& rect,
+ QItemSelectionModel::SelectionFlags command)
+{
+ if (!startIndex.isValid()) {
+ return;
+ }
+
+ // rect is assumed to be in viewport coordinates and normalized.
+ // Move down through the siblings of startIndex, exploring the children
+ // of any expanded nodes.
+ Q_ASSERT(rect.width() >= 0 && rect.height() >= 0);
+ QModelIndex currIndex = startIndex;
+ do {
+ const QModelIndex belowIndex = indexBelow(currIndex);
+ if (isExpanded(currIndex)) {
+ // If belowIndex exists and is above the top of rect, then we need not explore
+ // the children of currIndex as they will always be above "below". Otherwise,
+ // explore the children.
+ if (!belowIndex.isValid() || visualRect(belowIndex).bottom() >= rect.top()) {
+ setSelectionRecursive(currIndex.child(0, currIndex.column()), rect, command);
+ }
+ }
+
+ QRect itemContentRect = nameColumnRect(currIndex);
+ if (itemContentRect.top() > rect.bottom()) {
+ // All remaining items will be below itemContentRect, so we may cull.
+ return;
+ }
+
+ if (itemContentRect.intersects(rect)) {
+ selectionModel()->select(currIndex, QItemSelectionModel::Select);
+ }
+
+ currIndex = belowIndex;
+ } while (currIndex.isValid());
+}
+