Parcourir la source

Add documentation and tests for ctkPopupWidget

Fix some minor bugs.
Julien Finet il y a 13 ans
Parent
commit
04a16bc1cf

+ 76 - 13
Libs/Widgets/Testing/Cpp/ctkPopupWidgetTest1.cpp

@@ -22,9 +22,11 @@
 #include <QApplication>
 #include <QVBoxLayout>
 #include <QPushButton>
+#include <QSlider>
 #include <QTimer>
 
 // CTK includes
+#include "ctkCallback.h"
 #include "ctkPopupWidget.h"
 
 // STD includes
@@ -32,6 +34,13 @@
 #include <iostream>
 
 //-----------------------------------------------------------------------------
+void changeOpacity(void* callData)
+{
+  ctkPopupWidget* popup = reinterpret_cast<ctkPopupWidget*>(callData);
+  popup->setOpacity(qobject_cast<QSlider*>(popup->baseWidget())->value());
+}
+
+//-----------------------------------------------------------------------------
 int ctkPopupWidgetTest1(int argc, char * argv [] )
 {
   QApplication app(argc, argv);
@@ -49,23 +58,77 @@ int ctkPopupWidgetTest1(int argc, char * argv [] )
   base.show();
 
   QWidget topLevel;
-  QPushButton button1("button");
+  QPushButton focusButton("Focus popup");
+  QPushButton openButton("Open popup");
+  QPushButton toggleButton("Toggle popup");
+  toggleButton.setCheckable(true);
+  QSlider opacitySlider(Qt::Horizontal);
+  opacitySlider.setRange(0, 255);
   QVBoxLayout* vlayout = new QVBoxLayout;
-  vlayout->addWidget(&button1);
+  vlayout->addWidget(&focusButton);
+  vlayout->addWidget(&openButton);
+  vlayout->addWidget(&toggleButton);
+  vlayout->addWidget(&opacitySlider);
   topLevel.setLayout(vlayout);
-  topLevel.show();
 
-  ctkPopupWidget popup2;
-  popup2.setFrameStyle(QFrame::Box);
-  popup2.setLineWidth(2);
-  QPushButton popup2Content("popup2");
-  QVBoxLayout* p2layout = new QVBoxLayout;
-  p2layout->setContentsMargins(0,0,0,0);
-  p2layout->addWidget(&popup2Content);
-  popup2.setLayout(p2layout);
-  popup2.setBaseWidget(&button1);
-  
+  ctkPopupWidget focusPopup;
+  focusPopup.setFrameStyle(QFrame::Box);
+  focusPopup.setLineWidth(1);
+  focusPopup.setAutoHide(true);
+  QPushButton focusPopupContent("button");
+  QVBoxLayout* focusLayout = new QVBoxLayout;
+  focusLayout->addWidget(&focusPopupContent);
+  focusPopup.setLayout(focusLayout);
+  focusPopup.setBaseWidget(&focusButton);
+
+  ctkPopupWidget openPopup;
+  openPopup.setAutoHide(false);
+  QPushButton openPopupContent("Close popup");
+  QVBoxLayout* openLayout = new QVBoxLayout;
+  openLayout->addWidget(&openPopupContent);
+  openPopup.setLayout(openLayout);
+  openPopup.setBaseWidget(&openButton);
+  QObject::connect(&openButton, SIGNAL(clicked()),
+                   &openPopup, SLOT(showPopup()));
+  QObject::connect(&openPopupContent, SIGNAL(clicked()),
+                   &openPopup, SLOT(hidePopup()));
+                   
+  ctkPopupWidget togglePopup;
+  togglePopup.setAutoHide(false);
+  QPushButton togglePopupContent("button");
+  QVBoxLayout* toggleLayout = new QVBoxLayout;
+  toggleLayout->addWidget(&togglePopupContent);
+  togglePopup.setLayout(toggleLayout);
+  togglePopup.setBaseWidget(&toggleButton);
+  QObject::connect(&toggleButton, SIGNAL(toggled(bool)),
+                   &togglePopup, SLOT(showPopup(bool)));
+  togglePopup.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
   
+  ctkPopupWidget sliderPopup;
+  sliderPopup.setAutoHide(false);
+  sliderPopup.setOpacity(255);
+  QPalette palette = sliderPopup.palette();
+  QLinearGradient linearGradient(QPointF(0.f, 0.f), QPointF(0.f, 0.666f));
+  linearGradient.setSpread(QGradient::PadSpread);
+  linearGradient.setCoordinateMode(QGradient::StretchToDeviceMode);
+  linearGradient.setColorAt(0, palette.color(QPalette::Window));
+  linearGradient.setColorAt(1, palette.color(QPalette::Dark));
+  palette.setBrush(QPalette::Window, linearGradient);
+  sliderPopup.setPalette(palette);
+  QWidget sliderPopupContent;
+  QVBoxLayout* sliderLayout = new QVBoxLayout;
+  sliderLayout->addWidget(&sliderPopupContent);
+  sliderPopup.setLayout(sliderLayout);
+  sliderPopup.setBaseWidget(&opacitySlider);
+  ctkCallback callback(changeOpacity);
+  callback.setCallbackData(&sliderPopup);
+  opacitySlider.setValue(255);
+  QObject::connect(&opacitySlider, SIGNAL(valueChanged(int)),
+                   &callback, SLOT(invoke()));
+
+  topLevel.show();
+  sliderPopup.showPopup();
+
   if (argc < 2 || QString(argv[1]) != "-I" )
     {
     QTimer::singleShot(200, &app, SLOT(quit()));

+ 37 - 47
Libs/Widgets/ctkPopupWidget.cpp

@@ -128,7 +128,7 @@ void ctkPopupWidgetPrivate::init()
   //q->setAttribute(Qt::WA_ContentsPropagated);
   this->Alpha = q->style()->styleHint(QStyle::SH_ToolTipLabel_Opacity);
   this->Timer = new QTimer(q);
-  QObject::connect(this->Timer, SIGNAL(timeout()), q, SLOT(update()));
+  QObject::connect(this->Timer, SIGNAL(timeout()), q, SLOT(animatePopup()));
 }
 
 // -------------------------------------------------------------------------
@@ -183,6 +183,8 @@ void ctkPopupWidget::setOpacity(int alpha)
 {
   Q_D(ctkPopupWidget);
   d->Alpha = alpha;
+  d->CurrentAlpha = d->Alpha;
+  this->update();
 }
 
 // -------------------------------------------------------------------------
@@ -201,6 +203,37 @@ void ctkPopupWidget::setAutoHide(bool mode)
 }
 
 // -------------------------------------------------------------------------
