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-24
0007  * Description : A DItemToolTip prepared for use in QAbstractItemViews
0008  *
0009  * SPDX-FileCopyrightText: 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "itemviewtooltip.h"
0016 
0017 // Qt includes
0018 
0019 #include <QApplication>
0020 #include <QToolTip>
0021 
0022 // Local includes
0023 
0024 #include "digikam_debug.h"
0025 
0026 namespace Digikam
0027 {
0028 
0029 class Q_DECL_HIDDEN ItemViewToolTip::Private
0030 {
0031 public:
0032 
0033     explicit Private()
0034       : view           (nullptr),
0035         filterInstalled(false)
0036     {
0037     }
0038 
0039     QAbstractItemView* view;
0040     QModelIndex        index;
0041     QRect              rect;
0042     QString            text;
0043     bool               filterInstalled;
0044 };
0045 
0046 ItemViewToolTip::ItemViewToolTip(QAbstractItemView* const view)
0047     : DItemToolTip(view),
0048       d           (new Private)
0049 {
0050     d->view = view;
0051 
0052     setForegroundRole(QPalette::ToolTipText);
0053     setBackgroundRole(QPalette::ToolTipBase);
0054     setMouseTracking(true);
0055 }
0056 
0057 ItemViewToolTip::~ItemViewToolTip()
0058 {
0059     delete d;
0060 }
0061 
0062 QAbstractItemView* ItemViewToolTip::view() const
0063 {
0064     return d->view;
0065 }
0066 
0067 QAbstractItemModel* ItemViewToolTip::model() const
0068 {
0069     return (d->view ? d->view->model() : nullptr);
0070 }
0071 
0072 QModelIndex ItemViewToolTip::currentIndex() const
0073 {
0074     return d->index;
0075 }
0076 
0077 void ItemViewToolTip::show(const QStyleOptionViewItem& option, const QModelIndex& index)
0078 {
0079     d->index = index;
0080     d->rect  = option.rect;
0081     d->rect.moveTopLeft(d->view->viewport()->mapToGlobal(d->rect.topLeft()));
0082     updateToolTip();
0083     reposition();
0084 
0085     if (isHidden() && !toolTipIsEmpty())
0086     {
0087         if (!d->filterInstalled)
0088         {
0089             qApp->installEventFilter(this);
0090             d->filterInstalled = true;
0091         }
0092 
0093         DItemToolTip::show();
0094     }
0095 }
0096 
0097 void ItemViewToolTip::setTipContents(const QString& tipContents)
0098 {
0099     d->text = tipContents;
0100     updateToolTip();
0101 }
0102 
0103 QString ItemViewToolTip::tipContents()
0104 {
0105     return d->text;
0106 }
0107 
0108 QRect ItemViewToolTip::repositionRect()
0109 {
0110     return d->rect;
0111 }
0112 
0113 void ItemViewToolTip::hideEvent(QHideEvent*)
0114 {
0115     d->rect  = QRect();
0116     d->index = QModelIndex();
0117 
0118     if (d->filterInstalled)
0119     {
0120         d->filterInstalled = false;
0121         qApp->removeEventFilter(this);
0122     }
0123 }
0124 
0125 // The following code is inspired by qtooltip.cpp,
0126 // Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
0127 
0128 bool ItemViewToolTip::eventFilter(QObject* o, QEvent* e)
0129 {
0130     switch (e->type())
0131     {
0132 
0133 #ifdef Q_OS_MACOS
0134 
0135         case QEvent::KeyPress:
0136         case QEvent::KeyRelease:
0137         {
0138             int key                    = static_cast<QKeyEvent*>(e)->key();
0139             Qt::KeyboardModifiers mody = static_cast<QKeyEvent*>(e)->modifiers();
0140 
0141             if (!(mody & Qt::KeyboardModifierMask) &&
0142                 (key != Qt::Key_Shift)             &&
0143                 (key != Qt::Key_Control)           &&
0144                 (key != Qt::Key_Alt)               &&
0145                 (key != Qt::Key_Meta))
0146             {
0147                 hide();
0148             }
0149 
0150             break;
0151         }
0152 
0153 #endif // Q_OS_MACOS
0154 
0155         case QEvent::Leave:
0156         {
0157             hide(); // could add a 300ms timer here, like Qt
0158             break;
0159         }
0160 
0161         case QEvent::WindowActivate:
0162         case QEvent::WindowDeactivate:
0163         case QEvent::MouseButtonPress:
0164         case QEvent::MouseButtonDblClick:
0165         case QEvent::FocusIn:
0166         case QEvent::FocusOut:
0167         case QEvent::Wheel:
0168         {
0169             hide();
0170             break;
0171         }
0172 
0173         case QEvent::MouseMove:
0174         {
0175             // needs mouse tracking, obviously
0176             if ((o == d->view->viewport()) &&
0177                 !d->rect.isNull()          &&
0178 
0179 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0180 
0181                 !d->rect.contains(static_cast<QMouseEvent*>(e)->globalPosition().toPoint()))
0182 
0183 #else
0184 
0185                 !d->rect.contains(static_cast<QMouseEvent*>(e)->globalPos()))
0186 
0187 #endif
0188 
0189             {
0190                 hide();
0191             }
0192 
0193             break;
0194         }
0195 
0196         default:
0197         {
0198             break;
0199         }
0200     }
0201 
0202     return false;
0203 }
0204 
0205 void ItemViewToolTip::mouseMoveEvent(QMouseEvent* e)
0206 {
0207     if (d->rect.isNull())
0208     {
0209         return;
0210     }
0211 
0212 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0213 
0214     QPoint pos = e->globalPosition().toPoint();
0215 
0216 #else
0217 
0218     QPoint pos = e->globalPos();
0219 
0220 #endif
0221 
0222     pos        = d->view->viewport()->mapFromGlobal(pos);
0223 
0224     if (!d->rect.contains(pos))
0225     {
0226         hide();
0227     }
0228 
0229     DItemToolTip::mouseMoveEvent(e);
0230 }
0231 
0232 } // namespace Digikam
0233 
0234 #include "moc_itemviewtooltip.cpp"