Browse Source

The parent of a popup widget is actually the base widget

Doing so has multiple advantages:
 - it automatically deletes the popup when the parent is deleted.
 - when checking where the mouse is over, it is good to know have
the popup widget being the child of the basewidget. isAncestorOf would
then return the correct value.
Julien Finet 14 years ago
parent
commit
1711242234

+ 5 - 10
Libs/Widgets/Testing/Cpp/ctkPopupWidgetTest1.cpp

@@ -71,7 +71,7 @@ QWidget* createPanel(const QString& title, QList<ctkPopupWidget*>& popups)
   vlayout->addWidget(pinButton);
   vlayout->addWidget(pinButton);
   topLevel->setLayout(vlayout);
   topLevel->setLayout(vlayout);
 
 
-  ctkPopupWidget* focusPopup = new ctkPopupWidget;
+  ctkPopupWidget* focusPopup = new ctkPopupWidget(focusComboBox);
   focusPopup->setObjectName("focusPopup");
   focusPopup->setObjectName("focusPopup");
   focusPopup->setAutoShow(true);
   focusPopup->setAutoShow(true);
   focusPopup->setAutoHide(true);
   focusPopup->setAutoHide(true);
@@ -92,7 +92,6 @@ QWidget* createPanel(const QString& title, QList<ctkPopupWidget*>& popups)
   focusLayout->addWidget(focusPopupContent);
   focusLayout->addWidget(focusPopupContent);
   focusLayout->addWidget(popupToolButton);
   focusLayout->addWidget(popupToolButton);
   focusPopup->setLayout(focusLayout);
   focusPopup->setLayout(focusLayout);
-  focusPopup->setBaseWidget(focusComboBox);
   focusLayout->setContentsMargins(0,0,0,0);
   focusLayout->setContentsMargins(0,0,0,0);
 
 
   QPalette palette = focusPopup->palette();
   QPalette palette = focusPopup->palette();
@@ -104,7 +103,7 @@ QWidget* createPanel(const QString& title, QList<ctkPopupWidget*>& popups)
   palette.setBrush(QPalette::Window, linearGradient);
   palette.setBrush(QPalette::Window, linearGradient);
   focusPopup->setPalette(palette);
   focusPopup->setPalette(palette);
 
 
-  ctkPopupWidget* openPopup = new ctkPopupWidget;
+  ctkPopupWidget* openPopup = new ctkPopupWidget(openButton);
   openPopup->setObjectName("openPopup");
   openPopup->setObjectName("openPopup");
   openPopup->setFrameStyle(QFrame::Box);
   openPopup->setFrameStyle(QFrame::Box);
   openPopup->setLineWidth(1);
   openPopup->setLineWidth(1);
@@ -116,13 +115,12 @@ QWidget* createPanel(const QString& title, QList<ctkPopupWidget*>& popups)
   QVBoxLayout* openLayout = new QVBoxLayout;
   QVBoxLayout* openLayout = new QVBoxLayout;
   openLayout->addWidget(openPopupContent);
   openLayout->addWidget(openPopupContent);
   openPopup->setLayout(openLayout);
   openPopup->setLayout(openLayout);
-  openPopup->setBaseWidget(openButton);
   QObject::connect(openButton, SIGNAL(clicked()),
   QObject::connect(openButton, SIGNAL(clicked()),
                    openPopup, SLOT(showPopup()));
                    openPopup, SLOT(showPopup()));
   QObject::connect(openPopupContent, SIGNAL(clicked()),
   QObject::connect(openPopupContent, SIGNAL(clicked()),
                    openPopup, SLOT(hidePopup()));
                    openPopup, SLOT(hidePopup()));
                    
                    
-  ctkPopupWidget* togglePopup = new ctkPopupWidget;
+  ctkPopupWidget* togglePopup = new ctkPopupWidget(toggleButton);
   togglePopup->setObjectName("togglePopup");
   togglePopup->setObjectName("togglePopup");
   togglePopup->setAutoShow(false);
   togglePopup->setAutoShow(false);
   togglePopup->setAutoHide(false);
   togglePopup->setAutoHide(false);
