Bladeren bron

Merge branch 'ctkCollapsibleButton'

* ctkCollapsibleButton:
  Handle more tricky cases with visibility in ctkCollapsibleButton
Julien Finet 14 jaren geleden
bovenliggende
commit
1de5b95a9b
2 gewijzigde bestanden met toevoegingen van 161 en 52 verwijderingen
  1. 108 42
      Libs/Widgets/Testing/Cpp/ctkCollapsibleButtonTest2.cpp
  2. 53 10
      Libs/Widgets/ctkCollapsibleButton.cpp

+ 108 - 42
Libs/Widgets/Testing/Cpp/ctkCollapsibleButtonTest2.cpp

@@ -32,7 +32,7 @@
 // STD includes
 #include <cstdlib>
 #include <iostream>
-
+#include <QDebug>
 //-----------------------------------------------------------------------------
 int ctkCollapsibleButtonTest2(int argc, char * argv [] )
 {
@@ -40,123 +40,189 @@ int ctkCollapsibleButtonTest2(int argc, char * argv [] )
 
   ctkCollapsibleButton collapsibleButton;
   collapsibleButton.setText("Button");
+  collapsibleButton.setCollapsed(true);
 
   QLabel* label0 = new QLabel("should be invisible", &collapsibleButton);
   QLabel* label1 = new QLabel("should be invisible", &collapsibleButton);
   QLabel* label2 = new QLabel("should be invisible", &collapsibleButton);
-  QLabel* label3 = new QLabel("should be visible", &collapsibleButton);
+  QLabel* label3 = new QLabel("should be invisible", &collapsibleButton);
   QLabel* label4 = new QLabel("should be visible", &collapsibleButton);
   QLabel* label5 = new QLabel("should be visible", &collapsibleButton);
-  
+  QLabel* label6 = new QLabel("should be visible", &collapsibleButton);
+  QLabel* label7 = new QLabel("should be visible", &collapsibleButton);
+  QLabel* label8 = new QLabel("should be visible", &collapsibleButton);
+
+  label0->setVisible(false);
+  label7->setVisible(true);
+
   QVBoxLayout *vbox = new QVBoxLayout;
+  vbox->setContentsMargins(0, 0, 0, 0);
   vbox->addWidget(label0);
   vbox->addWidget(label1);
   vbox->addWidget(label2);
   vbox->addWidget(label3);
   vbox->addWidget(label4);
   vbox->addWidget(label5);
+  vbox->addWidget(label6);
+  vbox->addWidget(label7);
+  vbox->addWidget(label8);
   collapsibleButton.setLayout(vbox);
 
-  label0->setVisible(false);
+  label1->setVisible(false);
 
   collapsibleButton.show();
 
-  label1->setVisible(false);
-  
   if (label0->isVisible() ||
       label1->isVisible() ||
-      !label2->isVisible() ||
-      !label3->isVisible() ||
-      !label4->isVisible() ||
-      !label5->isVisible())
+      label2->isVisible() ||
+      label3->isVisible() ||
+      label4->isVisible() ||
+      label5->isVisible() ||
+      label6->isVisible() ||
+      label7->isVisible() ||
+      label8->isVisible())
     {
-    std::cout << "Wrong child visibility: "
+    std::cout <<  __LINE__ << "Wrong child visibility: "
       << label0->isVisible()  << " "
       << label1->isVisible()  << " "
       << label2->isVisible() << " "
       << label3->isVisible() << " "
       << label4->isVisible() << " "
-      << label5->isVisible() << std::endl;
+      << label5->isVisible() << " "
+      << label6->isVisible() << " "
+      << label7->isVisible() << " "
+      << label8->isVisible() << std::endl;
     return EXIT_FAILURE;
     }
-  
-  collapsibleButton.setCollapsed(true);
-  
+
+  label2->setVisible(false);
+
+  if (label2->isVisible())
+    {
+    std::cout <<  __LINE__ << "Wrong child visibility: "
+      << label2->isVisible() << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  collapsibleButton.setCollapsed(false);
+
   if (label0->isVisible() ||
       label1->isVisible() ||
       label2->isVisible() ||
-      label3->isVisible() ||
-      label4->isVisible() ||
-      label5->isVisible())
+      !label3->isVisible() ||
+      !label4->isVisible() ||
+      !label5->isVisible() ||
+      !label6->isVisible() ||
+      !label7->isVisible() ||
+      !label8->isVisible())
     {
-    std::cout << "Wrong child visibility: "
+    std::cout <<  __LINE__ << "Wrong child visibility: "
       << label0->isVisible()  << " "
       << label1->isVisible()  << " "
       << label2->isVisible() << " "
       << label3->isVisible() << " "
       << label4->isVisible() << " "
-      << label5->isVisible() << std::endl;
+      << label5->isVisible() << " "
+      << label6->isVisible() << " "
+      << label7->isVisible() << " "
+      << label8->isVisible() << std::endl;
     return EXIT_FAILURE;
     }
