1 | /* |
2 | SPDX-FileCopyrightText: 2007 Peter Penz <peter.penz@gmx.at> |
3 | SPDX-FileCopyrightText: 2019 Méven Car <meven.car@kdemail.net> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-only |
6 | */ |
7 | |
8 | #include "kdiroperatoriconview_p.h" |
9 | |
10 | #include <QApplication> |
11 | #include <QDragEnterEvent> |
12 | #include <QMimeData> |
13 | #include <QScrollBar> |
14 | |
15 | #include <KFileItemDelegate> |
16 | #include <KIconLoader> |
17 | |
18 | KDirOperatorIconView::KDirOperatorIconView(QWidget *parent, QStyleOptionViewItem::Position aDecorationPosition) |
19 | : QListView(parent) |
20 | { |
21 | setViewMode(QListView::IconMode); |
22 | setResizeMode(QListView::Adjust); |
23 | setSpacing(0); |
24 | setMovement(QListView::Static); |
25 | setDragDropMode(QListView::DragOnly); |
26 | setVerticalScrollMode(QListView::ScrollPerPixel); |
27 | setHorizontalScrollMode(QListView::ScrollPerPixel); |
28 | setEditTriggers(QAbstractItemView::NoEditTriggers); |
29 | setWordWrap(true); |
30 | setIconSize(QSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall)); |
31 | |
32 | decorationPosition = aDecorationPosition; |
33 | |
34 | const QFontMetrics metrics(viewport()->font()); |
35 | const int singleStep = metrics.height() * QApplication::wheelScrollLines(); |
36 | |
37 | verticalScrollBar()->setSingleStep(singleStep); |
38 | horizontalScrollBar()->setSingleStep(singleStep); |
39 | |
40 | updateLayout(); |
41 | connect(sender: this, signal: &QListView::iconSizeChanged, context: this, slot: &KDirOperatorIconView::updateLayout); |
42 | } |
43 | |
44 | KDirOperatorIconView::~KDirOperatorIconView() |
45 | { |
46 | } |
47 | |
48 | void KDirOperatorIconView::resizeEvent(QResizeEvent *event) |
49 | { |
50 | Q_UNUSED(event); |
51 | |
52 | updateLayout(); |
53 | } |
54 | |
55 | void KDirOperatorIconView::initViewItemOption(QStyleOptionViewItem *option) const |
56 | { |
57 | QListView::initViewItemOption(option); |
58 | option->showDecorationSelected = true; |
59 | option->textElideMode = Qt::ElideMiddle; |
60 | option->decorationPosition = decorationPosition; |
61 | if (option->decorationPosition == QStyleOptionViewItem::Left) { |
62 | option->displayAlignment = Qt::AlignLeft | Qt::AlignVCenter; |
63 | } else { |
64 | option->displayAlignment = Qt::AlignCenter; |
65 | } |
66 | } |
67 | |
68 | void KDirOperatorIconView::dragEnterEvent(QDragEnterEvent *event) |
69 | { |
70 | if (event->mimeData()->hasUrls()) { |
71 | event->acceptProposedAction(); |
72 | } |
73 | } |
74 | |
75 | void KDirOperatorIconView::mousePressEvent(QMouseEvent *event) |
76 | { |
77 | if (!indexAt(p: event->pos()).isValid()) { |
78 | const Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers(); |
79 | if (!(modifiers & Qt::ShiftModifier) && !(modifiers & Qt::ControlModifier)) { |
80 | clearSelection(); |
81 | } |
82 | } |
83 | |
84 | QListView::mousePressEvent(event); |
85 | } |
86 | |
87 | void KDirOperatorIconView::wheelEvent(QWheelEvent *event) |
88 | { |
89 | QListView::wheelEvent(e: event); |
90 | |
91 | // apply the vertical wheel event to the horizontal scrollbar, as |
92 | // the items are aligned from left to right |
93 | if (event->angleDelta().y() != 0) { |
94 | QWheelEvent horizEvent(event->position(), |
95 | event->globalPosition(), |
96 | QPoint(event->pixelDelta().y(), 0), |
97 | QPoint(event->angleDelta().y(), 0), |
98 | event->buttons(), |
99 | event->modifiers(), |
100 | event->phase(), |
101 | event->inverted(), |
102 | event->source()); |
103 | QApplication::sendEvent(receiver: horizontalScrollBar(), event: &horizEvent); |
104 | } |
105 | } |
106 | |
107 | void KDirOperatorIconView::updateLayout() |
108 | { |
109 | if (decorationPosition == QStyleOptionViewItem::Position::Top) { |
110 | // Icons view |
111 | setFlow(QListView::LeftToRight); |
112 | const QFontMetrics metrics(viewport()->font()); |
113 | |
114 | const int height = iconSize().height() + metrics.height() * 2.5; |
115 | const int minWidth = qMax(a: height, b: metrics.height() * 5); |
116 | |
117 | const int scrollBarWidth = verticalScrollBar()->sizeHint().width(); |
118 | |
119 | // Subtract 1 px to prevent flickering when resizing the window |
120 | // For Oxygen a column is missing after showing the dialog without resizing it, |
121 | // therefore subtract 4 more (scaled) pixels |
122 | const int viewPortWidth = contentsRect().width() - scrollBarWidth - 1 - 4 * devicePixelRatioF(); |
123 | const int itemsInRow = qMax(a: 1, b: viewPortWidth / minWidth); |
124 | const int remainingWidth = viewPortWidth - (minWidth * itemsInRow); |
125 | const int width = minWidth + (remainingWidth / itemsInRow); |
126 | |
127 | const QSize itemSize(width, height); |
128 | |
129 | setGridSize(itemSize); |
130 | KFileItemDelegate *delegate = qobject_cast<KFileItemDelegate *>(object: itemDelegate()); |
131 | if (delegate) { |
132 | delegate->setMaximumSize(itemSize); |
133 | } |
134 | } else { |
135 | // compact view |
136 | setFlow(QListView::TopToBottom); |
137 | setGridSize(QSize()); |
138 | KFileItemDelegate *delegate = qobject_cast<KFileItemDelegate *>(object: itemDelegate()); |
139 | if (delegate) { |
140 | delegate->setMaximumSize(QSize()); |
141 | } |
142 | } |
143 | } |
144 | void KDirOperatorIconView::setDecorationPosition(QStyleOptionViewItem::Position newDecorationPosition) |
145 | { |
146 | decorationPosition = newDecorationPosition; |
147 | updateLayout(); |
148 | } |
149 | |
150 | #include "moc_kdiroperatoriconview_p.cpp" |
151 | |