@@ -132,14 +130,12 @@ QWidget* createPanel(const QString& title, QList<ctkPopupWidget*>& popups)
   QVBoxLayout* toggleLayout = new QVBoxLayout;
   QVBoxLayout* toggleLayout = new QVBoxLayout;
   toggleLayout->addWidget(togglePopupContent);
   toggleLayout->addWidget(togglePopupContent);
   togglePopup->setLayout(toggleLayout);
   togglePopup->setLayout(toggleLayout);
-  togglePopup->setBaseWidget(toggleButton);
   QObject::connect(toggleButton, SIGNAL(toggled(bool)),
   QObject::connect(toggleButton, SIGNAL(toggled(bool)),
                    togglePopup, SLOT(showPopup(bool)));
                    togglePopup, SLOT(showPopup(bool)));
   togglePopup->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
   togglePopup->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
   
   
-  ctkPopupWidget* pinPopup = new ctkPopupWidget;
+  ctkPopupWidget* pinPopup = new ctkPopupWidget(pinButton);
   pinPopup->setObjectName("pinPopup");
   pinPopup->setObjectName("pinPopup");
-  pinPopup->setBaseWidget(pinButton);
   QPushButton* pinPopupContent = new QPushButton("pin button");
   QPushButton* pinPopupContent = new QPushButton("pin button");
   pinPopupContent->setCheckable(true);
   pinPopupContent->setCheckable(true);
   QObject::connect(pinPopupContent, SIGNAL(toggled(bool)),
   QObject::connect(pinPopupContent, SIGNAL(toggled(bool)),
@@ -164,13 +160,12 @@ int ctkPopupWidgetTest1(int argc, char * argv [] )
 
 
   QPushButton base("Top level push button");
   QPushButton base("Top level push button");
   
   
-  ctkPopupWidget popup;
+  ctkPopupWidget popup(&base);
   QPushButton popupContent("popup");
   QPushButton popupContent("popup");
   QVBoxLayout* layout = new QVBoxLayout;
   QVBoxLayout* layout = new QVBoxLayout;
   layout->addWidget(&popupContent);
   layout->addWidget(&popupContent);
   popup.setLayout(layout);
   popup.setLayout(layout);
 
 
-  popup.setBaseWidget(&base);
   popup.setAlignment(Qt::AlignVCenter | Qt::AlignRight);
   popup.setAlignment(Qt::AlignVCenter | Qt::AlignRight);
   popup.setHorizontalDirection(Qt::RightToLeft);
   popup.setHorizontalDirection(Qt::RightToLeft);
   popup.setOrientation(Qt::Horizontal);
   popup.setOrientation(Qt::Horizontal);

+ 27 - 10
Libs/Widgets/ctkBasePopupWidget.cpp

@@ -98,7 +98,6 @@ ctkBasePopupWidgetPrivate::ctkBasePopupWidgetPrivate(ctkBasePopupWidget& object)
 // -------------------------------------------------------------------------
 // -------------------------------------------------------------------------
 ctkBasePopupWidgetPrivate::~ctkBasePopupWidgetPrivate()
 ctkBasePopupWidgetPrivate::~ctkBasePopupWidgetPrivate()
 {
 {
-  delete this->PopupPixmapWidget;
 }
 }
 
 
 // -------------------------------------------------------------------------
 // -------------------------------------------------------------------------
@@ -117,7 +116,7 @@ void ctkBasePopupWidgetPrivate::init()
   QObject::connect(this->AlphaAnimation, SIGNAL(finished()),
   QObject::connect(this->AlphaAnimation, SIGNAL(finished()),
                    q, SLOT(onEffectFinished()));
                    q, SLOT(onEffectFinished()));
 
 
-  this->PopupPixmapWidget = new QLabel(0, Qt::ToolTip | Qt::FramelessWindowHint);
+  this->PopupPixmapWidget = new QLabel(q, Qt::ToolTip | Qt::FramelessWindowHint);
 
 
   this->ScrollAnimation = new QPropertyAnimation(q, "effectGeometry", q);
   this->ScrollAnimation = new QPropertyAnimation(q, "effectGeometry", q);
   this->ScrollAnimation->setDuration(DEFAULT_FADING_DURATION);
   this->ScrollAnimation->setDuration(DEFAULT_FADING_DURATION);
@@ -128,6 +127,7 @@ void ctkBasePopupWidgetPrivate::init()
 
 
   q->setAnimationEffect(this->Effect);
   q->setAnimationEffect(this->Effect);
   q->setEasingCurve(QEasingCurve::OutCubic);
   q->setEasingCurve(QEasingCurve::OutCubic);
+  q->setBaseWidget(q->parentWidget());
 }
 }
 
 
 // -------------------------------------------------------------------------
 // -------------------------------------------------------------------------
