Explorar el Código

Merge branch 'popup-base-widget-is-parent'

* popup-base-widget-is-parent:
  Reopen the popup when closing, AutoHide and the mouse back
  The parent of a popup widget is actually the base widget
Julien Finet hace 14 años
padre
commit
19ce60782f

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

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

+ 27 - 10
Libs/Widgets/ctkBasePopupWidget.cpp

@@ -98,7 +98,6 @@ ctkBasePopupWidgetPrivate::ctkBasePopupWidgetPrivate(ctkBasePopupWidget& object)
 // -------------------------------------------------------------------------
 ctkBasePopupWidgetPrivate::~ctkBasePopupWidgetPrivate()
 {
-  delete this->PopupPixmapWidget;
 }
 
 // -------------------------------------------------------------------------
@@ -117,7 +116,7 @@ void ctkBasePopupWidgetPrivate::init()
   QObject::connect(this->AlphaAnimation, SIGNAL(finished()),
                    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->setDuration(DEFAULT_FADING_DURATION);
@@ -128,6 +127,7 @@ void ctkBasePopupWidgetPrivate::init()
 
   q->setAnimationEffect(this->Effect);
   q->setEasingCurve(QEasingCurve::OutCubic);
+  q->setBaseWidget(q->parentWidget());
 }
 
 // -------------------------------------------------------------------------
@@ -215,7 +215,9 @@ bool ctkBasePopupWidgetPrivate::isAncestorOf(const QWidget* ancestor, const QWid
   while (child)
     {
     if (child == ancestor)
-        return true;
+      {
+      return true;
+      }
     child = child->parentWidget();
     }
   return false;
@@ -428,7 +430,7 @@ void ctkBasePopupWidgetPrivate::hideAll()
   // 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
   // In that case, there is no reason to hide the popup.
-  if (q->parentWidget() != 0)
+  if (!(q->windowFlags() & Qt::ToolTip))
     {
     return;
     }
@@ -458,7 +460,8 @@ void ctkBasePopupWidgetPrivate::hideAll()
 // 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)
 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)
   , d_ptr(new ctkBasePopupWidgetPrivate(*this))
 {
@@ -468,7 +471,8 @@ ctkBasePopupWidget::ctkBasePopupWidget(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)
   , d_ptr(pimpl)
 {
@@ -493,14 +497,14 @@ void ctkBasePopupWidget::setBaseWidget(QWidget* widget)
   Q_D(ctkBasePopupWidget);
   if (d->BaseWidget)
     {
-    disconnect(d->BaseWidget, SIGNAL(destroyed(QObject*)),
-               this, SLOT(onBaseWidgetDestroyed()));
+    //disconnect(d->BaseWidget, SIGNAL(destroyed(QObject*)),
+    //           this, SLOT(onBaseWidgetDestroyed()));
     }
   d->BaseWidget = widget;
   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)
 {
   Q_D(ctkBasePopupWidget);

+ 11 - 1
Libs/Widgets/ctkBasePopupWidget.h

@@ -66,14 +66,21 @@ class CTK_WIDGETS_EXPORT ctkBasePopupWidget : public QFrame
 
 public:
   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);
   virtual ~ctkBasePopupWidget();
 
   /// Widget the popup is attached to. It opens right under \a baseWidget
   /// and if the ctkBasePopupWidget sizepolicy contains the growFlag/shrinkFlag,
   /// it tries to resize itself to fit the same width of \a baseWidget.
+  /// By default, baseWidget is the parent widget.
   QWidget* baseWidget()const;
-  virtual void setBaseWidget(QWidget* baseWidget);
 
   enum AnimationEffect
   {
@@ -128,6 +135,9 @@ protected:
   double effectAlpha()const;
   QRect effectGeometry()const;
 
+  virtual void setBaseWidget(QWidget* baseWidget);
+
+  virtual bool event(QEvent* event);
   virtual void paintEvent(QPaintEvent*);
 
 protected slots:

+ 18 - 5
Libs/Widgets/ctkPopupWidget.cpp

@@ -60,8 +60,8 @@ void ctkPopupWidgetPrivate::init()
 {
   Q_Q(ctkPopupWidget);
   this->setParent(q);
-  this->Superclass::init();
   q->setActive(true);
+  this->Superclass::init();
 }
 
 // -------------------------------------------------------------------------
@@ -279,7 +279,10 @@ void ctkPopupWidget::setActive(bool active)
       {
       d->BaseWidget->installEventFilter(this);
       }
-    d->PopupPixmapWidget->installEventFilter(this);
+    if (d->PopupPixmapWidget)
+      {
+      d->PopupPixmapWidget->installEventFilter(this);
+      }
     qApp->installEventFilter(d);
     }
   else // not active
@@ -288,7 +291,10 @@ void ctkPopupWidget::setActive(bool active)
       {
       d->BaseWidget->removeEventFilter(this);
       }
-    d->PopupPixmapWidget->removeEventFilter(this);
+    if (d->PopupPixmapWidget)
+      {
+      d->PopupPixmapWidget->removeEventFilter(this);
+      }
     qApp->removeEventFilter(d);
     }
 }
@@ -359,7 +365,8 @@ void ctkPopupWidget::onEffectFinished()
 // --------------------------------------------------------------------------
 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);
 }
 
@@ -472,7 +479,13 @@ void ctkPopupWidget::updatePopup()
 
   // Querying mouseOver can be slow, don't do it if not needed.
   QWidget* mouseOver = (d->AutoShow || d->AutoHide) ? d->mouseOver() : 0;
-  if (d->AutoShow && mouseOver &&
+  if ((d->AutoShow ||
+     // Even if there is no AutoShow, we might still want to reopen the popup
+     // when closing it inadvertently
+       d->AutoHide && d->isClosing()) &&
+     // to be automatically open, the mouse has to be over a child widget
+      mouseOver &&
+     // disable opening the popup when the popup is disabled
       (!d->BaseWidget || d->BaseWidget->isEnabled()))
     {
     this->showPopup();

+ 5 - 5
Libs/Widgets/ctkPopupWidget.h

@@ -53,11 +53,6 @@ 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.
-  virtual void setBaseWidget(QWidget* baseWidget);
-
   bool isActive()const;
   void setActive(bool);
 
@@ -87,6 +82,11 @@ protected:
   virtual void enterEvent(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:
   void updatePopup();
   virtual void onEffectFinished();

+ 1 - 4
Libs/Widgets/ctkSliderWidget.cpp

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