Переглянути джерело

Merge branch 'cim-CheckablePushButton_not_user_checkable_checkbox' of https://github.com/cim-unito/CTK into ctkCheckablePushButton-checkState

Julien Finet 13 роки тому
батько
коміт
5675fbe741

+ 31 - 0
Libs/Widgets/Testing/Cpp/ctkCheckablePushButtonTest1.cpp

@@ -45,6 +45,12 @@ int ctkCheckablePushButtonTest1(int argc, char * argv [] )
   ctkCheckablePushButton button5(QObject::tr("Button5"));
   ctkCheckablePushButton button6(QObject::tr("Button6"));
   ctkCheckablePushButton button7(QObject::tr("Checkable PushButton"));
+  ctkCheckablePushButton button8(QObject::tr("Connected, Not User Checkable"));
+  ctkCheckablePushButton button9(QObject::tr("Connected, Not User Checkable"));
+  ctkCheckablePushButton button10(QObject::tr("Not Connected, User Checkable"));
+  ctkCheckablePushButton button11(QObject::tr("Not Connected, User Checkable"));
+  ctkCheckablePushButton button12(QObject::tr("Checkbox Not User Checkable\nButton Checkable"));
+  ctkCheckablePushButton button13(QObject::tr("Checkbox and Button User Checkable"));
 
   QVBoxLayout *layout= new QVBoxLayout;
   layout->addWidget(&button1);
@@ -54,6 +60,12 @@ int ctkCheckablePushButtonTest1(int argc, char * argv [] )
   layout->addWidget(&button5);
   layout->addWidget(&button6);
   layout->addWidget(&button7);
+  layout->addWidget(&button8);
+  layout->addWidget(&button9);
+  layout->addWidget(&button10);
+  layout->addWidget(&button11);
+  layout->addWidget(&button12);
+  layout->addWidget(&button13);
   topLevel.setLayout(layout);
 
   topLevel.show();
@@ -89,6 +101,25 @@ int ctkCheckablePushButtonTest1(int argc, char * argv [] )
   button7.setButtonTextAlignment(Qt::AlignCenter);
   button7.setIndicatorAlignment(Qt::AlignLeft);
   
+  // Connected to button, not user checkable:
+  button8.setCheckBoxUserCheckable(false);
+  button8.setCheckState(Qt::Checked);
+  button9.setCheckBoxUserCheckable(false);
+  button9.setCheckState(Qt::Unchecked);
+
+  // Not connected to button, user checkable:
+  button10.setCheckBoxControlsButton(false);
+  button10.setCheckState(Qt::Checked);
+  button11.setCheckBoxControlsButton(false);
+  button11.setCheckState(Qt::PartiallyChecked);
+
+  button12.setCheckBoxControlsButton(false);
+  button12.setCheckBoxUserCheckable(false);
+  button12.setCheckable(true);
+  button13.setCheckBoxControlsButton(false);
+  button13.setCheckBoxUserCheckable(true);
+  button13.setCheckable(true);
+
   if (argc < 2 || QString(argv[1]) != "-I" )
     {
     QTimer::singleShot(200, &app, SLOT(quit()));

+ 118 - 7
Libs/Widgets/ctkCheckablePushButton.cpp

@@ -53,6 +53,8 @@ public:
   // Tuning of the button look&feel
   Qt::Alignment TextAlignment;
   Qt::Alignment IndicatorAlignment;
+  Qt::ItemFlags CheckBoxFlags;
+  Qt::CheckState CheckState;
 };
 
 //-----------------------------------------------------------------------------
@@ -61,6 +63,8 @@ ctkCheckablePushButtonPrivate::ctkCheckablePushButtonPrivate(ctkCheckablePushBut
 {
   this->TextAlignment = Qt::AlignLeft | Qt::AlignVCenter;
   this->IndicatorAlignment = Qt::AlignLeft | Qt::AlignVCenter;
+  this->CheckBoxFlags = Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
+  this->CheckState = Qt::Unchecked;
 }
 
 //-----------------------------------------------------------------------------
@@ -218,6 +222,74 @@ Qt::Alignment ctkCheckablePushButton::indicatorAlignment()const
 }
 
 //-----------------------------------------------------------------------------
+void ctkCheckablePushButton::setCheckState(Qt::CheckState checkState)
+{
+  Q_D(ctkCheckablePushButton);
+  Qt::CheckState oldCheckState = d->CheckState;
+  if (checkState != oldCheckState)
+    {
+    d->CheckState = checkState;
+    if (d->CheckBoxFlags & Qt::ItemIsEnabled)
+      {
+      setCheckable(checkState == Qt::Checked);
+      }
+    this->update();
+    emit checkStateChanged(checkState);
+    }
+}
+
+//-----------------------------------------------------------------------------
+Qt::CheckState ctkCheckablePushButton::checkState()const
+{
+  Q_D(const ctkCheckablePushButton);
+  return d->CheckState;
+}
+
+//-----------------------------------------------------------------------------
+void ctkCheckablePushButton::setCheckBoxControlsButton(bool b)
+{
+  Q_D(ctkCheckablePushButton);
+  if (b)
+    {
+    d->CheckBoxFlags |= Qt::ItemIsEnabled;
+    }
+  else
+    {
+    d->CheckBoxFlags &= ~Qt::ItemIsEnabled;
+    }
+  this->update();
+}
+
+//-----------------------------------------------------------------------------
+bool ctkCheckablePushButton::checkBoxControlsButton()const
+{
+  Q_D(const ctkCheckablePushButton);
+  return d->CheckBoxFlags & Qt::ItemIsEnabled;
+}
+
+//-----------------------------------------------------------------------------
+void ctkCheckablePushButton::setCheckBoxUserCheckable(bool b)
+{
+  Q_D(ctkCheckablePushButton);
+  if (b)
+    {
+    d->CheckBoxFlags |= Qt::ItemIsUserCheckable;
+    }
+  else
+    {
+    d->CheckBoxFlags &= ~Qt::ItemIsUserCheckable;
+    }
+  this->update();
+}
+
+//-----------------------------------------------------------------------------
+bool ctkCheckablePushButton::isCheckBoxUserCheckable()const
+{
+  Q_D(const ctkCheckablePushButton);
+  return d->CheckBoxFlags & Qt::ItemIsUserCheckable;
+}
+
+//-----------------------------------------------------------------------------
 QSize ctkCheckablePushButton::minimumSizeHint()const
 {
   Q_D(const ctkCheckablePushButton);
@@ -261,19 +333,41 @@ void ctkCheckablePushButton::paintEvent(QPaintEvent * _event)
     tf |= Qt::TextHideMnemonic;
     }
   int textWidth = opt.fontMetrics.boundingRect(opt.rect, tf, opt.text).width();