@@ -215,7 +215,9 @@ bool ctkBasePopupWidgetPrivate::isAncestorOf(const QWidget* ancestor, const QWid
   while (child)
   while (child)
     {
     {
     if (child == ancestor)
     if (child == ancestor)
-        return true;
+      {
+      return true;
+      }
     child = child->parentWidget();
     child = child->parentWidget();
     }
     }
   return false;
   return false;
@@ -428,7 +430,7 @@ void ctkBasePopupWidgetPrivate::hideAll()
   // It is possible to have the popup widget not being a popup but inside
   // It is possible to have the popup widget not being a popup but inside
   // a layout: maybe the popup has been pin-down in a way that it gets parented
   // a layout: maybe the popup has been pin-down in a way that it gets parented
   // In that case, there is no reason to hide the popup.
   // In that case, there is no reason to hide the popup.
-  if (q->parentWidget() != 0)
+  if (!(q->windowFlags() & Qt::ToolTip))
     {
     {
     return;
     return;
     }
     }
@@ -458,7 +460,8 @@ void ctkBasePopupWidgetPrivate::hideAll()
 // Qt::Toolip is preferred to Qt::Popup as it would close itself at the first
 // Qt::Toolip is preferred to Qt::Popup as it would close itself at the first
 // click outside the widget (typically a click in the BaseWidget)
 // click outside the widget (typically a click in the BaseWidget)
 ctkBasePopupWidget::ctkBasePopupWidget(QWidget* parentWidget)
 ctkBasePopupWidget::ctkBasePopupWidget(QWidget* parentWidget)
-  : Superclass(QApplication::desktop()->screen(QApplication::desktop()->screenNumber(parentWidget)),
+  //: Superclass(QApplication::desktop()->screen(QApplication::desktop()->screenNumber(parentWidget)),
+  : Superclass(parentWidget,
                Qt::ToolTip | Qt::FramelessWindowHint)
                Qt::ToolTip | Qt::FramelessWindowHint)
   , d_ptr(new ctkBasePopupWidgetPrivate(*this))
   , d_ptr(new ctkBasePopupWidgetPrivate(*this))
 {
 {
@@ -468,7 +471,8 @@ ctkBasePopupWidget::ctkBasePopupWidget(QWidget* parentWidget)
 
 
 // -------------------------------------------------------------------------
 // -------------------------------------------------------------------------
 ctkBasePopupWidget::ctkBasePopupWidget(ctkBasePopupWidgetPrivate* pimpl, QWidget* parentWidget)
 ctkBasePopupWidget::ctkBasePopupWidget(ctkBasePopupWidgetPrivate* pimpl, QWidget* parentWidget)
-  : Superclass(QApplication::desktop()->screen(QApplication::desktop()->screenNumber(parentWidget)),
+  //: //Superclass(QApplication::desktop()->screen(QApplication::desktop()->screenNumber(parentWidget)),
+  : Superclass(parentWidget,
                Qt::ToolTip | Qt::FramelessWindowHint)
                Qt::ToolTip | Qt::FramelessWindowHint)
   , d_ptr(pimpl)
   , d_ptr(pimpl)
 {
 {
@@ -493,14 +497,14 @@ void ctkBasePopupWidget::setBaseWidget(QWidget* widget)
   Q_D(ctkBasePopupWidget);
   Q_D(ctkBasePopupWidget);
   if (d->BaseWidget)
   if (d->BaseWidget)
     {
     {
-    disconnect(d->BaseWidget, SIGNAL(destroyed(QObject*)),
-               this, SLOT(onBaseWidgetDestroyed()));
+    //disconnect(d->BaseWidget, SIGNAL(destroyed(QObject*)),
+    //           this, SLOT(onBaseWidgetDestroyed()));
     }
     }
   d->BaseWidget = widget;
   d->BaseWidget = widget;
   if (d->BaseWidget)
   if (d->BaseWidget)
     {
     {
-    connect(d->BaseWidget, SIGNAL(destroyed(QObject*)),
-            this, SLOT(onBaseWidgetDestroyed()));
+    //connect(d->BaseWidget, SIGNAL(destroyed(QObject*)),
+    //        this, SLOT(onBaseWidgetDestroyed()));
     }
     }
 }
 }
 
 
@@ -622,6 +626,19 @@ void ctkBasePopupWidget::onEffectFinished()
 }
 }
 
 
 // -------------------------------------------------------------------------
 // -------------------------------------------------------------------------
+bool ctkBasePopupWidget::event(QEvent* event)
+{
+  Q_D(ctkBasePopupWidget);
+  switch(event->type())
+    {
+    case QEvent::ParentChange:
+      this->setBaseWidget(this->parentWidget());
+      break;
+    }
+  return this->Superclass::event(event);
+}
+
+// -------------------------------------------------------------------------
 void ctkBasePopupWidget::paintEvent(QPaintEvent* event)
 void ctkBasePopupWidget::paintEvent(QPaintEvent* event)
 {
 {
   Q_D(ctkBasePopupWidget);
   Q_D(ctkBasePopupWidget);

+ 11 - 1
Libs/Widgets/ctkBasePopupWidget.h

@@ -66,14 +66,21 @@ class CTK_WIDGETS_EXPORT ctkBasePopupWidget : public QFrame
 
 
 public:
 public:
   typedef QFrame Superclass;
   typedef QFrame Superclass;
+  /// Although a popup widget is a top-level widget, if a parent is
+  /// passed the popup widget will be deleted when that parent is
+  /// destroyed (as with any other QObject).
+  /// ctkBasePopupWidget is a top-level widget (Qt::ToolTip), so
+  /// even if a parent is passed, the popup will display outside the possible
+  /// parent layout.
+  /// \sa baseWidget().
   explicit ctkBasePopupWidget(QWidget* parent = 0);
   explicit ctkBasePopupWidget(QWidget* parent = 0);
   virtual ~ctkBasePopupWidget();
   virtual ~ctkBasePopupWidget();
 
 
   /// Widget the popup is attached to. It opens right under \a baseWidget
   /// Widget the popup is attached to. It opens right under \a baseWidget
   /// and if the ctkBasePopupWidget sizepolicy contains the growFlag/shrinkFlag,
   /// and if the ctkBasePopupWidget sizepolicy contains the growFlag/shrinkFlag,
   /// it tries to resize itself to fit the same width of \a baseWidget.
   /// it tries to resize itself to fit the same width of \a baseWidget.
+  /// By default, baseWidget is the parent widget.
   QWidget* baseWidget()const;
   QWidget* baseWidget()const;
-  virtual void setBaseWidget(QWidget* baseWidget);
 
 
   enum AnimationEffect
   enum AnimationEffect
   {
   {
@@ -128,6 +135,9 @@ protected:
   double effectAlpha()const;
   double effectAlpha()const;
   QRect effectGeometry()const;
   QRect effectGeometry()const;
 
 
+  virtual void setBaseWidget(QWidget* baseWidget);
+
+  virtual bool event(QEvent* event);
   virtual void paintEvent(QPaintEvent*);
   virtual void paintEvent(QPaintEvent*);
 
 
 protected slots:
 protected slots:

+ 11 - 4
Libs/Widgets/ctkPopupWidget.cpp

@@ -60,8 +60,8 @@ void ctkPopupWidgetPrivate::init()
 {
 {
   Q_Q(ctkPopupWidget);
   Q_Q(ctkPopupWidget);
   this->setParent(q);
   this->setParent(q);
-  this->Superclass::init();
   q->setActive(true);
   q->setActive(true);
+  this->Superclass::init();
 }
 }
 
 
 // -------------------------------------------------------------------------
 // -------------------------------------------------------------------------
@@ -279,7 +279,10 @@ void ctkPopupWidget::setActive(bool active)
       {
       {
       d->BaseWidget->installEventFilter(this);
       d->BaseWidget->installEventFilter(this);
       }
       }
-    d->PopupPixmapWidget->installEventFilter(this);
+    if (d->PopupPixmapWidget)
+      {
+      d->PopupPixmapWidget->installEventFilter(this);
+      }
     qApp->installEventFilter(d);
     qApp->installEventFilter(d);
     }
     }
   else // not active
   else // not active
@@ -288,7 +291,10 @@ void ctkPopupWidget::setActive(bool active)
       {
       {
       d->BaseWidget->removeEventFilter(this);
       d->BaseWidget->removeEventFilter(this);
       }
       }
-    d->PopupPixmapWidget->removeEventFilter(this);
+    if (d->PopupPixmapWidget)
+      {
+      d->PopupPixmapWidget->removeEventFilter(this);
+      }
     qApp->removeEventFilter(d);
     qApp->removeEventFilter(d);
     }
     }
 }
 }
