Browse Source

Merge branch 'popup-widget'

* popup-widget:
  Better support for opacity in ctkPopupWidget
  Add Scroll effect to ctkPopupWidget
  Use QPropertyAnimation to control fading in ctkPopupWidget

Conflicts:
	Libs/Widgets/Testing/Cpp/ctkPopupWidgetTest1.cpp
	Libs/Widgets/ctkPopupWidget.cpp
	Libs/Widgets/ctkPopupWidget.h
Julien Finet 14 years ago
parent
commit
d18d448e15

+ 4 - 0
Libs/Widgets/Testing/Cpp/ctkPopupWidgetTest1.cpp

@@ -122,6 +122,10 @@ int ctkPopupWidgetTest1(int argc, char * argv [] )
     popup->setHorizontalDirection(Qt::LeftToRight);
     popup->setAlignment( Qt::AlignBottom | Qt::AlignLeft);
     popup->setEasingCurve(QEasingCurve::OutElastic);
+    QPalette p = popup->palette();
+    p.setColor(QPalette::Window, QColor(255, 0, 0, 128));
+    popup->setPalette(p);
+    popup->setAttribute(Qt::WA_TranslucentBackground);
     }
   popups.clear();
   QWidget* fadePanel = createPanel("Window opacity", popups);

+ 70 - 60
Libs/Widgets/ctkPopupWidget.cpp

@@ -89,6 +89,7 @@ public:
   void init();
   bool fitBaseWidgetSize()const;
   Qt::Alignment pixmapAlignment()const;
+  void setupPopupPixmapWidget();
   
   QRect closedGeometry()const;
   QRect openGeometry()const;
@@ -98,10 +99,11 @@ public:
   QWidget* BaseWidget;
   bool AutoHide;
 
-  int Alpha;
+  double WindowAlpha;
+
   ctkPopupWidget::AnimationEffect Effect;
   QPropertyAnimation* AlphaAnimation;
-  int WindowAlpha;
+  bool                ForcedTranslucent;
   QPropertyAnimation* ScrollAnimation;
   QLabel*             PopupPixmapWidget;
   
@@ -120,10 +122,10 @@ ctkPopupWidgetPrivate::ctkPopupWidgetPrivate(ctkPopupWidget& object)
 {
   this->BaseWidget = 0;
   this->AutoHide = true;
-  this->Alpha = 255;
   this->Effect = ctkPopupWidget::ScrollEffect;
-  this->WindowAlpha = 0;
+  this->WindowAlpha = 1.;
   this->AlphaAnimation = 0;
+  this->ForcedTranslucent = false;
   this->ScrollAnimation = 0;
   this->PopupPixmapWidget = 0;
   // Geometry attributes
@@ -143,13 +145,11 @@ ctkPopupWidgetPrivate::~ctkPopupWidgetPrivate()
 void ctkPopupWidgetPrivate::init()
 {
   Q_Q(ctkPopupWidget);
-  q->setAnimationEffect(this->Effect);
-  this->Alpha = q->style()->styleHint(QStyle::SH_ToolTipLabel_Opacity);
 
   this->AlphaAnimation = new QPropertyAnimation(q, "windowAlpha", q);
   this->AlphaAnimation->setDuration(DEFAULT_FADING_DURATION);
-  this->AlphaAnimation->setStartValue(0);
-  this->AlphaAnimation->setEndValue(this->Alpha);
+  this->AlphaAnimation->setStartValue(0.);
+  this->AlphaAnimation->setEndValue(1.);
   QObject::connect(this->AlphaAnimation, SIGNAL(finished()),
                    q, SLOT(onEffectFinished()));
 
@@ -161,6 +161,7 @@ void ctkPopupWidgetPrivate::init()
   QObject::connect(this->ScrollAnimation, SIGNAL(finished()),
                    this->PopupPixmapWidget, SLOT(hide()));
 
+  q->setAnimationEffect(this->Effect);
   q->setEasingCurve(QEasingCurve::OutCubic);
 }
 
@@ -172,6 +173,30 @@ QPropertyAnimation* ctkPopupWidgetPrivate::currentAnimation()const
 }
 
 // -------------------------------------------------------------------------