+void ctkPopupWidget::animatePopup()
+{
+  Q_D(ctkPopupWidget);
+  this->repaint();
+  if (d->OpenState == ctkPopupWidgetPrivate::Opening &&  d->CurrentAlpha < d->Alpha)
+    {
+    d->CurrentAlpha += d->Alpha * d->Timer->interval() / d->Duration;
+    }
+  else if (d->OpenState ==  ctkPopupWidgetPrivate::Closing &&  d->CurrentAlpha > 0)
+    {
+    d->CurrentAlpha -= d->Alpha * d->Timer->interval() / d->Duration;
+    }
+
+  if (d->CurrentAlpha >= d->Alpha)
+    {
+    d->CurrentAlpha = d->Alpha;
+    d->OpenState = ctkPopupWidgetPrivate::Open;
+    }
+
+  if (d->CurrentAlpha <= 0)
+    {
+    d->CurrentAlpha = 0;
+    d->OpenState = ctkPopupWidgetPrivate::Closed;
+    if (d->Alpha > 0)
+      {
+      this->hide();
+      }
+    }
+}
+
+// -------------------------------------------------------------------------
 void ctkPopupWidget::paintEvent(QPaintEvent* event)
 {
   Q_D(ctkPopupWidget);
@@ -232,28 +265,8 @@ void ctkPopupWidget::paintEvent(QPaintEvent* event)
   //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);
-
-  if (d->OpenState == ctkPopupWidgetPrivate::Opening &&  d->CurrentAlpha < d->Alpha)
-    {
-    d->CurrentAlpha += d->Alpha * d->Timer->interval() / d->Duration;
-    }
-  else if (d->OpenState ==  ctkPopupWidgetPrivate::Closing &&  d->CurrentAlpha > 0)
-    {
-    d->CurrentAlpha -= d->Alpha * d->Timer->interval() / d->Duration;
-    }
-  if (d->CurrentAlpha >= d->Alpha)
-    {
-    d->CurrentAlpha = d->Alpha;
-    d->OpenState = ctkPopupWidgetPrivate::Open;
-    }
-    
-  if (d->CurrentAlpha <= 0)
-    {
-    d->CurrentAlpha = 0;
-    this->hide();
-    d->OpenState = ctkPopupWidgetPrivate::Closed;
-    }
 }
 
 // --------------------------------------------------------------------------