@@ -359,7 +365,8 @@ void ctkPopupWidget::onEffectFinished()
 // --------------------------------------------------------------------------
 // --------------------------------------------------------------------------
 void ctkPopupWidget::leaveEvent(QEvent* event)
 void ctkPopupWidget::leaveEvent(QEvent* event)
 {
 {
-  QTimer::singleShot(LEAVE_CLOSING_DELAY, this, SLOT(updatePopup()));
+  //QTimer::singleShot(LEAVE_CLOSING_DELAY, this, SLOT(updatePopup()));
+  this->updatePopup();
   this->Superclass::leaveEvent(event);
   this->Superclass::leaveEvent(event);
 }
 }
 
 

+ 5 - 5
Libs/Widgets/ctkPopupWidget.h

@@ -53,11 +53,6 @@ public:
   explicit ctkPopupWidget(QWidget* parent = 0);
   explicit ctkPopupWidget(QWidget* parent = 0);
   virtual ~ctkPopupWidget();
   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.
-  virtual void setBaseWidget(QWidget* baseWidget);
-
   bool isActive()const;
   bool isActive()const;
   void setActive(bool);
   void setActive(bool);
 
 
@@ -87,6 +82,11 @@ protected:
   virtual void enterEvent(QEvent* event);
   virtual void enterEvent(QEvent* event);
   virtual bool eventFilter(QObject* obj, QEvent* event);
   virtual bool eventFilter(QObject* obj, QEvent* event);
 
 