-  
-  label2->setVisible(false);
-  label3->setVisible(true);
-  label4->setVisible(false);
-  label5->setVisible(false);
-  label5->setVisible(true);
+
+  label3->setVisible(false);
+  label8->setVisible(false);
   
   if (label0->isVisible() ||
       label1->isVisible() ||
       label2->isVisible() ||
       label3->isVisible() ||
-      label4->isVisible() ||
-      label5->isVisible())
+      !label4->isVisible() ||
+      !label5->isVisible() ||
+      !label6->isVisible() ||
+      !label7->isVisible() ||
+      label8->isVisible())
     {
-    std::cout << "Wrong child visibility: "
+    std::cout <<  __LINE__ << "Wrong child visibility: "
       << label0->isVisible()  << " "
       << label1->isVisible()  << " "
       << label2->isVisible() << " "
       << label3->isVisible() << " "
       << label4->isVisible() << " "
-      << label5->isVisible() << std::endl;
+      << label5->isVisible() << " "
+      << label6->isVisible() << " "
+      << label7->isVisible() << " "
+      << label8->isVisible() << std::endl;
     return EXIT_FAILURE;
     }
-  
-  collapsibleButton.setCollapsed(false);
+
+  collapsibleButton.setCollapsed(true);
 
   if (label0->isVisible() ||
       label1->isVisible() ||
       label2->isVisible() ||
-      !label3->isVisible() ||
+      label3->isVisible() ||
       label4->isVisible() ||
-      !label5->isVisible())
+      label5->isVisible() ||
+      label6->isVisible() ||
+      label7->isVisible() ||
+      label8->isVisible())
     {
-    std::cout << "Wrong child visibility: "
+    std::cout <<  __LINE__ << "Wrong child visibility: "
       << label0->isVisible()  << " "
       << label1->isVisible()  << " "
       << label2->isVisible() << " "
       << label3->isVisible() << " "
       << label4->isVisible() << " "
-      << label5->isVisible() << std::endl;
+      << label5->isVisible() << " "
+      << label6->isVisible() << " "
+      << label7->isVisible() << " "
+      << label8->isVisible() << std::endl;
     return EXIT_FAILURE;
     }
 