@@ -304,34 +317,11 @@ void ctkPopupWidget::updatePopup()
     this->hidePopup();
     }
 }
-/*
-// --------------------------------------------------------------------------
-void ctkPopupWidget::hidePopup()
-{
-  Q_D(ctkPopupWidget);
-  if (this->underMouse() || d->BaseWidget->underMouse())
-    {
-    return;
-    }
-  d->hidePopup();
-}
 
 // --------------------------------------------------------------------------
 void ctkPopupWidget::showPopup()
 {
   Q_D(ctkPopupWidget);
-  if ((!this->underMouse() && !d->BaseWidget->underMouse()) ||
-      (this->isVisible() && d->CurrentAlpha == d->Alpha))
-    {
-    return;
-    }
-  d->showPopup();
-}
-*/
-// --------------------------------------------------------------------------
-void ctkPopupWidget::showPopup()
-{
-  Q_D(ctkPopupWidget);
   if (this->isVisible() && d->OpenState == ctkPopupWidgetPrivate::Open)
     {
     return;
@@ -342,9 +332,9 @@ void ctkPopupWidget::showPopup()
     QPoint pos = d->BaseWidget->parentWidget() ? d->BaseWidget->parentWidget()->mapToGlobal(bottomLeft) : bottomLeft;
     this->move(pos);
     /// TODO: need some refinement
-    if ((this->sizePolicy().horizontalPolicy() | QSizePolicy::GrowFlag &&
+    if ((this->sizePolicy().horizontalPolicy() & QSizePolicy::GrowFlag &&
          this->width() < d->BaseWidget->width()) ||
-        (this->sizePolicy().horizontalPolicy() | QSizePolicy::ShrinkFlag &&
+        (this->sizePolicy().horizontalPolicy() & QSizePolicy::ShrinkFlag &&
              this->width() > d->BaseWidget->width()))
       {
       // Fit to BaseWidget size

+ 28 - 0
Libs/Widgets/ctkPopupWidget.h

@@ -36,6 +36,9 @@ class CTK_WIDGETS_EXPORT ctkPopupWidget : public QFrame
   /// 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.
   Q_PROPERTY( bool autoHide READ autoHide WRITE setAutoHide)
 
 public:
@@ -43,6 +46,9 @@ public:
   explicit ctkPopupWidget(QWidget* parent = 0);
   virtual ~ctkPopupWidget();
 
+  /// Widget the popup is attached to. It opens right under \a baseWidget
+  /// and if the ctkPopupWidget sizepolicy contains the growFlag/shrinkFlag,
+  /// it tries to resize itself to fit the same width of \a baseWidget.
   QWidget* baseWidget()const;
   void setBaseWidget(QWidget* baseWidget);
   
@@ -53,9 +59,19 @@ public:
   void setAutoHide(bool);
 
 public slots:
+  /// Hide the popup if open or opening. It takes around 300ms 
+  /// for the fading effect to hide the popup.
   void hidePopup();
+  /// Open the popup if closed or closing. It takes around 300ms 
+  /// for the fading effect to open the popup.
   void showPopup();
+  /// Show/hide the popup. It can be conveniently linked to a QPushButton
+  /// signal.
+  inline void showPopup(bool show);
+
+protected slots:
   void updatePopup();
+  void animatePopup();
 
 protected:
   QScopedPointer<ctkPopupWidgetPrivate> d_ptr;
@@ -70,4 +86,16 @@ private:
   Q_DISABLE_COPY(ctkPopupWidget);
 };
 
+void ctkPopupWidget::showPopup(bool show)
+{
+  if (show)
+    {
+    this->showPopup();
+    }
+  else
+    {
+    this->hidePopup();
+    }
+}
+
 #endif