File indexing completed on 2025-04-27 03:58:26
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2006-01-20 0007 * Description : action categorized view 0008 * 0009 * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #include "actioncategorizedview.h" 0016 0017 // Qt includes 0018 0019 #include <QString> 0020 #include <QPropertyAnimation> 0021 #include <QScrollBar> 0022 #include <QApplication> 0023 #include <QStyle> 0024 0025 // Local includes 0026 0027 #include "digikam_debug.h" 0028 #include "dcategorydrawer.h" 0029 0030 namespace Digikam 0031 { 0032 0033 ActionCategorizedView::ActionCategorizedView(QWidget* const parent, bool autoScroll) 0034 : DCategorizedView(parent), 0035 m_autoScroll (autoScroll) 0036 { 0037 m_horizontalScrollAnimation = new QPropertyAnimation(horizontalScrollBar(), "value", this); 0038 m_verticalScrollAnimation = new QPropertyAnimation(verticalScrollBar(), "value", this); 0039 } 0040 0041 ActionCategorizedView::~ActionCategorizedView() 0042 { 0043 } 0044 0045 void ActionCategorizedView::setupIconMode() 0046 { 0047 setViewMode(QListView::IconMode); 0048 setMovement(QListView::Static); 0049 setCategoryDrawer(new DCategoryDrawer(this)); // deprecated, but needed for KDE 4.4 compatibility 0050 setSelectionMode(QAbstractItemView::SingleSelection); 0051 0052 setMouseTracking(true); 0053 viewport()->setAttribute(Qt::WA_Hover); 0054 0055 setFrameShape(QFrame::NoFrame); 0056 } 0057 0058 void ActionCategorizedView::adjustGridSize() 0059 { 0060 // Find a suitable grid size. The delegate's size hint does never word-wrap. 0061 // To keep a suitable width, we want to word wrap. 0062 0063 setWordWrap(true); 0064 QStyleOptionViewItem option; 0065 0066 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0067 0068 initViewItemOption(&option); 0069 0070 #else 0071 0072 option = viewOptions(); 0073 0074 #endif 0075 0076 int maxWidth = option.decorationSize.width() * 4; 0077 QFontMetrics fm(option.font); 0078 QSize grid; 0079 0080 for (int i = 0 ; i < model()->rowCount() ; ++i) 0081 { 0082 const QModelIndex index = model()->index(i, 0); 0083 const QSize size = sizeHintForIndex(index); 0084 0085 if (size.width() > maxWidth) 0086 { 0087 QString text = index.data(Qt::DisplayRole).toString(); 0088 QRect wrappedRect = fm.boundingRect(QRect(0, 0, maxWidth, maxWidth), 0089 Qt::AlignLeft | Qt::TextWordWrap, text); 0090 grid = grid.expandedTo(QSize(maxWidth, wrappedRect.height())); 0091 } 0092 else 0093 { 0094 grid = grid.expandedTo(size); 0095 } 0096 } 0097 /* 0098 grid += QSize(qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing), 0099 QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)), qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing), 0100 QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing))); 0101 */ 0102 setGridSize(grid); 0103 } 0104 0105 int ActionCategorizedView::autoScrollDuration(float relativeDifference, QPropertyAnimation* animation) 0106 { 0107 const int minimumTime = 1000; 0108 const int maxPixelPerSecond = 1000; 0109 0110 int pixelToScroll = qAbs(animation->startValue().toInt() - animation->endValue().toInt()); 0111 int factor = qMax(1.0f, relativeDifference * 100); // in [1;15] 0112 0113 int duration = 1000 * pixelToScroll / maxPixelPerSecond; 0114 duration *= factor; 0115 0116 return qMax(minimumTime, duration); 0117 } 0118 0119 void ActionCategorizedView::autoScroll(float relativePos, QScrollBar* scrollBar, QPropertyAnimation* animation) 0120 { 0121 if (scrollBar->minimum() != scrollBar->maximum()) 0122 { 0123 const float lowerPart = 0.15F; 0124 const float upperPart = 0.85F; 0125 0126 if ((relativePos > upperPart) && (scrollBar->value() != scrollBar->maximum())) 0127 { 0128 animation->stop(); 0129 animation->setStartValue(scrollBar->value()); 0130 animation->setEndValue(scrollBar->maximum()); 0131 animation->setDuration(autoScrollDuration(1 - relativePos, animation)); 0132 animation->start(); 0133 } 0134 else if ((relativePos < lowerPart) && (scrollBar->value() != scrollBar->minimum())) 0135 { 0136 animation->stop(); 0137 animation->setStartValue(scrollBar->value()); 0138 animation->setEndValue(scrollBar->minimum()); 0139 animation->setDuration(autoScrollDuration(relativePos, animation)); 0140 animation->start(); 0141 } 0142 else 0143 { 0144 animation->stop(); 0145 } 0146 } 0147 } 0148 0149 void ActionCategorizedView::mouseMoveEvent(QMouseEvent* e) 0150 { 0151 DCategorizedView::mouseMoveEvent(e); 0152 0153 if (m_autoScroll) 0154 { 0155 autoScroll(float(e->pos().x()) / viewport()->width(), horizontalScrollBar(), m_horizontalScrollAnimation); 0156 autoScroll(float(e->pos().y()) / viewport()->height(), verticalScrollBar(), m_verticalScrollAnimation); 0157 } 0158 } 0159 0160 void ActionCategorizedView::leaveEvent(QEvent* e) 0161 { 0162 DCategorizedView::leaveEvent(e); 0163 m_horizontalScrollAnimation->stop(); 0164 m_verticalScrollAnimation->stop(); 0165 } 0166 0167 } // namespace Digikam 0168 0169 #include "moc_actioncategorizedview.cpp"