+void ctkPopupWidgetPrivate::setupPopupPixmapWidget()
+{
+  Q_Q(ctkPopupWidget);
+  QPixmap pixmap;
+  if (q->testAttribute(Qt::WA_TranslucentBackground))
+    {
+    this->PopupPixmapWidget->setAlignment(this->pixmapAlignment());  
+    // only QImage handle transparency correctly
+    QImage image(this->openGeometry().size(), QImage::Format_ARGB32);
+    image.fill(0);
+    q->render(&image);
+    pixmap = QPixmap::fromImage(image);
+    }
+  else
+    {
+    pixmap = QPixmap::grabWidget(q, QRect(QPoint(0,0), this->openGeometry().size()));
+    }
+  this->PopupPixmapWidget->setPixmap(pixmap);
+  this->PopupPixmapWidget->setAttribute(
+    Qt::WA_TranslucentBackground, q->testAttribute(Qt::WA_TranslucentBackground));
+  this->PopupPixmapWidget->setWindowOpacity(q->windowOpacity());
+}
+
+// -------------------------------------------------------------------------
 Qt::Alignment ctkPopupWidgetPrivate::pixmapAlignment()const
 {
   Q_Q(const ctkPopupWidget);
@@ -374,25 +399,6 @@ void ctkPopupWidget::setBaseWidget(QWidget* widget)
 }
 
 // -------------------------------------------------------------------------
-int ctkPopupWidget::opacity()const
-{
-  Q_D(const ctkPopupWidget);
-  return d->Alpha;
-}
-
-// -------------------------------------------------------------------------
-void ctkPopupWidget::setOpacity(int alpha)
-{
-  Q_D(ctkPopupWidget);
-  d->Alpha = alpha;
-  if (d->AlphaAnimation->state() == QAbstractAnimation::Stopped)
-    {
-    d->WindowAlpha = d->Alpha;
-    }
-  this->update();
-}
-
-// -------------------------------------------------------------------------
 bool ctkPopupWidget::autoHide()const
 {
   Q_D(const ctkPopupWidget);
@@ -420,10 +426,6 @@ void ctkPopupWidget::setAnimationEffect(ctkPopupWidget::AnimationEffect effect)
   Q_D(ctkPopupWidget);
   /// TODO: handle the case where there is an animation running
   d->Effect = effect;
-  bool transparent = (d->Effect == ctkPopupWidget::WindowOpacityFadeEffect);
-  this->setAttribute(Qt::WA_NoSystemBackground, transparent);
-  //this->setAttribute(Qt::WA_OpaquePaintEvent, !transparent);
-  this->setAttribute(Qt::WA_TranslucentBackground, transparent);
 }
 
 // -------------------------------------------------------------------------
