File indexing completed on 2024-05-19 04:27:45

0001 /*
0002  * SPDX-FileCopyrightText: 2023 Srirupa Datta <srirupa.sps@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "KisResourceItemListWidget.h"
0008 
0009 #include <QDebug>
0010 #include <QEvent>
0011 #include <QHeaderView>
0012 #include <QHelpEvent>
0013 #include <QScroller>
0014 #include <QScrollBar>
0015 #include <QScrollArea>
0016 
0017 #include "KisIconToolTip.h"
0018 
0019 
0020 struct  Q_DECL_HIDDEN KisResourceItemListWidget::Private
0021 {
0022     ListViewMode viewMode = ListViewMode::IconGrid;
0023     bool strictSelectionMode {false};
0024     KisIconToolTip tip;
0025 
0026     QScroller* scroller {0};
0027     QString prev_scrollbar_style;
0028 };
0029 
0030 KisResourceItemListWidget::KisResourceItemListWidget(QWidget *parent)
0031     : QListWidget(parent)
0032     , m_d(new Private)
0033 {
0034     setSelectionMode(QAbstractItemView::ExtendedSelection);
0035     setContextMenuPolicy(Qt::DefaultContextMenu);
0036     setViewMode(QListView::IconMode);
0037     setGridSize(QSize(56, 56));
0038     setIconSize(QSize(56, 56));
0039     setResizeMode(QListWidget::Adjust);
0040     setUniformItemSizes(true);
0041 
0042     m_d->scroller = KisKineticScroller::createPreconfiguredScroller(this);
0043     if (m_d->scroller) {
0044         connect(m_d->scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChange(QScroller::State)));
0045     }
0046 
0047     connect(this, SIGNAL(clicked(QModelIndex)), SIGNAL(currentResourceClicked(const QModelIndex &)));
0048 
0049      m_d->prev_scrollbar_style = horizontalScrollBar()->styleSheet();
0050 }
0051 
0052 KisResourceItemListWidget::~KisResourceItemListWidget()
0053 {
0054 }
0055 
0056 void KisResourceItemListWidget::setListViewMode(ListViewMode viewMode)
0057 {
0058     m_d->viewMode = viewMode;
0059 
0060     switch (viewMode) {
0061     case ListViewMode::IconGrid: {
0062         setViewMode(ViewMode::IconMode);
0063         setFlow(Flow::LeftToRight);
0064         setWrapping(true);
0065         horizontalScrollBar()->setStyleSheet(m_d->prev_scrollbar_style);
0066         setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded);
0067         break;
0068     }
0069     case ListViewMode::IconStripHorizontal: {
0070         setViewMode(ViewMode::IconMode);
0071         setFlow(Flow::LeftToRight);
0072         setWrapping(false);
0073 
0074         // this is the only way to hide it and not have it ocupy space
0075         horizontalScrollBar()->setStyleSheet("QScrollBar::horizontal {height: 0px;}");
0076         setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
0077         break;
0078     }
0079     case ListViewMode::Detail: {
0080         setViewMode(ViewMode::ListMode);
0081         setFlow(Flow::TopToBottom);
0082         setWrapping(false);
0083         // horizontalScrollBar()->setStyleSheet(m_d->prev_scrollbar_style);
0084         setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded);
0085         setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded);
0086         break;
0087     }
0088     }
0089 
0090     setItemSize(iconSize());
0091 }
0092 
0093 void KisResourceItemListWidget::setItemSize(QSize size)
0094 {
0095     switch (m_d->viewMode) {
0096     case ListViewMode::IconGrid: {
0097         setGridSize(size);
0098         setIconSize(size);
0099         break;
0100     }
0101     case ListViewMode::IconStripHorizontal: {
0102         // you can not set the item size in strip mode
0103         // it is configured automatically based on size
0104         break;
0105     }
0106     case ListViewMode::Detail: {
0107         const int w = width();
0108         setGridSize(QSize(w, size.height()));
0109         setIconSize(QSize(size));
0110         break;
0111     }
0112     }
0113 }
0114 
0115 void KisResourceItemListWidget::setStrictSelectionMode(bool enable)
0116 {
0117     m_d->strictSelectionMode = enable;
0118 }
0119 
0120 void KisResourceItemListWidget::setFixedToolTipThumbnailSize(const QSize &size)
0121 {
0122     m_d->tip.setFixedToolTipThumbnailSize(size);
0123 }
0124 
0125 void KisResourceItemListWidget::setToolTipShouldRenderCheckers(bool value)
0126 {
0127     m_d->tip.setToolTipShouldRenderCheckers(value);
0128 }
0129 
0130 void KisResourceItemListWidget::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
0131 {
0132     // QAbstractItemView moves the current index if the row it points to is removed,
0133     // which we don't want for strict selections
0134     QModelIndex current = currentIndex();
0135     if (selectionMode() == SingleSelection
0136             && m_d->strictSelectionMode
0137             && current.isValid()
0138             && current.row() >= start
0139             && current.row() <= end) {
0140 
0141         selectionModel()->clear();
0142     }
0143     QListWidget::rowsAboutToBeRemoved(parent, start, end);
0144 }
0145 
0146 void KisResourceItemListWidget::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
0147 {
0148     // base class takes care of viewport updates
0149     QListWidget::selectionChanged(selected, deselected);
0150 
0151     if (selected.isEmpty()) {
0152         emit currentResourceChanged(QModelIndex());
0153     }
0154     else {
0155         emit currentResourceChanged(selected.indexes().first());
0156     }
0157 }
0158 
0159 QItemSelectionModel::SelectionFlags KisResourceItemListWidget::selectionCommand(const QModelIndex &index, const QEvent *event) const
0160 {
0161     QItemSelectionModel::SelectionFlags cmd = QListWidget::selectionCommand(index, event);
0162 
0163     // avoid deselecting the current item by Ctrl-clicking in single selection mode
0164     if (selectionMode() == SingleSelection
0165             && m_d->strictSelectionMode
0166             && cmd.testFlag(QItemSelectionModel::Deselect)) {
0167 
0168         cmd = QItemSelectionModel::NoUpdate;
0169     }
0170     return cmd;
0171 }
0172 
0173 void KisResourceItemListWidget::contextMenuEvent(QContextMenuEvent *event)
0174 {
0175     QListWidget::contextMenuEvent(event);
0176     emit contextMenuRequested(event->globalPos());
0177 }
0178 
0179 bool KisResourceItemListWidget::viewportEvent(QEvent *event)
0180 {
0181     return QListWidget::viewportEvent(event);
0182 }
0183 
0184 void KisResourceItemListWidget::resizeEvent(QResizeEvent *event)
0185 {
0186     if (m_d->viewMode == ListViewMode::IconStripHorizontal) {
0187         const int height = event->size().height();
0188         setGridSize(QSize(height, height));
0189         setIconSize(QSize(height, height));
0190     }
0191     // trigger relaying the items, internally here not externally
0192     // by calling setItemSize
0193     else {
0194         setGridSize(gridSize());
0195     }
0196 }