File indexing completed on 2024-05-19 04:27:45
0001 /* This file is part of the KDE project 0002 * SPDX-FileCopyrightText: 2019 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "KisResourceItemListView.h" 0008 0009 #include <QEvent> 0010 #include <QScroller> 0011 #include <QScrollBar> 0012 #include <QHelpEvent> 0013 0014 #include "KisIconToolTip.h" 0015 0016 0017 struct Q_DECL_HIDDEN KisResourceItemListView::Private 0018 { 0019 ListViewMode viewMode = ListViewMode::IconGrid; 0020 bool strictSelectionMode {false}; 0021 KisIconToolTip tip; 0022 0023 QScroller* scroller {0}; 0024 QString prev_scrollbar_style; 0025 0026 QSize requestedItemSize = QSize(56, 56); 0027 }; 0028 0029 KisResourceItemListView::KisResourceItemListView(QWidget *parent) 0030 : QListView(parent) 0031 , m_d(new Private) 0032 { 0033 setSelectionMode(QAbstractItemView::SingleSelection); 0034 setContextMenuPolicy(Qt::DefaultContextMenu); 0035 setResizeMode(QListView::Adjust); 0036 setUniformItemSizes(true); 0037 0038 // Default configuration 0039 setViewMode(QListView::IconMode); 0040 setGridSize(QSize(56, 56)); 0041 setIconSize(QSize(56, 56)); 0042 setResizeMode(QListView::Adjust); 0043 setUniformItemSizes(true); 0044 0045 m_d->scroller = KisKineticScroller::createPreconfiguredScroller(this); 0046 if (m_d->scroller) { 0047 connect(m_d->scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChange(QScroller::State))); 0048 } 0049 0050 connect(this, SIGNAL(clicked(QModelIndex)), SIGNAL(currentResourceClicked(const QModelIndex &))); 0051 0052 m_d->prev_scrollbar_style = horizontalScrollBar()->styleSheet(); 0053 } 0054 0055 KisResourceItemListView::~KisResourceItemListView() 0056 { 0057 } 0058 0059 void KisResourceItemListView::setListViewMode(ListViewMode viewMode) 0060 { 0061 m_d->viewMode = viewMode; 0062 0063 auto restoreScrollbar = [&, this] () { 0064 horizontalScrollBar()->setStyleSheet(m_d->prev_scrollbar_style); 0065 setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); 0066 }; 0067 0068 switch (viewMode) { 0069 case ListViewMode::IconGrid: { 0070 setViewMode(ViewMode::IconMode); 0071 setFlow(Flow::LeftToRight); 0072 setWrapping(true); 0073 restoreScrollbar(); 0074 0075 setItemSize(m_d->requestedItemSize); 0076 break; 0077 } 0078 case ListViewMode::IconStripHorizontal: { 0079 setViewMode(ViewMode::IconMode); 0080 setFlow(Flow::LeftToRight); 0081 setWrapping(false); 0082 0083 // this is the only way to hide it and not have it ocupy space 0084 horizontalScrollBar()->setStyleSheet("QScrollBar::horizontal {height: 0px;}"); 0085 setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff); 0086 0087 setItemSize(m_d->requestedItemSize); 0088 break; 0089 } 0090 case ListViewMode::Detail: { 0091 setViewMode(ViewMode::ListMode); 0092 setFlow(Flow::TopToBottom); 0093 setWrapping(false); 0094 restoreScrollbar(); 0095 setItemSize(m_d->requestedItemSize); 0096 // horizontalScrollBar()->setStyleSheet(m_d->prev_scrollbar_style); 0097 setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); 0098 setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); 0099 break; 0100 } 0101 } 0102 } 0103 0104 void KisResourceItemListView::setItemSize(QSize size) 0105 { 0106 m_d->requestedItemSize = size; 0107 0108 switch (m_d->viewMode) { 0109 case ListViewMode::IconGrid: { 0110 setGridSize(size); 0111 setIconSize(size); 0112 break; 0113 } 0114 case ListViewMode::IconStripHorizontal: { 0115 // you can not set the item size in strip mode 0116 // it is configured automatically based on size 0117 break; 0118 } 0119 case ListViewMode::Detail: { 0120 const int w = width() - horizontalScrollBar()->width(); 0121 setGridSize(QSize(w, size.height())); 0122 setIconSize(QSize(size)); 0123 break; 0124 } 0125 } 0126 } 0127 0128 void KisResourceItemListView::setStrictSelectionMode(bool enable) 0129 { 0130 m_d->strictSelectionMode = enable; 0131 } 0132 0133 void KisResourceItemListView::setFixedToolTipThumbnailSize(const QSize &size) 0134 { 0135 m_d->tip.setFixedToolTipThumbnailSize(size); 0136 } 0137 0138 void KisResourceItemListView::setToolTipShouldRenderCheckers(bool value) 0139 { 0140 m_d->tip.setToolTipShouldRenderCheckers(value); 0141 } 0142 0143 void KisResourceItemListView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) 0144 { 0145 // QAbstractItemView moves the current index if the row it points to is removed, 0146 // which we don't want for strict selections 0147 QModelIndex current = currentIndex(); 0148 if (selectionMode() == SingleSelection 0149 && m_d->strictSelectionMode 0150 && current.isValid() 0151 && current.row() >= start 0152 && current.row() <= end) { 0153 0154 selectionModel()->clear(); 0155 } 0156 QListView::rowsAboutToBeRemoved(parent, start, end); 0157 } 0158 0159 void KisResourceItemListView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) 0160 { 0161 // base class takes care of viewport updates 0162 QListView::selectionChanged(selected, deselected); 0163 0164 if (selected.isEmpty()) { 0165 emit currentResourceChanged(QModelIndex()); 0166 } 0167 else { 0168 emit currentResourceChanged(selected.indexes().first()); 0169 } 0170 } 0171 0172 QItemSelectionModel::SelectionFlags KisResourceItemListView::selectionCommand(const QModelIndex &index, const QEvent *event) const 0173 { 0174 QItemSelectionModel::SelectionFlags cmd = QListView::selectionCommand(index, event); 0175 0176 // avoid deselecting the current item by Ctrl-clicking in single selection mode 0177 if (selectionMode() == SingleSelection 0178 && m_d->strictSelectionMode 0179 && cmd.testFlag(QItemSelectionModel::Deselect)) { 0180 0181 cmd = QItemSelectionModel::NoUpdate; 0182 } 0183 return cmd; 0184 } 0185 0186 void KisResourceItemListView::contextMenuEvent(QContextMenuEvent *event) 0187 { 0188 QListView::contextMenuEvent(event); 0189 emit contextMenuRequested(event->globalPos()); 0190 } 0191 0192 bool KisResourceItemListView::viewportEvent(QEvent *event) 0193 { 0194 if (!model()) return true; 0195 0196 if (event->type() == QEvent::ToolTip) { 0197 QHelpEvent *he = static_cast<QHelpEvent *>(event); 0198 QStyleOptionViewItem option = viewOptions(); 0199 QModelIndex index = model()->buddy(indexAt(he->pos())); 0200 if (index.isValid()) { 0201 option.rect = visualRect(index); 0202 m_d->tip.showTip(this, he->pos(), option, index); 0203 return true; 0204 } 0205 m_d->tip.hide(); 0206 } 0207 0208 return QListView::viewportEvent(event); 0209 } 0210 0211 void KisResourceItemListView::resizeEvent(QResizeEvent *event) 0212 { 0213 QListView::resizeEvent(event); 0214 0215 switch (m_d->viewMode) { 0216 case ListViewMode::IconStripHorizontal: { 0217 const int height = event->size().height(); 0218 setGridSize(QSize(height, height)); 0219 setIconSize(QSize(height, height)); 0220 break; 0221 } 0222 case ListViewMode::Detail: { 0223 setItemSize(m_d->requestedItemSize); 0224 } 0225 } 0226 scrollTo(currentIndex(), QAbstractItemView::PositionAtCenter); 0227 }