@@ -501,6 +503,11 @@ void ctkPopupWidget::setHorizontalDirection(Qt::LayoutDirection horizontalDirect
 void ctkPopupWidget::onEffectFinished()
 {
   Q_D(ctkPopupWidget);
+  if (d->ForcedTranslucent)
+    {
+    d->ForcedTranslucent = false;
+    this->setAttribute(Qt::WA_TranslucentBackground, false);
+    }
   if (qobject_cast<QAbstractAnimation*>(this->sender())->direction() == QAbstractAnimation::Backward)
     {
     this->hide();
@@ -522,7 +529,8 @@ void ctkPopupWidget::paintEvent(QPaintEvent* event)
     int opacity = d->Alpha;
     if (d->AlphaAnimation->state() != QAbstractAnimation::Stopped)
       {
-      opacity = d->WindowAlpha;
+      stop.second.setAlpha(stop.second.alpha() * d->WindowAlpha);
+      stops.push_back(stop);
       }
     QPainter painter(this);
     QBrush brush = this->palette().window();
@@ -551,6 +559,15 @@ void ctkPopupWidget::paintEvent(QPaintEvent* event)
     //semiTransparentColor.setAlpha(d->CurrentAlpha);
     painter.fillRect(this->rect(), brush);
     }
+  else
+    {
+    QColor color = brush.color();
+    color.setAlpha(color.alpha() * d->WindowAlpha);
+    brush.setColor(color);
+    }
+  //QColor semiTransparentColor = this->palette().window().color();
+  //semiTransparentColor.setAlpha(d->CurrentAlpha);
+  painter.fillRect(this->rect(), brush);
   // Let the QFrame draw itself if needed
   this->Superclass::paintEvent(event);
 }
@@ -639,31 +656,21 @@ void ctkPopupWidget::showPopup()
   switch(d->Effect)
     {
     case WindowOpacityFadeEffect:
-      // just in case it wasn't visible, usually it's a no op
+      if (!this->testAttribute(Qt::WA_TranslucentBackground))
+        {
+        d->ForcedTranslucent = true;
+        this->setAttribute(Qt::WA_TranslucentBackground, true);
+        }
       this->show();
       break;
     case ScrollEffect:
       {
-      /*
-      QRect endGeometry = this->geometry();
-      if (!this->testAttribute(Qt::WA_WState_Created) &&
-          !d->fitBaseWidgetSize())
-        {
-        endGeometry.setSize(this->sizeHint());
-        }
-      QRect startGeometry = endGeometry;
-      startGeometry.setHeight(0);
-      d->PopupPixmapWidget->setGeometry(startGeometry);
-      d->ScrollAnimation->setStartValue(startGeometry);
-      d->ScrollAnimation->setEndValue(endGeometry);
-      */
-      d->PopupPixmapWidget->setGeometry(d->closedGeometry());
-      d->ScrollAnimation->setStartValue(d->closedGeometry());
-      d->ScrollAnimation->setEndValue(d->openGeometry());
-      d->PopupPixmapWidget->setAlignment(d->pixmapAlignment());
-      QPixmap pixmap = QPixmap::grabWidget(this, QRect(QPoint(0,0), d->openGeometry().size()));
-      d->PopupPixmapWidget->setPixmap(pixmap);
-      d->PopupPixmapWidget->setWindowOpacity(this->windowOpacity());
+      QRect closedGeometry = d->closedGeometry();
+      QRect openGeometry = d->openGeometry();
+      d->PopupPixmapWidget->setGeometry(closedGeometry);
+      d->ScrollAnimation->setStartValue(closedGeometry);
+      d->ScrollAnimation->setEndValue(openGeometry);
+      d->setupPopupPixmapWidget();
       d->PopupPixmapWidget->show();
       break;
       }
@@ -673,7 +680,6 @@ void ctkPopupWidget::showPopup()
   switch(d->currentAnimation()->state())
     {
     case QAbstractAnimation::Stopped:
-      d->WindowAlpha = 0;
       d->currentAnimation()->start();
       break;
     case QAbstractAnimation::Paused:
@@ -698,12 +704,16 @@ void ctkPopupWidget::hidePopup()
   d->currentAnimation()->setDirection(QAbstractAnimation::Backward);
   switch(d->Effect)
     {
+    case WindowOpacityFadeEffect:
+      if (!this->testAttribute(Qt::WA_TranslucentBackground))
+        {
+        d->ForcedTranslucent = true;
+        this->setAttribute(Qt::WA_TranslucentBackground, true);
+        }
+      break;
     case ScrollEffect:
       {
-      d->PopupPixmapWidget->setAlignment(d->pixmapAlignment());
-      QPixmap pixmap = QPixmap::grabWidget(this, QRect(QPoint(0,0), this->size()));
-      d->PopupPixmapWidget->setPixmap(pixmap);
-      d->PopupPixmapWidget->setWindowOpacity(this->windowOpacity());
+      d->setupPopupPixmapWidget();
       d->PopupPixmapWidget->show();
       this->hide();
       break;
@@ -726,14 +736,14 @@ void ctkPopupWidget::hidePopup()
 }
 
 // --------------------------------------------------------------------------
-int ctkPopupWidget::windowAlpha()const
+double ctkPopupWidget::windowAlpha()const
 {
   Q_D(const ctkPopupWidget);
   return d->WindowAlpha;
 }
 
 // --------------------------------------------------------------------------
-void ctkPopupWidget::setWindowAlpha(int alpha)
+void ctkPopupWidget::setWindowAlpha(double alpha)
 {
   Q_D(ctkPopupWidget);
   d->WindowAlpha = alpha;

+ 3 - 9
Libs/Widgets/ctkPopupWidget.h

@@ -34,9 +34,6 @@ class ctkPopupWidgetPrivate;
 class CTK_WIDGETS_EXPORT ctkPopupWidget : public QFrame
 {
   Q_OBJECT
-  /// Final transparency of the widget (after opacity fading)
-  /// QStyle::SH_ToolTipLabel_Opacity by default.
-  Q_PROPERTY( int opacity READ opacity WRITE setOpacity)
   /// Control wether the popup automatically opens when the mouse
   /// is over the baseWidget and automatically closes when it leaves
   /// the widget.
@@ -72,9 +69,6 @@ public:
   QWidget* baseWidget()const;
   void setBaseWidget(QWidget* baseWidget);
   
-  int opacity()const;
-  void setOpacity(int alpha);
-  
   bool autoHide()const;
   void setAutoHide(bool);
   
@@ -123,12 +117,12 @@ protected slots:
   void updatePopup();
   //void animatePopup();
   void onEffectFinished();
-  void setWindowAlpha(int alpha);
+  void setWindowAlpha(double alpha);
   void setWindowGeometry(QRect geometry);
 
 protected:
   QScopedPointer<ctkPopupWidgetPrivate> d_ptr;
-  Q_PROPERTY(int windowAlpha READ windowAlpha WRITE setWindowAlpha DESIGNABLE false)
+  Q_PROPERTY(double windowAlpha READ windowAlpha WRITE setWindowAlpha DESIGNABLE false)
   Q_PROPERTY(QRect windowGeometry READ windowGeometry WRITE setWindowGeometry DESIGNABLE false)
 
   virtual void paintEvent(QPaintEvent*);
@@ -136,7 +130,7 @@ protected:
   virtual void enterEvent(QEvent* event);
   virtual bool eventFilter(QObject* obj, QEvent* event);
 
-  int windowAlpha()const;
+  double windowAlpha()const;
   QRect windowGeometry()const;
 private:
   Q_DECLARE_PRIVATE(ctkPopupWidget);