File indexing completed on 2024-12-01 06:45:09

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 void KDirOperatorIconView::initViewItemOption(QStyleOptionViewItem *option) const
0056 {
0057     QListView::initViewItemOption(option);
0058     option->showDecorationSelected = true;
0059     option->textElideMode = Qt::ElideMiddle;
0060     option->decorationPosition = decorationPosition;
0061     if (option->decorationPosition == QStyleOptionViewItem::Left) {
0062         option->displayAlignment = Qt::AlignLeft | Qt::AlignVCenter;
0063     } else {
0064         option->displayAlignment = Qt::AlignCenter;
0065     }
0066 }
0067 
0068 void KDirOperatorIconView::dragEnterEvent(QDragEnterEvent *event)
0069 {
0070     if (event->mimeData()->hasUrls()) {
0071         event->acceptProposedAction();
0072     }
0073 }
0074 
0075 void KDirOperatorIconView::mousePressEvent(QMouseEvent *event)
0076 {
0077     if (!indexAt(event->pos()).isValid()) {
0078         const Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();
0079         if (!(modifiers & Qt::ShiftModifier) && !(modifiers & Qt::ControlModifier)) {
0080             clearSelection();
0081         }
0082     }
0083 
0084     QListView::mousePressEvent(event);
0085 }
0086 
0087 void KDirOperatorIconView::wheelEvent(QWheelEvent *event)
0088 {
0089     QListView::wheelEvent(event);
0090 
0091     // apply the vertical wheel event to the horizontal scrollbar, as
0092     // the items are aligned from left to right
0093     if (event->angleDelta().y() != 0) {
0094         QWheelEvent horizEvent(event->position(),
0095                                event->globalPosition(),
0096                                QPoint(event->pixelDelta().y(), 0),
0097                                QPoint(event->angleDelta().y(), 0),
0098                                event->buttons(),
0099                                event->modifiers(),
0100                                event->phase(),
0101                                event->inverted(),
0102                                event->source());
0103         QApplication::sendEvent(horizontalScrollBar(), &horizEvent);
0104     }
0105 }
0106 
0107 void KDirOperatorIconView::updateLayout()
0108 {
0109     if (decorationPosition == QStyleOptionViewItem::Position::Top) {
0110         // Icons view
0111         setFlow(QListView::LeftToRight);
0112         const QFontMetrics metrics(viewport()->font());
0113 
0114         const int height = iconSize().height() + metrics.height() * 2.5;
0115         const int minWidth = qMax(height, metrics.height() * 5);
0116 
0117         const int scrollBarWidth = verticalScrollBar()->sizeHint().width();
0118 
0119         // Subtract 1 px to prevent flickering when resizing the window
0120         // For Oxygen a column is missing after showing the dialog without resizing it,
0121         // therefore subtract 4 more (scaled) pixels
0122         const int viewPortWidth = contentsRect().width() - scrollBarWidth - 1 - 4 * devicePixelRatioF();
0123         const int itemsInRow = qMax(1, viewPortWidth / minWidth);
0124         const int remainingWidth = viewPortWidth - (minWidth * itemsInRow);
0125         const int width = minWidth + (remainingWidth / itemsInRow);
0126 
0127         const QSize itemSize(width, height);
0128 
0129         setGridSize(itemSize);
0130         KFileItemDelegate *delegate = qobject_cast<KFileItemDelegate *>(itemDelegate());
0131         if (delegate) {
0132             delegate->setMaximumSize(itemSize);
0133         }
0134     } else {
0135         // compact view
0136         setFlow(QListView::TopToBottom);
0137         setGridSize(QSize());
0138         KFileItemDelegate *delegate = qobject_cast<KFileItemDelegate *>(itemDelegate());
0139         if (delegate) {
0140             delegate->setMaximumSize(QSize());
0141         }
0142     }
0143 }
0144 void KDirOperatorIconView::setDecorationPosition(QStyleOptionViewItem::Position newDecorationPosition)
0145 {
0146     decorationPosition = newDecorationPosition;
0147     updateLayout();
0148 }
0149 
0150 #include "moc_kdiroperatoriconview_p.cpp"