File indexing completed on 2024-05-19 05:35:25

0001 //////////////////////////////////////////////////////////////////////////////
0002 // oxygenlabeldata.cpp
0003 // data container for QLabel transition
0004 // -------------------
0005 //
0006 // SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
0007 //
0008 // SPDX-License-Identifier: MIT
0009 //////////////////////////////////////////////////////////////////////////////
0010 
0011 #include "oxygenlabeldata.h"
0012 
0013 #include <QEvent>
0014 #include <QPainter>
0015 #include <QTextStream>
0016 
0017 namespace Oxygen
0018 {
0019 // use 300 milliseconds for animation lock
0020 const int LabelData::_lockTime = 300;
0021 
0022 //______________________________________________________
0023 LabelData::LabelData(QObject *parent, QLabel *target, int duration)
0024     : TransitionData(parent, target, duration)
0025     , _target(target)
0026 {
0027     _target.data()->installEventFilter(this);
0028 
0029     const bool hasProxy(_target.data()->graphicsProxyWidget());
0030     const bool hasMessageWidget(hasParent(target, "KMessageWidget"));
0031 
0032     transition().data()->setFlags(hasProxy || hasMessageWidget ? TransitionWidget::Transparent : TransitionWidget::GrabFromWindow);
0033 
0034     connect(_target.data(), SIGNAL(destroyed()), SLOT(targetDestroyed()));
0035 }
0036 
0037 //___________________________________________________________________
0038 bool LabelData::eventFilter(QObject *object, QEvent *event)
0039 {
0040     if (object != _target.data())
0041         return TransitionData::eventFilter(object, event);
0042     switch (event->type()) {
0043     case QEvent::Show:
0044         /*
0045         at show event, on set the old text to current
0046         to avoid animate the "first" paint event.
0047         text mnemonic is always removed to avoid triggering the animation when only the
0048         latter is changed
0049         */
0050         _text = _target.data()->text().remove(QChar::fromLatin1('&'));
0051         break;
0052 
0053     case QEvent::Paint: {
0054         if (enabled() && _target) {
0055             // remove showMnemonic from text before comparing
0056             QString text(_target.data()->text().remove(QChar::fromLatin1('&')));
0057             if (text == _text) {
0058                 if (transparent() && transition().data()->isAnimated() && TransitionWidget::paintEnabled())
0059                     return true;
0060                 else
0061                     break;
0062             }
0063 
0064             // update text and pixmap
0065             _text = text;
0066 
0067             if (!(transition() && _target.data()->isVisible()))
0068                 break;
0069 
0070             if (transition().data()->isAnimated()) {
0071                 transition().data()->endAnimation();
0072             }
0073 
0074             // check whether animations are locked
0075             if (isLocked()) {
0076                 // hide transition widget
0077                 transition().data()->hide();
0078 
0079                 // restart the lock timer
0080                 // and abort transition
0081                 lockAnimations();
0082                 break;
0083             }
0084 
0085             // restart the lock timer
0086             // and prepare transition
0087             lockAnimations();
0088             initializeAnimation();
0089             _timer.start(0, this);
0090 
0091             if (!transition().data()->startPixmap().isNull() && TransitionWidget::paintEnabled()) {
0092                 // show the transition widget
0093                 // and disable this event painting
0094                 transition().data()->show();
0095                 transition().data()->raise();
0096                 if (transparent())
0097                     return true;
0098                 else
0099                     break;
0100 
0101             } else {
0102                 // hide transition widget and abort transition
0103                 transition().data()->hide();
0104                 break;
0105             }
0106 
0107         } else if (transition().data()->isAnimated() && TransitionWidget::paintEnabled()) {
0108             // disable painting when transition is running
0109             // since label is obscured by transition widget
0110             return true;
0111 
0112         } else
0113             break;
0114     }
0115 
0116     default:
0117         break;
0118     }
0119 
0120     return TransitionData::eventFilter(object, event);
0121 }
0122 
0123 //___________________________________________________________________
0124 void LabelData::timerEvent(QTimerEvent *event)
0125 {
0126     if (event->timerId() == _timer.timerId()) {
0127         _timer.stop();
0128 
0129         // check transition and widget validity
0130         if (!(enabled() && _target && transition()))
0131             return;
0132 
0133         // assign end pixmap
0134         transition().data()->setEndPixmap(transition().data()->grab(_target.data()));
0135 
0136         // start animation
0137         animate();
0138 
0139     } else if (event->timerId() == _animationLockTimer.timerId()) {
0140         unlockAnimations();
0141 
0142         // check transition and widget validity
0143         if (!(enabled() && _target && transition()))
0144             return;
0145 
0146         // reassign end pixmap for the next transition to be properly initialized
0147         transition().data()->setEndPixmap(transition().data()->grab(_target.data()));
0148 
0149     } else
0150         return TransitionData::timerEvent(event);
0151 }
0152 
0153 //___________________________________________________________________
0154 bool LabelData::initializeAnimation(void)
0155 {
0156     transition().data()->setOpacity(0);
0157     QRect current(_target.data()->geometry());
0158     if (_widgetRect.isValid() && _widgetRect != current) {
0159         _widgetRect = current;
0160         transition().data()->resetStartPixmap();
0161         transition().data()->resetEndPixmap();
0162         return false;
0163     }
0164 
0165     transition().data()->setStartPixmap(transition().data()->currentPixmap());
0166     transition().data()->setGeometry(_target.data()->rect());
0167     _widgetRect = current;
0168     return true;
0169 }
0170 
0171 //___________________________________________________________________
0172 bool LabelData::animate(void)
0173 {
0174     if (transition().data()->startPixmap().isNull())
0175         return false;
0176 
0177     transition().data()->animate();
0178     return true;
0179 }
0180 
0181 //___________________________________________________________________
0182 void LabelData::targetDestroyed(void)
0183 {
0184     setEnabled(false);
0185     _target.clear();
0186 }
0187 }