+  /// 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.
+  virtual void setBaseWidget(QWidget* baseWidget);
+
 protected slots:
 protected slots:
   void updatePopup();
   void updatePopup();
   virtual void onEffectFinished();
   virtual void onEffectFinished();

+ 1 - 4
Libs/Widgets/ctkSliderWidget.cpp

@@ -71,8 +71,6 @@ ctkSliderWidgetPrivate::ctkSliderWidgetPrivate(ctkSliderWidget& object)
 // --------------------------------------------------------------------------
 // --------------------------------------------------------------------------
 ctkSliderWidgetPrivate::~ctkSliderWidgetPrivate()
 ctkSliderWidgetPrivate::~ctkSliderWidgetPrivate()
 {
 {
-  delete this->SliderPopup;
-  this->SliderPopup = 0;
 }
 }
 
 
 // --------------------------------------------------------------------------
 // --------------------------------------------------------------------------
@@ -525,7 +523,7 @@ void ctkSliderWidget::setPopupSlider(bool popup)
     }
     }
   if (popup)
   if (popup)
     {
     {
-    d->SliderPopup = new ctkPopupWidget(0);
+    d->SliderPopup = new ctkPopupWidget(this);
 
 
     QHBoxLayout* layout = new QHBoxLayout(d->SliderPopup);
     QHBoxLayout* layout = new QHBoxLayout(d->SliderPopup);
     layout->setContentsMargins(0,0,0,0);
     layout->setContentsMargins(0,0,0,0);
@@ -536,7 +534,6 @@ void ctkSliderWidget::setPopupSlider(bool popup)
     d->SliderPopup->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
     d->SliderPopup->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
     d->SliderPopup->setOrientation(Qt::Horizontal);
     d->SliderPopup->setOrientation(Qt::Horizontal);
     d->SliderPopup->setHorizontalDirection(Qt::RightToLeft);
     d->SliderPopup->setHorizontalDirection(Qt::RightToLeft);
-    d->SliderPopup->setBaseWidget(d->SpinBox);
     }
     }
   else
   else
     {
     {