-  label4->setVisible(true);
+  label4->setVisible(false);
+  label8->setVisible(true);
+
+  if (label4->isVisible() ||
+      label8->isVisible())
+    {
+    std::cout <<  __LINE__ << "Wrong child visibility: "
+      << label4->isVisible() << " "
+      << label8->isVisible() << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  collapsibleButton.setCollapsed(false);
 
   if (label0->isVisible() ||
       label1->isVisible() ||
       label2->isVisible() ||
-      !label3->isVisible() ||
-      !label4->isVisible() ||
-      !label5->isVisible())
+      label3->isVisible() ||
+      label4->isVisible() ||
+      !label5->isVisible() ||
+      !label6->isVisible() ||
+      !label7->isVisible() ||
+      !label8->isVisible())
     {
-    std::cout << "Wrong child visibility: "
+    std::cout << __LINE__ << "Wrong child visibility: "
       << label0->isVisible()  << " "
       << label1->isVisible()  << " "
       << label2->isVisible() << " "
       << label3->isVisible() << " "
       << label4->isVisible() << " "
-      << label5->isVisible() << std::endl;
+      << label5->isVisible() << " "
+      << label6->isVisible() << " "
+      << label7->isVisible() << " "
+      << label8->isVisible() << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  label4->setVisible(true);
+
+  if (!label4->isVisible())
+    {
+    std::cout << "Wrong child visibility: "
+      << label4->isVisible() << std::endl;
     return EXIT_FAILURE;
     }
 

+ 53 - 10
Libs/Widgets/ctkCollapsibleButton.cpp

@@ -88,6 +88,7 @@ void ctkCollapsibleButtonPrivate::init()
   this->CollapsedHeight = 10;
   this->ExclusiveMouseOver = false;  
   this->LookOffWhenChecked = true; // set as a prop ?
+  this->ForcingVisibility = false;
   
   this->MaximumHeight = q->maximumHeight();
 
@@ -109,17 +110,34 @@ void ctkCollapsibleButtonPrivate::init()
 //-----------------------------------------------------------------------------
 void ctkCollapsibleButtonPrivate::setChildVisibility(QWidget* childWidget)
 {
+  Q_Q(ctkCollapsibleButton);
+  // Don't hide children while the widget is not yet created (before show() is
+  // called). If we hide them (but don't set ExplicitShowHide), they would be
+  // shown anyway when they will be created (because ExplicitShowHide is not set).
+  // If we set ExplicitShowHide, then calling setVisible(false) on them would
+  // be a no (because they are already hidden and ExplicitShowHide is set).
+  // So we don't hide/show the children until the widget is created.
+  if (!q->testAttribute(Qt::WA_WState_Created))
+    {
+    return;
+    }
   this->ForcingVisibility = true;
 
-  bool visible= !this->Collapsed &&
-    (childWidget->property("visibilityToParent").isValid() ?
-       childWidget->property("visibilityToParent").toBool() : true);
+  bool visible= !this->Collapsed;
+  // if the widget has been explicity hidden, then hide it.
+  if (childWidget->property("visibilityToParent").isValid()
+      && !childWidget->property("visibilityToParent").toBool())
+    {
+    visible = false;
+    }
 
   childWidget->setVisible(visible);
 
-  // restore the flag as we don't want to make it like it is an explicit visible set.
-  if (!childWidget->property("visibilityToParent").isValid() ||
-      childWidget->property("visibilityToParent").toBool())
+  // setVisible() has set the ExplicitShowHide flag, restore it as we don't want
+  // to make it like it was an explicit visible set because we want
+  // to allow the children to be explicitly hidden by the user.
+  if ((!childWidget->property("visibilityToParent").isValid() ||
+      childWidget->property("visibilityToParent").toBool()))
     {
     childWidget->setAttribute(Qt::WA_WState_ExplicitShowHide, false);
     }
@@ -631,15 +649,24 @@ bool ctkCollapsibleButton::hitButton(const QPoint & _pos)const
 void ctkCollapsibleButton::childEvent(QChildEvent* c)
 {
   Q_D(ctkCollapsibleButton);
+  QObject* child = c->child();
   if (c && c->type() == QEvent::ChildAdded &&
-      c->child() && c->child()->isWidgetType())
+      child && child->isWidgetType())
     {
+    QWidget *childWidget = qobject_cast<QWidget*>(c->child());
+    // Handle the case where the child has already it's visibility set before
+    // being added to the widget
+    if (childWidget->testAttribute(Qt::WA_WState_ExplicitShowHide) &&
+        childWidget->testAttribute(Qt::WA_WState_Hidden))
+      {
+      // if the widget has explicitly set to hidden, then mark it as such
+      childWidget->setProperty("visibilityToParent", false);
+      }
     // We want to catch all the child's Show/Hide events.
-    c->child()->installEventFilter(this);
+    child->installEventFilter(this);
     // If the child is added while ctkCollapsibleButton is collapsed, then we
     // need to hide the child.
-    QWidget *w = static_cast<QWidget*>(c->child());
-    d->setChildVisibility(w);
+    d->setChildVisibility(childWidget);
     }
   this->QAbstractButton::childEvent(c);
 }
@@ -648,6 +675,7 @@ void ctkCollapsibleButton::childEvent(QChildEvent* c)
 void ctkCollapsibleButton::setVisible(bool show)
 {
   Q_D(ctkCollapsibleButton);
+  bool wasCreated = this->testAttribute(Qt::WA_WState_Created);
   // calling QWidget::setVisible() on ctkCollapsibleButton will eventually
   // call QWidget::showChildren() or hideChildren() which will generate
   // ShowToParent/HideToParent events but we want to ignore that case in
@@ -655,6 +683,21 @@ void ctkCollapsibleButton::setVisible(bool show)
   d->ForcingVisibility = true;
   this->QWidget::setVisible(show);
   d->ForcingVisibility = false;
+  // We have been ignoring setChildVisibility() while the collapsible button
+  // is not yet created, now that it is created, ensure that the children
+  // are correctly shown/hidden depending on their explicit visibility and
+  // the collapsed property of the button.
+  if (!wasCreated && this->testAttribute(Qt::WA_WState_Created))
+    {
+    foreach(QObject* child, this->children())
+      {
+      QWidget* childWidget = qobject_cast<QWidget*>(child);
+      if (childWidget)
+        {
+        d->setChildVisibility(childWidget);
+        }
+      }
+    }
 }
 
 //-----------------------------------------------------------------------------