File indexing completed on 2025-04-27 03:58:29

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2009-04-30
0007  * Description : Qt item view mouse hover button
0008  *
0009  * SPDX-FileCopyrightText: 2008      by Peter Penz <peter dot penz at gmx dot at>
0010  * SPDX-FileCopyrightText: 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "itemviewhoverbutton.h"
0017 
0018 // Qt includes
0019 
0020 #include <QPainter>
0021 #include <QPaintEvent>
0022 #include <QRect>
0023 #include <QTimer>
0024 #include <QTimeLine>
0025 #include <QIcon>
0026 
0027 namespace Digikam
0028 {
0029 
0030 ItemViewHoverButton::ItemViewHoverButton(QAbstractItemView* const view)
0031     : QAbstractButton(view->viewport()),
0032       m_isHovered       (false),
0033       m_fadingValue     (0),
0034       m_icon            (),
0035       m_fadingTimeLine  (nullptr)
0036 {
0037     m_fadingTimeLine = new QTimeLine(600, this);
0038     m_fadingTimeLine->setFrameRange(0, 255);
0039 
0040     setCheckable(true);
0041     setChecked(false);
0042 }
0043 
0044 void ItemViewHoverButton::setup()
0045 {
0046     connect(m_fadingTimeLine, SIGNAL(frameChanged(int)),
0047             this, SLOT(setFadingValue(int)));
0048 
0049     connect(this, SIGNAL(toggled(bool)),
0050             this, SLOT(refreshIcon()));
0051 }
0052 
0053 void ItemViewHoverButton::initIcon()
0054 {
0055     // virtual, cannot call from constructor
0056 
0057     refreshIcon();
0058     resize(sizeHint());
0059 }
0060 
0061 void ItemViewHoverButton::updateToolTip()
0062 {
0063 }
0064 
0065 void ItemViewHoverButton::reset()
0066 {
0067     m_index = QModelIndex();
0068     hide();
0069 }
0070 
0071 void ItemViewHoverButton::setIndex(const QModelIndex& index)
0072 {
0073     m_index = index;
0074 
0075     if (index.isValid())
0076     {
0077         startFading();
0078     }
0079 }
0080 
0081 QModelIndex ItemViewHoverButton::index() const
0082 {
0083     return m_index;
0084 }
0085 
0086 void ItemViewHoverButton::setVisible(bool visible)
0087 {
0088     QAbstractButton::setVisible(visible);
0089 
0090     stopFading();
0091 
0092     if (visible)
0093     {
0094         startFading();
0095     }
0096 }
0097 
0098 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0099 
0100 void ItemViewHoverButton::enterEvent(QEnterEvent* event)
0101 
0102 #else
0103 
0104 void ItemViewHoverButton::enterEvent(QEvent* event)
0105 
0106 #endif
0107 
0108 {
0109     QAbstractButton::enterEvent(event);
0110 
0111     // if the mouse cursor is above the button, display
0112     // it immediately without fading timer
0113 
0114     m_isHovered   = true;
0115     m_fadingTimeLine->stop();
0116     m_fadingValue = 255;
0117     updateToolTip();
0118     update();
0119 }
0120 
0121 void ItemViewHoverButton::leaveEvent(QEvent* event)
0122 {
0123     QAbstractButton::leaveEvent(event);
0124     m_isHovered = false;
0125     update();
0126 }
0127 
0128 void ItemViewHoverButton::paintEvent(QPaintEvent* event)
0129 {
0130     QPainter painter(this);
0131     painter.setClipRect(event->rect());
0132     painter.setRenderHint(QPainter::Antialiasing);
0133 
0134     // draw an alpha blended circle as background
0135 
0136     const QPalette& palette       = parentWidget()->palette();
0137 
0138     const QBrush& backgroundBrush = palette.brush(QPalette::Normal, QPalette::Window);
0139     QColor background             = backgroundBrush.color();
0140     background.setAlpha(m_fadingValue / 2);
0141     painter.setBrush(background);
0142 
0143     const QBrush& foregroundBrush = palette.brush(QPalette::Normal, QPalette::WindowText);
0144     QColor foreground             = foregroundBrush.color();
0145     foreground.setAlpha(m_fadingValue / 4);
0146     painter.setPen(foreground);
0147 
0148     painter.drawEllipse(0, 0, width(), height());
0149 
0150     // draw the icon overlay
0151 
0152     QPixmap icon = m_icon.pixmap(width() - 2, height() - 2);
0153 
0154     if (m_isHovered)
0155     {
0156         QPixmap hovered = icon;
0157         QPainter p(&hovered);
0158         p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
0159         p.fillRect(hovered.rect(), QColor(0, 0, 0, 127));
0160         p.setCompositionMode(QPainter::CompositionMode_Plus);
0161         p.drawPixmap(0, 0, icon);
0162         p.end();
0163         painter.drawPixmap(1, 1, hovered);
0164     }
0165     else
0166     {
0167         if (m_fadingValue < 255)
0168         {
0169             QPainter p(&icon);
0170             p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
0171             p.fillRect(icon.rect(), QColor(0, 0, 0, m_fadingValue));
0172             p.end();
0173             painter.drawPixmap(1, 1, icon);
0174         }
0175         else
0176         {
0177             // no fading is required
0178 
0179             painter.drawPixmap(1, 1, icon);
0180         }
0181     }
0182 }
0183 
0184 void ItemViewHoverButton::setFadingValue(int value)
0185 {
0186     m_fadingValue = value;
0187 
0188     if (m_fadingValue >= 255)
0189     {
0190         m_fadingTimeLine->stop();
0191     }
0192 
0193     update();
0194 }
0195 
0196 /*
0197 void ItemViewHoverButton::setIconOverlay()
0198 {
0199     const char* icon = isChecked() ? "list-remove" : "list-add";
0200     m_icon = QIcon::fromTheme(icon).pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize));
0201 }
0202 */
0203 
0204 void ItemViewHoverButton::refreshIcon()
0205 {
0206     m_icon = icon();
0207     update();
0208 }
0209 
0210 void ItemViewHoverButton::startFading()
0211 {
0212     if (m_fadingTimeLine->state() != QTimeLine::Running)
0213     {
0214         m_fadingTimeLine->start();
0215     }
0216 
0217     m_fadingValue = 0;
0218 }
0219 
0220 void ItemViewHoverButton::stopFading()
0221 {
0222     m_fadingTimeLine->stop();
0223     m_fadingValue = 0;
0224 }
0225 
0226 } // namespace Digikam
0227 
0228 #include "moc_itemviewhoverbutton.cpp"