File indexing completed on 2024-12-01 09:53:05

0001 /*
0002     SPDX-FileCopyrightText: 2007 Peter Penz <peter.penz@gmx.at>
0003     SPDX-FileCopyrightText: 2019 Méven Car <meven.car@kdemail.net>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-only
0006 */
0007 
0008 #include "kdiroperatoriconview_p.h"
0009 
0010 #include <QApplication>
0011 #include <QDragEnterEvent>
0012 #include <QMimeData>
0013 #include <QScrollBar>
0014 
0015 #include <KFileItemDelegate>
0016 #include <KIconLoader>
0017 
0018 KDirOperatorIconView::KDirOperatorIconView(QWidget *parent, QStyleOptionViewItem::Position aDecorationPosition)
0019     : QListView(parent)
0020 {
0021     setViewMode(QListView::IconMode);
0022     setResizeMode(QListView::Adjust);
0023     setSpacing(0);
0024     setMovement(QListView::Static);
0025     setDragDropMode(QListView::DragOnly);
0026     setVerticalScrollMode(QListView::ScrollPerPixel);
0027     setHorizontalScrollMode(QListView::ScrollPerPixel);
0028     setEditTriggers(QAbstractItemView::NoEditTriggers);
0029     setWordWrap(true);
0030     setIconSize(QSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall));
0031 
0032     decorationPosition = aDecorationPosition;
0033 
0034     const QFontMetrics metrics(viewport()->font());
0035     const int singleStep = metrics.height() * QApplication::wheelScrollLines();
0036 
0037     verticalScrollBar()->setSingleStep(singleStep);
0038     horizontalScrollBar()->setSingleStep(singleStep);
0039 
0040     updateLayout();
0041     connect(this, &QListView::iconSizeChanged, this, &KDirOperatorIconView::updateLayout);
0042 }
0043 
0044 KDirOperatorIconView::~KDirOperatorIconView()
0045 {
0046 }
0047 
0048 void KDirOperatorIconView::resizeEvent(QResizeEvent *event)
0049 {
0050     Q_UNUSED(event);
0051 
0052     updateLayout();
0053 }
0054 
0055 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0056 void KDirOperatorIconView::initViewItemOption(QStyleOptionViewItem *option) const
0057 {
0058     QListView::initViewItemOption(option);
0059     option->showDecorationSelected = true;
0060     option->textElideMode = Qt::ElideMiddle;
0061     option->decorationPosition = decorationPosition;
0062     if (option->decorationPosition == QStyleOptionViewItem::Left) {
0063         option->displayAlignment = Qt::AlignLeft | Qt::AlignVCenter;
0064     } else {
0065         option->displayAlignment = Qt::AlignCenter;
0066     }
0067 }
0068 #else
0069 QStyleOptionViewItem KDirOperatorIconView::viewOptions() const
0070 {
0071     QStyleOptionViewItem viewOptions = QListView::viewOptions();
0072     viewOptions.showDecorationSelected = true;
0073     viewOptions.textElideMode = Qt::ElideMiddle;
0074     viewOptions.decorationPosition = decorationPosition;
0075     if (viewOptions.decorationPosition == QStyleOptionViewItem::Left) {
0076         viewOptions.displayAlignment = Qt::AlignLeft | Qt::AlignVCenter;
0077     } else {
0078         viewOptions.displayAlignment = Qt::AlignCenter;
0079     }
0080 
0081     return viewOptions;
0082 }
0083 #endif
0084 
0085 void KDirOperatorIconView::dragEnterEvent(QDragEnterEvent *event)
0086 {
0087     if (event->mimeData()->hasUrls()) {
0088         event->acceptProposedAction();
0089     }
0090 }
0091 
0092 void KDirOperatorIconView::mousePressEvent(QMouseEvent *event)
0093 {
0094     if (!indexAt(event->pos()).isValid()) {
0095         const Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();
0096         if (!(modifiers & Qt::ShiftModifier) && !(modifiers & Qt::ControlModifier)) {
0097             clearSelection();
0098         }
0099     }
0100 
0101     QListView::mousePressEvent(event);
0102 }
0103 
0104 void KDirOperatorIconView::wheelEvent(QWheelEvent *event)
0105 {
0106     QListView::wheelEvent(event);
0107 
0108     // apply the vertical wheel event to the horizontal scrollbar, as
0109     // the items are aligned from left to right
0110     if (event->angleDelta().y() != 0) {
0111         QWheelEvent horizEvent(event->position(),
0112                                event->globalPosition(),
0113                                QPoint(event->pixelDelta().y(), 0),
0114                                QPoint(event->angleDelta().y(), 0),
0115                                event->buttons(),
0116                                event->modifiers(),
0117                                event->phase(),
0118                                event->inverted(),
0119                                event->source());
0120         QApplication::sendEvent(horizontalScrollBar(), &horizEvent);
0121     }
0122 }
0123 
0124 void KDirOperatorIconView::updateLayout()
0125 {
0126     if (decorationPosition == QStyleOptionViewItem::Position::Top) {
0127         // Icons view
0128         setFlow(QListView::LeftToRight);
0129         const QFontMetrics metrics(viewport()->font());
0130 
0131         const int height = iconSize().height() + metrics.height() * 2.5;
0132         const int minWidth = qMax(height, metrics.height() * 5);
0133 
0134         const int scrollBarWidth = verticalScrollBar()->sizeHint().width();
0135 
0136         // Subtract 1 px to prevent flickering when resizing the window
0137         // For Oxygen a column is missing after showing the dialog without resizing it,
0138         // therefore subtract 4 more (scaled) pixels
0139         const int viewPortWidth = contentsRect().width() - scrollBarWidth - 1 - 4 * devicePixelRatioF();
0140         const int itemsInRow = qMax(1, viewPortWidth / minWidth);
0141         const int remainingWidth = viewPortWidth - (minWidth * itemsInRow);
0142         const int width = minWidth + (remainingWidth / itemsInRow);
0143 
0144         const QSize itemSize(width, height);
0145 
0146         setGridSize(itemSize);
0147         KFileItemDelegate *delegate = qobject_cast<KFileItemDelegate *>(itemDelegate());
0148         if (delegate) {
0149             delegate->setMaximumSize(itemSize);
0150         }
0151     } else {
0152         // compact view
0153         setFlow(QListView::TopToBottom);
0154         setGridSize(QSize());
0155         KFileItemDelegate *delegate = qobject_cast<KFileItemDelegate *>(itemDelegate());
0156         if (delegate) {
0157             delegate->setMaximumSize(QSize());
0158         }
0159     }
0160 }
0161 void KDirOperatorIconView::setDecorationPosition(QStyleOptionViewItem::Position newDecorationPosition)
0162 {
0163     decorationPosition = newDecorationPosition;
0164     updateLayout();
0165 }
0166 
0167 #include "moc_kdiroperatoriconview_p.cpp"