Explorar o código

Expose delays and duration of the popup widget

Allows custom fine tuning of the popup.
Julien Finet %!s(int64=13) %!d(string=hai) anos
pai
achega
734ffd3af5

+ 19 - 5
Libs/Widgets/ctkBasePopupWidget.cpp

@@ -37,8 +37,6 @@
 // CTK includes
 #include "ctkBasePopupWidget_p.h"
 
-#define DEFAULT_FADING_DURATION 333 // fast enough without being too slow
-
 // -------------------------------------------------------------------------
 QGradient* duplicateGradient(const QGradient* gradient)
 {
@@ -83,6 +81,7 @@ ctkBasePopupWidgetPrivate::ctkBasePopupWidgetPrivate(ctkBasePopupWidget& object)
 {
   this->BaseWidget = 0;
   this->Effect = ctkBasePopupWidget::ScrollEffect;
+  this->EffectDuration = 333; // in ms
   this->EffectAlpha = 1.;
   this->AlphaAnimation = 0;
   this->ForcedTranslucent = false;
@@ -110,7 +109,7 @@ void ctkBasePopupWidgetPrivate::init()
   q->setAttribute(Qt::WA_AlwaysShowToolTips, true);
 
   this->AlphaAnimation = new QPropertyAnimation(q, "effectAlpha", q);
-  this->AlphaAnimation->setDuration(DEFAULT_FADING_DURATION);
+  this->AlphaAnimation->setDuration(this->EffectDuration);
   this->AlphaAnimation->setStartValue(0.);
   this->AlphaAnimation->setEndValue(1.);
   QObject::connect(this->AlphaAnimation, SIGNAL(finished()),
@@ -119,7 +118,7 @@ void ctkBasePopupWidgetPrivate::init()
   this->PopupPixmapWidget = new QLabel(q, Qt::ToolTip | Qt::FramelessWindowHint);
 
   this->ScrollAnimation = new QPropertyAnimation(q, "effectGeometry", q);
-  this->ScrollAnimation->setDuration(DEFAULT_FADING_DURATION);
+  this->ScrollAnimation->setDuration(this->EffectDuration);
   QObject::connect(this->ScrollAnimation, SIGNAL(finished()),
                    q, SLOT(onEffectFinished()));
   QObject::connect(this->ScrollAnimation, SIGNAL(finished()),
@@ -478,7 +477,6 @@ ctkBasePopupWidget::ctkBasePopupWidget(ctkBasePopupWidgetPrivate* pimpl, QWidget
 {
 }
 
-
 // -------------------------------------------------------------------------
 ctkBasePopupWidget::~ctkBasePopupWidget()
 {
@@ -534,6 +532,22 @@ void ctkBasePopupWidget::setAnimationEffect(ctkBasePopupWidget::AnimationEffect
 }
 
 // -------------------------------------------------------------------------
+int ctkBasePopupWidget::effectDuration()const
+{
+  Q_D(const ctkBasePopupWidget);
+  return d->EffectDuration;
+}
+
+// -------------------------------------------------------------------------
+void ctkBasePopupWidget::setEffectDuration(int duration)
+{
+  Q_D(ctkBasePopupWidget);
+  d->EffectDuration = duration;
+  d->AlphaAnimation->setDuration(d->EffectDuration);
+  d->ScrollAnimation->setDuration(d->EffectDuration);
+}
+
+// -------------------------------------------------------------------------
 QEasingCurve::Type ctkBasePopupWidget::easingCurve()const
 {
   Q_D(const ctkBasePopupWidget);

+ 13 - 6
Libs/Widgets/ctkBasePopupWidget.h

@@ -35,17 +35,21 @@ class ctkBasePopupWidgetPrivate;
 class CTK_WIDGETS_EXPORT ctkBasePopupWidget : public QFrame
 {
   Q_OBJECT
-  
+
   Q_ENUMS(AnimationEffect)
   Q_ENUMS(VerticalDirection)
 
   /// ScrollEffect by default
   Q_PROPERTY( AnimationEffect animationEffect READ animationEffect WRITE setAnimationEffect)
-  
+
+  /// Effect duration in ms
+  /// Default to 333ms
+  Q_PROPERTY( int effectDuration READ effectDuration WRITE setEffectDuration);
+
   /// Opening/Closing curve
   /// QEasingCurve::InOutQuad by default
   Q_PROPERTY( QEasingCurve::Type easingCurve READ easingCurve WRITE setEasingCurve);
-  
+
   /// Where is the popup in relation to the BaseWidget
   /// To vertically justify, use Qt::AlignTop | Qt::AlignBottom
   /// Qt::AlignJustify | Qt::AlignBottom by default
@@ -88,13 +92,16 @@ public:
     ScrollEffect,
     FadeEffect
   };
-  
+
   AnimationEffect animationEffect()const;
   void setAnimationEffect(AnimationEffect effect);
-  
+
+  int effectDuration()const;
+  void setEffectDuration(int duration);
+
   QEasingCurve::Type easingCurve()const;
   void setEasingCurve(QEasingCurve::Type easingCurve);
-  
+
   Qt::Alignment alignment()const;
   void setAlignment(Qt::Alignment alignment);
   

+ 2 - 1
Libs/Widgets/ctkBasePopupWidget_p.h

@@ -88,6 +88,7 @@ protected:
   double EffectAlpha;
 
   ctkBasePopupWidget::AnimationEffect Effect;
+  int                 EffectDuration;
   QPropertyAnimation* AlphaAnimation;
   bool                ForcedTranslucent;
   QPropertyAnimation* ScrollAnimation;
@@ -96,7 +97,7 @@ protected:
   // Geometry attributes
   Qt::Alignment    Alignment;
   Qt::Orientations Orientations;
-  
+
   ctkBasePopupWidget::VerticalDirection VerticalDirection;
   Qt::LayoutDirection HorizontalDirection;
 };

+ 54 - 27
Libs/Widgets/ctkPopupWidget.cpp

@@ -37,17 +37,15 @@
 // CTK includes
 #include "ctkPopupWidget_p.h"
 
-#define LEAVE_CLOSING_DELAY 100 // we don't want to be too fast to close
-#define ENTER_OPENING_DELAY 20 // we want to be responsive but allow "errors"
-#define DEFAULT_FADING_DURATION 333 // fast enough without being too slow
-
 // -------------------------------------------------------------------------
 ctkPopupWidgetPrivate::ctkPopupWidgetPrivate(ctkPopupWidget& object)
   :Superclass(object)
 {
   this->Active = false;
   this->AutoShow = true;
+  this->ShowDelay = 20;
   this->AutoHide = true;
+  this->HideDelay = 200;
 }
 
 // -------------------------------------------------------------------------
@@ -312,7 +310,7 @@ void ctkPopupWidget::setBaseWidget(QWidget* widget)
     {
     d->BaseWidget->installEventFilter(this);
     }
-  QTimer::singleShot(ENTER_OPENING_DELAY, this, SLOT(updatePopup()));
+  QTimer::singleShot(d->ShowDelay, this, SLOT(updatePopup()));
 }
 
 // -------------------------------------------------------------------------
@@ -327,7 +325,21 @@ void ctkPopupWidget::setAutoShow(bool mode)
 {
   Q_D(ctkPopupWidget);
   d->AutoShow = mode;
-  QTimer::singleShot(ENTER_OPENING_DELAY, this, SLOT(updatePopup()));
+  QTimer::singleShot(d->ShowDelay, this, SLOT(updatePopup()));
+}
+
+// -------------------------------------------------------------------------
+int ctkPopupWidget::showDelay()const
+{
+  Q_D(const ctkPopupWidget);
+  return d->ShowDelay;
+}
+
+// -------------------------------------------------------------------------
+void ctkPopupWidget::setShowDelay(int delay)
+{
+  Q_D(ctkPopupWidget);
+  d->ShowDelay = delay;
 }
 
 // -------------------------------------------------------------------------
@@ -342,7 +354,21 @@ void ctkPopupWidget::setAutoHide(bool mode)
 {
   Q_D(ctkPopupWidget);
   d->AutoHide = mode;
-  QTimer::singleShot(LEAVE_CLOSING_DELAY, this, SLOT(updatePopup()));
+  QTimer::singleShot(d->HideDelay, this, SLOT(updatePopup()));
+}
+
+// -------------------------------------------------------------------------
+int ctkPopupWidget::hideDelay()const
+{
+  Q_D(const ctkPopupWidget);
+  return d->HideDelay;
+}
+
+// -------------------------------------------------------------------------
+void ctkPopupWidget::setHideDelay(int delay)
+{
+  Q_D(ctkPopupWidget);
+  d->HideDelay = delay;
 }
 
 // -------------------------------------------------------------------------
@@ -365,15 +391,16 @@ void ctkPopupWidget::onEffectFinished()
 // --------------------------------------------------------------------------
 void ctkPopupWidget::leaveEvent(QEvent* event)
 {
-  //QTimer::singleShot(LEAVE_CLOSING_DELAY, this, SLOT(updatePopup()));
-  this->updatePopup();
+  Q_D(ctkPopupWidget);
+  QTimer::singleShot(d->HideDelay, this, SLOT(updatePopup()));
   this->Superclass::leaveEvent(event);
 }
 
 // --------------------------------------------------------------------------
 void ctkPopupWidget::enterEvent(QEvent* event)
 {
-  QTimer::singleShot(ENTER_OPENING_DELAY, this, SLOT(updatePopup()));
+  Q_D(ctkPopupWidget);
+  QTimer::singleShot(d->ShowDelay, this, SLOT(updatePopup()));
   this->Superclass::enterEvent(event);
 }
 
@@ -387,19 +414,19 @@ bool ctkPopupWidget::eventFilter(QObject* obj, QEvent* event)
     {
     case QEvent::Move:
       {
-	    if (obj != d->BaseWidget)
-	      {
-	      break;
-	      }
-	    QMoveEvent* moveEvent = dynamic_cast<QMoveEvent*>(event);
-	    QRect newBaseGeometry = d->baseGeometry();
-	    newBaseGeometry.moveTopLeft(d->mapToGlobal(moveEvent->pos()));
-	    QRect desiredGeometry = d->desiredOpenGeometry(newBaseGeometry);
-	    this->move(desiredGeometry.topLeft());
-	    //this->move(this->pos() + moveEvent->pos() - moveEvent->oldPos());
-	    this->update();
-	    break;
-	    }	    
+      if (obj != d->BaseWidget)
+        {
+        break;
+        }
+      QMoveEvent* moveEvent = dynamic_cast<QMoveEvent*>(event);
+      QRect newBaseGeometry = d->baseGeometry();
+      newBaseGeometry.moveTopLeft(d->mapToGlobal(moveEvent->pos()));
+      QRect desiredGeometry = d->desiredOpenGeometry(newBaseGeometry);
+      this->move(desiredGeometry.topLeft());
+      //this->move(this->pos() + moveEvent->pos() - moveEvent->oldPos());
+      this->update();
+      break;
+      }
     case QEvent::Hide:
     case QEvent::Close:
       // if the mouse was in a base widget child popup, then when we leave
@@ -410,12 +437,12 @@ bool ctkPopupWidget::eventFilter(QObject* obj, QEvent* event)
             qobject_cast<QWidget*>(obj)->windowType() == Qt::Popup)
           {
           obj->removeEventFilter(this);
-          QTimer::singleShot(LEAVE_CLOSING_DELAY, this, SLOT(updatePopup()));
+          QTimer::singleShot(d->HideDelay, this, SLOT(updatePopup()));
           }
         break;
         }
       d->temporarilyHiddenOn();
-	    break;
+      break;
     case QEvent::Show:
       if (obj != d->BaseWidget)
         {
@@ -440,7 +467,7 @@ bool ctkPopupWidget::eventFilter(QObject* obj, QEvent* event)
         {
         // Maybe the user moved the mouse on the widget by mistake, don't open
         // the popup instantly...
-        QTimer::singleShot(ENTER_OPENING_DELAY, this, SLOT(updatePopup()));
+        QTimer::singleShot(d->ShowDelay, this, SLOT(updatePopup()));
         }
       else 
         {
@@ -459,7 +486,7 @@ bool ctkPopupWidget::eventFilter(QObject* obj, QEvent* event)
         break;
         }
       // The mouse might have left the area that keeps the popup open
-      QTimer::singleShot(LEAVE_CLOSING_DELAY, this, SLOT(updatePopup()));
+      QTimer::singleShot(d->HideDelay, this, SLOT(updatePopup()));
       if (obj != d->BaseWidget &&
           obj != d->PopupPixmapWidget)
         {

+ 14 - 0
Libs/Widgets/ctkPopupWidget.h

@@ -44,10 +44,18 @@ class CTK_WIDGETS_EXPORT ctkPopupWidget : public ctkBasePopupWidget
   /// enter the widget. True by default
   Q_PROPERTY( bool autoShow READ autoShow WRITE setAutoShow)
 
+  /// Time in ms to wait before opening the popup if autoShow is set.
+  /// 20ms by default
+  Q_PROPERTY( int showDelay READ showDelay WRITE setShowDelay)
+
   /// Control wether the popup automatically closes when the mouse
   /// leaves the widget. True by default
   Q_PROPERTY( bool autoHide READ autoHide WRITE setAutoHide)
 
+  /// Time in ms to wait before closing the popup if autoHide is set.
+  /// 200ms by default
+  Q_PROPERTY( int hideDelay READ hideDelay WRITE setHideDelay)
+
 public:
   typedef ctkBasePopupWidget Superclass;
   explicit ctkPopupWidget(QWidget* parent = 0);
@@ -61,12 +69,18 @@ public:
   /// is above the popup or the base widget.
   void setAutoShow(bool);
 
+  int showDelay()const;
+  void setShowDelay(int delay);
+
   bool autoHide()const;
   /// Don't automatically close the popup when leaving the widget.
   /// Calling setAutoHide automatically updates the state close the popup
   /// if the mouse is not over the popup nor the base widget.
   void setAutoHide(bool autoHide);
 
+  int hideDelay()const;
+  void setHideDelay(int delay);
+
 public slots:
   /// Convenient function that calls setAutoHide(!pin) and opens the popup
   /// if pin is true regardless of the value of \a AutoShow.

+ 2 - 0
Libs/Widgets/ctkPopupWidget_p.h

@@ -56,7 +56,9 @@ public slots:
 protected:
   bool Active;
   bool AutoShow;
+  int  ShowDelay;
   bool AutoHide;
+  int  HideDelay;
 };
 
 #endif