-  // Spacing betweent the text and the checkbox
+  // Spacing between the text and the checkbox
   int indicatorSpacing = this->style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, &opt, this);
   int buttonMargin = this->style()->pixelMetric(QStyle::PM_ButtonMargin, &opt, this);
   // Draw Indicator
   QStyleOption indicatorOpt;
   indicatorOpt.init(this);
-  if (this->isCheckable())
+  if (!(d->CheckBoxFlags & Qt::ItemIsUserCheckable))
     {
-    indicatorOpt.state |= QStyle::State_On;
+    indicatorOpt.state &= ~QStyle::State_Enabled;
+    }
+  if (d->CheckBoxFlags & Qt::ItemIsEnabled)
+    {
+    if (this->isCheckable())
+      {
+      indicatorOpt.state |= QStyle::State_On;
+      }
+    else
+      {
+      indicatorOpt.state |= QStyle::State_Off;
+      }
     }
   else
     {
-    indicatorOpt.state |= QStyle::State_Off;
+    if (d->CheckState == Qt::Checked)
+      {
+      indicatorOpt.state |= QStyle::State_On;
+      }
+    else if (d->CheckState == Qt::PartiallyChecked)
+      {
+      indicatorOpt.state |= QStyle::State_NoChange;
+      }
+    else
+      {
+      indicatorOpt.state |= QStyle::State_Off;
+      }
     }
   indicatorOpt.rect = d->checkboxRect();
   this->style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &indicatorOpt, &p, 0);
@@ -348,10 +442,27 @@ void ctkCheckablePushButton::mousePressEvent(QMouseEvent *e)
     {
     return;
     }
-  if (d->checkboxRect().contains(e->pos()))
+  if (d->checkboxRect().contains(e->pos()) &&
+      (d->CheckBoxFlags & Qt::ItemIsUserCheckable))
     {
-    //check the checkbox
-    this->setCheckable(!this->isCheckable());
+    if (d->CheckBoxFlags & Qt::ItemIsEnabled)
+      {
+      //check the checkbox
+      this->setCheckable(!this->isCheckable());
+      }
+    else
+      {
+      switch (d->CheckState)
+        {
+        case Qt::Unchecked:
+        case Qt::PartiallyChecked:
+          d->CheckState = Qt::Checked;
+          break;
+        case Qt::Checked:
+          d->CheckState = Qt::Unchecked;
+          break;
+        }
+      }
     this->update();
     e->accept();
     }

+ 21 - 2
Libs/Widgets/ctkCheckablePushButton.h

@@ -32,13 +32,20 @@
 class ctkCheckablePushButtonPrivate;
 
 /// Description
-/// ctkCheckablePushButton is a QPushButton with a checkbox that controls the
-/// checkable property of the button
+/// ctkCheckablePushButton is a QPushButton with a checkbox. By default
+/// the checkbox is connected to the checkable property of the push button.
+/// You can change this behaviour by clearing the "checkBoxControlsButton"
+/// property.
+/// The checkBoxUserCheckable property determines if the state of the
+/// checkbox can be changed interactively.
 class CTK_WIDGETS_EXPORT ctkCheckablePushButton : public QPushButton
 {
   Q_OBJECT
   Q_PROPERTY(Qt::Alignment buttonTextAlignment READ buttonTextAlignment WRITE setButtonTextAlignment)
   Q_PROPERTY(Qt::Alignment indicatorAlignment READ indicatorAlignment WRITE setIndicatorAlignment)
+  Q_PROPERTY(Qt::CheckState checkState READ checkState WRITE setCheckState NOTIFY checkStateChanged)
+  Q_PROPERTY(bool checkBoxControlsButton READ checkBoxControlsButton WRITE setCheckBoxControlsButton)
+  Q_PROPERTY(bool checkBoxUserCheckable READ isCheckBoxUserCheckable WRITE setCheckBoxUserCheckable)
 
 public:
   ctkCheckablePushButton(QWidget *parent = 0);
@@ -60,6 +67,18 @@ public:
   virtual QSize minimumSizeHint()const;
   virtual QSize sizeHint()const;
 
+  virtual Qt::CheckState checkState()const;
+  virtual void setCheckState(Qt::CheckState checkState);
+
+  virtual bool checkBoxControlsButton()const;
+  virtual void setCheckBoxControlsButton(bool b);
+
+  virtual bool isCheckBoxUserCheckable()const;
+  virtual void setCheckBoxUserCheckable(bool b);
+
+signals:
+  void checkStateChanged(Qt::CheckState newCheckState);
+
 protected:
   /// Reimplemented for internal reasons
   virtual void paintEvent(QPaintEvent*);