|
@@ -36,33 +36,29 @@
|
|
|
|
|
|
// CTK includes
|
|
|
#include "ctkCheckablePushButton.h"
|
|
|
+#include "ctkPushButton_p.h"
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-class ctkCheckablePushButtonPrivate
|
|
|
+class ctkCheckablePushButtonPrivate: public ctkPushButtonPrivate
|
|
|
{
|
|
|
Q_DECLARE_PUBLIC(ctkCheckablePushButton);
|
|
|
protected:
|
|
|
ctkCheckablePushButton* const q_ptr;
|
|
|
public:
|
|
|
ctkCheckablePushButtonPrivate(ctkCheckablePushButton& object);
|
|
|
- void init();
|
|
|
-
|
|
|
- QRect checkboxRect() const;
|
|
|
- QSize buttonSizeHint()const;
|
|
|
+ virtual void init();
|
|
|
+ virtual QStyleOptionButton drawIcon(QPainter* p);
|
|
|
|
|
|
// Tuning of the button look&feel
|
|
|
- Qt::Alignment TextAlignment;
|
|
|
- Qt::Alignment IndicatorAlignment;
|
|
|
Qt::ItemFlags CheckBoxFlags;
|
|
|
Qt::CheckState CheckState;
|
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
ctkCheckablePushButtonPrivate::ctkCheckablePushButtonPrivate(ctkCheckablePushButton& object)
|
|
|
- :q_ptr(&object)
|
|
|
+ : ctkPushButtonPrivate(object)
|
|
|
+ , q_ptr(&object)
|
|
|
{
|
|
|
- this->TextAlignment = Qt::AlignLeft | Qt::AlignVCenter;
|
|
|
- this->IndicatorAlignment = Qt::AlignLeft | Qt::AlignVCenter;
|
|
|
this->CheckBoxFlags = Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
|
|
|
this->CheckState = Qt::Unchecked;
|
|
|
}
|
|
@@ -70,110 +66,58 @@ ctkCheckablePushButtonPrivate::ctkCheckablePushButtonPrivate(ctkCheckablePushBut
|
|
|
//-----------------------------------------------------------------------------
|
|
|
void ctkCheckablePushButtonPrivate::init()
|
|
|
{
|
|
|
-}
|
|
|
+ Q_Q(ctkCheckablePushButton);
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-QRect ctkCheckablePushButtonPrivate::checkboxRect()const
|
|
|
-{
|
|
|
- Q_Q(const ctkCheckablePushButton);
|
|
|
- QRect rect;
|
|
|
QStyleOptionButton opt;
|
|
|
- q->initStyleOption(&opt);
|
|
|
+ opt.initFrom(q);
|
|
|
|
|
|
QSize indicatorSize = QSize(q->style()->pixelMetric(QStyle::PM_IndicatorWidth, &opt, q),
|
|
|
q->style()->pixelMetric(QStyle::PM_IndicatorHeight, &opt, q));
|
|
|
- int buttonHeight = opt.rect.height();
|
|
|
- uint tf = this->TextAlignment;
|
|
|
- if (q->style()->styleHint(QStyle::SH_UnderlineShortcut, &opt, q))
|
|
|
- {
|
|
|
- tf |= Qt::TextShowMnemonic;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- tf |= Qt::TextHideMnemonic;
|
|
|
- }
|
|
|
- int textWidth = opt.fontMetrics.boundingRect(opt.rect, tf, opt.text).width();
|
|
|
- int indicatorSpacing = q->style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, &opt, q);
|
|
|
- int buttonMargin = q->style()->pixelMetric(QStyle::PM_ButtonMargin, &opt, q);
|
|
|
- if (this->IndicatorAlignment & Qt::AlignLeft)
|
|
|
- {
|
|
|
- rect = QRect((buttonHeight - indicatorSize.width()) / 2,
|
|
|
- (buttonHeight - indicatorSize.height()) / 2,
|
|
|
- indicatorSize.width(), indicatorSize.height());
|
|
|
- }
|
|
|
- else if (this->IndicatorAlignment & Qt::AlignHCenter)
|
|
|
- {
|
|
|
- int w = indicatorSize.width();
|
|
|
- if (!opt.text.isEmpty() && (this->TextAlignment & Qt::AlignHCenter))
|
|
|
- {
|
|
|
- w += textWidth + indicatorSpacing;
|
|
|
- }
|
|
|
- rect = QRect(opt.rect.x()+ opt.rect.width() /2 - w / 2,
|
|
|
- (buttonHeight - indicatorSize.height()) / 2,
|
|
|
- indicatorSize.width(), indicatorSize.height());
|
|
|
- if (this->TextAlignment & Qt::AlignLeft &&
|
|
|
- rect.left() < opt.rect.x() + buttonMargin + textWidth)
|
|
|
- {
|
|
|
- rect.moveLeft(opt.rect.x() + buttonMargin + textWidth);
|
|
|
- }
|
|
|
- else if (this->TextAlignment & Qt::AlignRight &&
|
|
|
- rect.right() > opt.rect.right() - buttonMargin - textWidth)
|
|
|
- {
|
|
|
- rect.moveRight(opt.rect.right() - buttonMargin - textWidth);
|
|
|
- }
|
|
|
- }
|
|
|
- else if (this->IndicatorAlignment & Qt::AlignRight)
|
|
|
- {
|
|
|
- rect = QRect(opt.rect.width() - (buttonHeight - indicatorSize.width()) / 2
|
|
|
- - indicatorSize.width(),
|
|
|
- (buttonHeight - indicatorSize.height()) / 2,
|
|
|
- indicatorSize.width(), indicatorSize.height());
|
|
|
- }
|
|
|
- return rect;
|
|
|
+ q->setIconSize(indicatorSize);
|
|
|
+ this->IconSpacing = q->style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, &opt, q);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-QSize ctkCheckablePushButtonPrivate::buttonSizeHint()const
|
|
|
+QStyleOptionButton ctkCheckablePushButtonPrivate::drawIcon(QPainter* p)
|
|
|
{
|
|
|
- Q_Q(const ctkCheckablePushButton);
|
|
|
- int w = 0, h = 0;
|
|
|
+ Q_Q(ctkCheckablePushButton);
|
|
|
|
|
|
- QStyleOptionButton opt;
|
|
|
- opt.initFrom(q);
|
|
|
-
|
|
|
- // indicator
|
|
|
- QSize indicatorSize = QSize(q->style()->pixelMetric(QStyle::PM_IndicatorWidth, &opt, q),
|
|
|
- q->style()->pixelMetric(QStyle::PM_IndicatorHeight, &opt, q));
|
|
|
- int indicatorSpacing = q->style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, &opt, q);
|
|
|
- int ih = indicatorSize.height();
|
|
|
- int iw = indicatorSize.width() + indicatorSpacing;
|
|
|
- w += iw;
|
|
|
- h = qMax(h, ih);
|
|
|
-
|
|
|
- // text
|
|
|
- QString string(q->text());
|
|
|
- bool empty = string.isEmpty();
|
|
|
- if (empty)
|
|
|
+ QStyleOptionButton indicatorOpt;
|
|
|
+
|
|
|
+ indicatorOpt.init(q);
|
|
|
+ if (!(this->CheckBoxFlags & Qt::ItemIsUserCheckable))
|
|
|
{
|
|
|
- string = QString::fromLatin1("XXXX");
|
|
|
+ indicatorOpt.state &= ~QStyle::State_Enabled;
|
|
|
+ }
|
|
|
+ if (q->checkBoxControlsButton())
|
|
|
+ {
|
|
|
+ // Hack: calling setCheckable() instead of setCheckState while being in a
|
|
|
+ // control button mode leads to an inconsistent state, we need to make
|
|
|
+ // synchronize the 2 properties.
|
|
|
+ q->setCheckState(q->isCheckable() ? Qt::Checked : Qt::Unchecked);
|
|
|
}
|
|
|
- QFontMetrics fm = q->fontMetrics();
|
|
|
- QSize sz = fm.size(Qt::TextShowMnemonic, string);
|
|
|
- if(!empty || !w)
|
|
|
+ switch (this->CheckState)
|
|
|
{
|
|
|
- w += sz.width();
|
|
|
+ case Qt::Checked:
|
|
|
+ indicatorOpt.state |= QStyle::State_On;
|
|
|
+ break;
|
|
|
+ case Qt::PartiallyChecked:
|
|
|
+ indicatorOpt.state |= QStyle::State_NoChange;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ case Qt::Unchecked:
|
|
|
+ indicatorOpt.state |= QStyle::State_Off;
|
|
|
+ break;
|
|
|
}
|
|
|
- h = qMax(h, sz.height());
|
|
|
- //opt.rect.setSize(QSize(w, h)); // PM_MenuButtonIndicator depends on the height
|
|
|
- QSize buttonSize = (q->style()->sizeFromContents(QStyle::CT_PushButton, &opt, QSize(w, h), q).
|
|
|
- expandedTo(QApplication::globalStrut()));
|
|
|
- return buttonSize;
|
|
|
+ indicatorOpt.rect = this->iconRect();
|
|
|
+ q->style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &indicatorOpt, p, 0);
|
|
|
+ return indicatorOpt;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
//-----------------------------------------------------------------------------
|
|
|
ctkCheckablePushButton::ctkCheckablePushButton(QWidget* _parent)
|
|
|
- :QPushButton(_parent)
|
|
|
- , d_ptr(new ctkCheckablePushButtonPrivate(*this))
|
|
|
+ : ctkPushButton(new ctkCheckablePushButtonPrivate(*this), _parent)
|
|
|
{
|
|
|
Q_D(ctkCheckablePushButton);
|
|
|
d->init();
|
|
@@ -181,44 +125,28 @@ ctkCheckablePushButton::ctkCheckablePushButton(QWidget* _parent)
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
ctkCheckablePushButton::ctkCheckablePushButton(const QString& title, QWidget* _parent)
|
|
|
- :QPushButton(title, _parent)
|
|
|
- , d_ptr(new ctkCheckablePushButtonPrivate(*this))
|
|
|
-{
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-ctkCheckablePushButton::~ctkCheckablePushButton()
|
|
|
-{
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void ctkCheckablePushButton::setButtonTextAlignment(Qt::Alignment textAlignment)
|
|
|
+ : ctkPushButton(new ctkCheckablePushButtonPrivate(*this), _parent)
|
|
|
{
|
|
|
Q_D(ctkCheckablePushButton);
|
|
|
- d->TextAlignment = textAlignment;
|
|
|
- this->update();
|
|
|
+ d->init();
|
|
|
+ this->setText(title);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-Qt::Alignment ctkCheckablePushButton::buttonTextAlignment()const
|
|
|
+ctkCheckablePushButton::~ctkCheckablePushButton()
|
|
|
{
|
|
|
- Q_D(const ctkCheckablePushButton);
|
|
|
- return d->TextAlignment;
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
void ctkCheckablePushButton::setIndicatorAlignment(Qt::Alignment indicatorAlignment)
|
|
|
{
|
|
|
- Q_D(ctkCheckablePushButton);
|
|
|
- d->IndicatorAlignment = indicatorAlignment;
|
|
|
- this->update();
|
|
|
+ this->setIconAlignment(indicatorAlignment);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
Qt::Alignment ctkCheckablePushButton::indicatorAlignment()const
|
|
|
{
|
|
|
- Q_D(const ctkCheckablePushButton);
|
|
|
- return d->IndicatorAlignment;
|
|
|
+ return this->iconAlignment();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
@@ -303,144 +231,14 @@ bool ctkCheckablePushButton::isCheckBoxUserCheckable()const
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-QSize ctkCheckablePushButton::minimumSizeHint()const
|
|
|
-{
|
|
|
- Q_D(const ctkCheckablePushButton);
|
|
|
- return d->buttonSizeHint();
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-QSize ctkCheckablePushButton::sizeHint()const
|
|
|
-{
|
|
|
- return this->minimumSizeHint();
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void ctkCheckablePushButton::paintEvent(QPaintEvent * _event)
|
|
|
-{
|
|
|
- Q_UNUSED(_event);
|
|
|
- Q_D(ctkCheckablePushButton);
|
|
|
-
|
|
|
- QPainter p(this);
|
|
|
- // Draw Button
|
|
|
- QStyleOptionButton opt;
|
|
|
- this->initStyleOption(&opt);
|
|
|
-
|
|
|
- // Checkbox size
|
|
|
- QSize indicatorSize = QSize(style()->pixelMetric(QStyle::PM_IndicatorWidth, &opt, this),
|
|
|
- style()->pixelMetric(QStyle::PM_IndicatorHeight, &opt, this));
|
|
|
- // Replace the icon size by the checkbox size
|
|
|
- opt.iconSize = indicatorSize;
|
|
|
- // Draw the panel of the button (no text, no icon)
|
|
|
- style()->drawControl(QStyle::CE_PushButtonBevel, &opt, &p, this);
|
|
|
- // TBD is PE_PanelButtonCommand better ?
|
|
|
- //style()->drawPrimitive(QStyle::PE_PanelButtonCommand, &opt, &p, this);
|
|
|
- //int buttonHeight = opt.rect.height();
|
|
|
- uint tf = d->TextAlignment;
|
|
|
- if (this->style()->styleHint(QStyle::SH_UnderlineShortcut, &opt, this))
|
|
|
- {
|
|
|
- tf |= Qt::TextShowMnemonic;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- tf |= Qt::TextHideMnemonic;
|
|
|
- }
|
|
|
- int textWidth = opt.fontMetrics.boundingRect(opt.rect, tf, opt.text).width();
|
|
|
- // 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
|
|
|
- QStyleOptionButton indicatorOpt;
|
|
|
- indicatorOpt.init(this);
|
|
|
- if (!(d->CheckBoxFlags & Qt::ItemIsUserCheckable))
|
|
|
- {
|
|
|
- indicatorOpt.state &= ~QStyle::State_Enabled;
|
|
|
- }
|
|
|
- if (this->checkBoxControlsButton())
|
|
|
- {
|
|
|
- // Hack: calling setCheckable() instead of setCheckState while being in a
|
|
|
- // control button mode leads to an inconsistent state, we need to make
|
|
|
- // synchronize the 2 properties.
|
|
|
- this->setCheckState(this->isCheckable() ? Qt::Checked : Qt::Unchecked);
|
|
|
- }
|
|
|
- switch (d->CheckState)
|
|
|
- {
|
|
|
- case Qt::Checked:
|
|
|
- indicatorOpt.state |= QStyle::State_On;
|
|
|
- break;
|
|
|
- case Qt::PartiallyChecked:
|
|
|
- indicatorOpt.state |= QStyle::State_NoChange;
|
|
|
- break;
|
|
|
- default:
|
|
|
- case Qt::Unchecked:
|
|
|
- indicatorOpt.state |= QStyle::State_Off;
|
|
|
- break;
|
|
|
- }
|
|
|
- indicatorOpt.rect = d->checkboxRect();
|
|
|
- this->style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &indicatorOpt, &p, 0);
|
|
|
-
|
|
|
- // Draw Text
|
|
|
- if (d->TextAlignment & Qt::AlignLeft)
|
|
|
- {
|
|
|
- if (d->IndicatorAlignment & Qt::AlignLeft)
|
|
|
- {
|
|
|
- opt.rect.setLeft(indicatorOpt.rect.right() + indicatorSpacing);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- opt.rect.setLeft(opt.rect.x() + buttonMargin);
|
|
|
- }
|
|
|
- }
|
|
|
- else if (d->TextAlignment & Qt::AlignHCenter)
|
|
|
- {
|
|
|
- if (d->IndicatorAlignment & Qt::AlignHCenter)
|
|
|
- {
|
|
|
- opt.rect.setLeft(indicatorOpt.rect.right() + indicatorSpacing);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- opt.rect.setLeft(opt.rect.x() + opt.rect.width() / 2 - textWidth / 2);
|
|
|
- if (d->IndicatorAlignment & Qt::AlignLeft)
|
|
|
- {
|
|
|
- opt.rect.setLeft( qMax(indicatorOpt.rect.right() + indicatorSpacing, opt.rect.left()) );
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else if (d->TextAlignment & Qt::AlignRight)
|
|
|
- {
|
|
|
- if (d->IndicatorAlignment & Qt::AlignRight)
|
|
|
- {
|
|
|
- opt.rect.setLeft(indicatorOpt.rect.left() - indicatorSpacing - textWidth);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- opt.rect.setLeft(opt.rect.right() - buttonMargin - textWidth);
|
|
|
- }
|
|
|
- }
|
|
|
- // all the computations have been made infering the text would be left oriented
|
|
|
- tf &= ~Qt::AlignHCenter & ~Qt::AlignRight;
|
|
|
- tf |= Qt::AlignLeft;
|
|
|
- this->style()->drawItemText(&p, opt.rect, tf, opt.palette, (opt.state & QStyle::State_Enabled),
|
|
|
- opt.text, QPalette::ButtonText);
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
bool ctkCheckablePushButton::hitButton(const QPoint & _pos)const
|
|
|
{
|
|
|
Q_D(const ctkCheckablePushButton);
|
|
|
- return !d->checkboxRect().contains(_pos)
|
|
|
+ return !d->iconRect().contains(_pos)
|
|
|
&& this->QPushButton::hitButton(_pos);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void ctkCheckablePushButton::initStyleOption(QStyleOptionButton* option)const
|
|
|
-{
|
|
|
- this->QPushButton::initStyleOption(option);
|
|
|
- option->iconSize = QSize(this->style()->pixelMetric(QStyle::PM_IndicatorWidth, option, this),
|
|
|
- this->style()->pixelMetric(QStyle::PM_IndicatorHeight, option, this));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
void ctkCheckablePushButton::mousePressEvent(QMouseEvent *e)
|
|
|
{
|
|
|
Q_D(ctkCheckablePushButton);
|
|
@@ -449,7 +247,7 @@ void ctkCheckablePushButton::mousePressEvent(QMouseEvent *e)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
- if (d->checkboxRect().contains(e->pos()) &&
|
|
|
+ if (d->iconRect().contains(e->pos()) &&
|
|
|
(d->CheckBoxFlags & Qt::ItemIsUserCheckable))
|
|
|
{
|
|
|
Qt::CheckState newCheckState;
|