00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "qtoolbutton.h"
00025 #ifndef QT_NO_TOOLBUTTON
00026
00027 #include <qapplication.h>
00028 #include <qdesktopwidget.h>
00029 #include <qdrawutil.h>
00030 #include <qevent.h>
00031 #include <qicon.h>
00032 #include <qmenu.h>
00033 #include <qpainter.h>
00034 #include <qpointer.h>
00035 #include <qstyle.h>
00036 #include <qstyleoption.h>
00037 #include <qtooltip.h>
00038 #include <qmainwindow.h>
00039 #include <qtoolbar.h>
00040 #include <qvariant.h>
00041 #include <qstylepainter.h>
00042 #include <private/qabstractbutton_p.h>
00043 #include <private/qaction_p.h>
00044
00045 class QToolButtonPrivate : public QAbstractButtonPrivate
00046 {
00047 Q_DECLARE_PUBLIC(QToolButton)
00048 public:
00049 void init();
00050 #ifndef QT_NO_MENU
00051 void _q_buttonPressed();
00052 void popupTimerDone();
00053 #endif
00054 void _q_actionTriggered();
00055 QStyleOptionToolButton getStyleOption() const;
00056 QPointer<QAction> menuAction;
00057 QBasicTimer popupTimer;
00058 int delay;
00059 Qt::ArrowType arrowType;
00060 Qt::ToolButtonStyle toolButtonStyle;
00061 QToolButton::ToolButtonPopupMode popupMode;
00062 enum { NoButtonPressed=0, MenuButtonPressed=1, ToolButtonPressed=2 };
00063 uint buttonPressed : 2;
00064 uint menuButtonDown : 1;
00065 uint autoRaise : 1;
00066 uint repeat : 1;
00067 QAction *defaultAction;
00068 #ifndef QT_NO_MENU
00069 bool hasMenu() const;
00070 #endif
00071 };
00072
00073 #ifndef QT_NO_MENU
00074 bool QToolButtonPrivate::hasMenu() const
00075 {
00076 Q_Q(const QToolButton);
00077 return ((defaultAction && defaultAction->menu())
00078 || (menuAction && menuAction->menu())
00079 || q->actions().size() > (defaultAction ? 1 : 0));
00080 }
00081 #endif
00082
00158 QToolButton::QToolButton(QWidget * parent)
00159 : QAbstractButton(*new QToolButtonPrivate, parent)
00160 {
00161 Q_D(QToolButton);
00162 d->init();
00163 }
00164
00165 #ifdef QT3_SUPPORT
00166
00171 QToolButton::QToolButton(QWidget * parent, const char *name)
00172 : QAbstractButton(*new QToolButtonPrivate, parent)
00173 {
00174 Q_D(QToolButton);
00175 setObjectName(QString::fromAscii(name));
00176 d->init();
00177 }
00178
00189 QToolButton::QToolButton(const QIcon& icon, const QString &textLabel,
00190 const QString& statusTip,
00191 QObject * receiver, const char *slot,
00192 QWidget * parent, const char *name)
00193 : QAbstractButton(*new QToolButtonPrivate, parent)
00194 {
00195 Q_D(QToolButton);
00196 setObjectName(QString::fromAscii(name));
00197 d->init();
00198 setIcon(icon);
00199 setText(textLabel);
00200 if (receiver && slot)
00201 connect(this, SIGNAL(clicked()), receiver, slot);
00202 #ifndef QT_NO_TOOLTIP
00203 if (!textLabel.isEmpty())
00204 setToolTip(textLabel);
00205 #endif
00206 #ifndef QT_NO_STATUSTIP
00207 if (!statusTip.isEmpty())
00208 setStatusTip(statusTip);
00209 #else
00210 Q_UNUSED(statusTip);
00211 #endif
00212 }
00213
00214
00225 QToolButton::QToolButton(Qt::ArrowType type, QWidget *parent, const char *name)
00226 : QAbstractButton(*new QToolButtonPrivate, parent)
00227 {
00228 Q_D(QToolButton);
00229 setObjectName(QString::fromAscii(name));
00230 d->init();
00231 setAutoRepeat(true);
00232 d->arrowType = type;
00233 }
00234
00235 #endif
00236
00237
00238
00239
00240 void QToolButtonPrivate::init()
00241 {
00242 Q_Q(QToolButton);
00243 delay = q->style()->styleHint(QStyle::SH_ToolButton_PopupDelay, 0, q);
00244 defaultAction = 0;
00245 #ifndef QT_NO_TOOLBAR
00246 if (qobject_cast<QToolBar*>(q->parentWidget()))
00247 autoRaise = true;
00248 else
00249 #endif
00250 autoRaise = false;
00251 arrowType = Qt::NoArrow;
00252 menuButtonDown = false;
00253 popupMode = QToolButton::DelayedPopup;
00254 buttonPressed = QToolButtonPrivate::NoButtonPressed;
00255
00256 toolButtonStyle = Qt::ToolButtonIconOnly;
00257
00258 q->setFocusPolicy(Qt::TabFocus);
00259 q->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
00260
00261 QObject::connect(q, SIGNAL(pressed()), q, SLOT(_q_buttonPressed()));
00262 }
00263
00264
00265 QStyleOptionToolButton QToolButtonPrivate::getStyleOption() const
00266 {
00267 Q_Q(const QToolButton);
00268 QStyleOptionToolButton opt;
00269 opt.init(q);
00270 bool down = q->isDown();
00271 bool checked = q->isChecked();
00272 bool forceNoText = false;
00273
00274 #ifndef QT_NO_TOOLBAR
00275 if (q->parentWidget()) {
00276 #ifdef QT3_SUPPORT
00277 if (q->parentWidget()->inherits("Q3ToolBar")) {
00278 int iconSize = q->style()->pixelMetric(QStyle::PM_ToolBarIconSize, &opt, q);
00279 opt.iconSize = icon.actualSize(QSize(iconSize, iconSize));
00280 forceNoText = toolButtonStyle == Qt::ToolButtonIconOnly;
00281 } else
00282 #endif
00283 if (QToolBar *toolBar = qobject_cast<QToolBar *>(q->parentWidget())) {
00284 opt.iconSize = toolBar->iconSize();
00285 } else {
00286 opt.iconSize = q->iconSize();
00287 }
00288 }
00289 #endif // QT_NO_TOOLBAR
00290
00291 if (!forceNoText)
00292 opt.text = text;
00293 opt.icon = icon;
00294 opt.arrowType = arrowType;
00295 if (down)
00296 opt.state |= QStyle::State_Sunken;
00297 if (checked)
00298 opt.state |= QStyle::State_On;
00299 if (autoRaise)
00300 opt.state |= QStyle::State_AutoRaise;
00301 if (!checked && !down)
00302 opt.state |= QStyle::State_Raised;
00303
00304 opt.subControls = QStyle::SC_ToolButton;
00305 opt.activeSubControls = QStyle::SC_None;
00306
00307
00308
00309 opt.features = QStyleOptionToolButton::None;
00310 if (popupMode == QToolButton::MenuButtonPopup) {
00311 opt.subControls |= QStyle::SC_ToolButtonMenu;
00312 opt.features |= QStyleOptionToolButton::Menu;
00313 if (menuButtonDown || down) {
00314 opt.state |= QStyle::State_MouseOver;
00315 opt.activeSubControls |= QStyle::SC_ToolButtonMenu;
00316 }
00317 } else {
00318 if (menuButtonDown)
00319 opt.state |= QStyle::State_Sunken;
00320 }
00321 if (arrowType != Qt::NoArrow)
00322 opt.features |= QStyleOptionToolButton::Arrow;
00323 if (popupMode == QToolButton::DelayedPopup)
00324 opt.features |= QStyleOptionToolButton::PopupDelay;
00325 opt.toolButtonStyle = toolButtonStyle;
00326 if (icon.isNull() && arrowType == Qt::NoArrow && !forceNoText) {
00327 if (!text.isEmpty())
00328 opt.toolButtonStyle = Qt::ToolButtonTextOnly;
00329 else if (opt.toolButtonStyle != Qt::ToolButtonTextOnly)
00330 opt.toolButtonStyle = Qt::ToolButtonIconOnly;
00331 } else {
00332 if (text.isEmpty() && opt.toolButtonStyle != Qt::ToolButtonIconOnly)
00333 opt.toolButtonStyle = Qt::ToolButtonIconOnly;
00334 }
00335
00336 opt.pos = q->pos();
00337 opt.font = q->font();
00338 return opt;
00339 }
00340
00345 QToolButton::~QToolButton()
00346 {
00347 }
00348
00352 QSize QToolButton::sizeHint() const
00353 {
00354 Q_D(const QToolButton);
00355 ensurePolished();
00356
00357 int w = 0, h = 0;
00358 QStyleOptionToolButton opt = d->getStyleOption();
00359
00360 QFontMetrics fm = fontMetrics();
00361 if (opt.toolButtonStyle != Qt::ToolButtonTextOnly) {
00362 QSize icon = opt.iconSize;
00363 w = icon.width();
00364 h = icon.height();
00365 }
00366
00367 if (opt.toolButtonStyle != Qt::ToolButtonIconOnly) {
00368 QSize textSize = fm.size(Qt::TextShowMnemonic, text());
00369 textSize.setWidth(textSize.width() + fm.width(QLatin1Char(' '))*2);
00370 if (opt.toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
00371 h += 4 + textSize.height();
00372 if (textSize.width() > w)
00373 w = textSize.width();
00374 } else if (opt.toolButtonStyle == Qt::ToolButtonTextBesideIcon) {
00375 w += 4 + textSize.width();
00376 if (textSize.height() > h)
00377 h = textSize.height();
00378 } else {
00379 w = textSize.width();
00380 h = textSize.height();
00381 }
00382 }
00383
00384 opt.rect.setHeight(h);
00385 if (d->popupMode == MenuButtonPopup)
00386 w += style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &opt, this);
00387
00388 return style()->sizeFromContents(QStyle::CT_ToolButton, &opt, QSize(w, h), this).
00389 expandedTo(QApplication::globalStrut());
00390 }
00391
00395 QSize QToolButton::minimumSizeHint() const
00396 {
00397 return sizeHint();
00398 }
00399
00431 Qt::ToolButtonStyle QToolButton::toolButtonStyle() const
00432 {
00433 Q_D(const QToolButton);
00434 return d->toolButtonStyle;
00435 }
00436
00437 Qt::ArrowType QToolButton::arrowType() const
00438 {
00439 Q_D(const QToolButton);
00440 return d->arrowType;
00441 }
00442
00443
00444 void QToolButton::setToolButtonStyle(Qt::ToolButtonStyle style)
00445 {
00446 Q_D(QToolButton);
00447 if (d->toolButtonStyle == style)
00448 return;
00449
00450 d->toolButtonStyle = style;
00451 updateGeometry();
00452 if (isVisible()) {
00453 update();
00454 }
00455 }
00456
00457 void QToolButton::setArrowType(Qt::ArrowType type)
00458 {
00459 Q_D(QToolButton);
00460 if (d->arrowType == type)
00461 return;
00462
00463 d->arrowType = type;
00464 updateGeometry();
00465 if (isVisible()) {
00466 update();
00467 }
00468 }
00469
00475 void QToolButton::paintEvent(QPaintEvent *)
00476 {
00477 Q_D(QToolButton);
00478 QStylePainter p(this);
00479 p.drawComplexControl(QStyle::CC_ToolButton, d->getStyleOption());
00480 }
00481
00485 void QToolButton::actionEvent(QActionEvent *event)
00486 {
00487 Q_D(QToolButton);
00488 QAction *action = event->action();
00489 switch (event->type()) {
00490 case QEvent::ActionChanged:
00491 if (action == d->defaultAction)
00492 setDefaultAction(action);
00493 break;
00494 case QEvent::ActionAdded:
00495 connect(action, SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
00496 break;
00497 case QEvent::ActionRemoved:
00498 if (d->defaultAction == action)
00499 d->defaultAction = 0;
00500 #ifndef QT_NO_MENU
00501 if (action == d->menuAction)
00502 d->menuAction = 0;
00503 #endif
00504 action->disconnect(this);
00505 break;
00506 default:
00507 ;
00508 }
00509 QAbstractButton::actionEvent(event);
00510 }
00511
00512 void QToolButtonPrivate::_q_actionTriggered()
00513 {
00514 Q_Q(QToolButton);
00515 if (QAction *action = qobject_cast<QAction *>(q->sender()))
00516 emit q->triggered(action);
00517 }
00518
00522 void QToolButton::enterEvent(QEvent * e)
00523 {
00524 Q_D(QToolButton);
00525 if (d->autoRaise)
00526 update();
00527
00528 QAbstractButton::enterEvent(e);
00529 }
00530
00531
00535 void QToolButton::leaveEvent(QEvent * e)
00536 {
00537 Q_D(QToolButton);
00538 if (d->autoRaise)
00539 update();
00540
00541 QAbstractButton::leaveEvent(e);
00542 }
00543
00544
00548 void QToolButton::timerEvent(QTimerEvent *e)
00549 {
00550 #ifndef QT_NO_MENU
00551 Q_D(QToolButton);
00552 if (e->timerId() == d->popupTimer.timerId()) {
00553 d->popupTimerDone();
00554 return;
00555 }
00556 #endif
00557 QAbstractButton::timerEvent(e);
00558 }
00559
00560
00564 void QToolButton::changeEvent(QEvent *e)
00565 {
00566 #ifndef QT_NO_TOOLBAR
00567 Q_D(QToolButton);
00568 if (e->type() == QEvent::ParentChange) {
00569 if (qobject_cast<QToolBar*>(parentWidget()))
00570 d->autoRaise = true;
00571 }
00572 #endif
00573 QAbstractButton::changeEvent(e);
00574 }
00575
00579 void QToolButton::mousePressEvent(QMouseEvent *e)
00580 {
00581 Q_D(QToolButton);
00582 #ifndef QT_NO_MENU
00583 QStyleOptionToolButton opt = d->getStyleOption();
00584 if (e->button() == Qt::LeftButton && d->popupMode == MenuButtonPopup) {
00585 QRect popupr = style()->subControlRect(QStyle::CC_ToolButton, &opt,
00586 QStyle::SC_ToolButtonMenu, this);
00587 if (popupr.isValid() && popupr.contains(e->pos())) {
00588 d->buttonPressed = QToolButtonPrivate::MenuButtonPressed;
00589 showMenu();
00590 return;
00591 }
00592 }
00593 #endif
00594 d->buttonPressed = QToolButtonPrivate::ToolButtonPressed;
00595 QAbstractButton::mousePressEvent(e);
00596 }
00597
00601 void QToolButton::mouseReleaseEvent(QMouseEvent *e)
00602 {
00603 Q_D(QToolButton);
00604 QAbstractButton::mouseReleaseEvent(e);
00605 d->buttonPressed = QToolButtonPrivate::NoButtonPressed;
00606 }
00607
00611 bool QToolButton::hitButton(const QPoint &pos) const
00612 {
00613 Q_D(const QToolButton);
00614 if(QAbstractButton::hitButton(pos))
00615 return (d->buttonPressed != QToolButtonPrivate::MenuButtonPressed);
00616 return false;
00617 }
00618
00619 #ifdef QT3_SUPPORT
00620
00624 QIcon QToolButton::onIconSet() const
00625 {
00626 return icon();
00627 }
00628
00632 QIcon QToolButton::offIconSet() const
00633 {
00634 return icon();
00635 }
00636
00637
00643 void QToolButton::setOnIconSet(const QIcon& set)
00644 {
00645 setIcon(set);
00646 }
00647
00653 void QToolButton::setOffIconSet(const QIcon& set)
00654 {
00655 setIcon(set);
00656 }
00657
00658
00672 void QToolButton::setIconSet(const QIcon & set, bool )
00673 {
00674 QAbstractButton::setIcon(set);
00675 }
00676
00687 QIcon QToolButton::iconSet(bool ) const
00688 {
00689 return QAbstractButton::icon();
00690 }
00691
00692 #endif
00693
00694 #ifndef QT_NO_MENU
00695
00704 void QToolButton::setMenu(QMenu* menu)
00705 {
00706 Q_D(QToolButton);
00707
00708 if (d->menuAction)
00709 removeAction(d->menuAction);
00710
00711 if (menu) {
00712 d->menuAction = menu->menuAction();
00713 addAction(d->menuAction);
00714 } else {
00715 d->menuAction = 0;
00716 }
00717 update();
00718 }
00719
00725 QMenu* QToolButton::menu() const
00726 {
00727 Q_D(const QToolButton);
00728 if (d->menuAction)
00729 return d->menuAction->menu();
00730 return 0;
00731 }
00732
00738 void QToolButton::showMenu()
00739 {
00740 Q_D(QToolButton);
00741 if (!d->hasMenu()) {
00742 d->menuButtonDown = false;
00743 return;
00744 }
00745
00746 d->menuButtonDown = true;
00747 repaint();
00748 d->popupTimer.stop();
00749 d->popupTimerDone();
00750 }
00751
00752 void QToolButtonPrivate::_q_buttonPressed()
00753 {
00754 Q_Q(QToolButton);
00755 if (!hasMenu())
00756 return;
00757
00758 if (delay > 0 && popupMode == QToolButton::DelayedPopup)
00759 popupTimer.start(delay, q);
00760 else if (popupMode == QToolButton::InstantPopup)
00761 q->showMenu();
00762 }
00763
00764 void QToolButtonPrivate::popupTimerDone()
00765 {
00766 Q_Q(QToolButton);
00767 popupTimer.stop();
00768 if (!menuButtonDown && !down)
00769 return;
00770
00771 menuButtonDown = true;
00772 QPointer<QMenu> actualMenu;
00773 bool mustDeleteActualMenu = false;
00774 if(menuAction) {
00775 actualMenu = menuAction->menu();
00776 if (q->actions().size() > 1)
00777 qWarning("QToolButton: Menu in setMenu() overriding actions set in addAction!");
00778 } else if (defaultAction && defaultAction->menu()) {
00779 actualMenu = defaultAction->menu();
00780 } else {
00781 actualMenu = new QMenu(q);
00782 mustDeleteActualMenu = true;
00783 QList<QAction*> actions = q->actions();
00784 for(int i = 0; i < actions.size(); i++)
00785 actualMenu->addAction(actions.at(i));
00786 }
00787 repeat = q->autoRepeat();
00788 q->setAutoRepeat(false);
00789 bool horizontal = true;
00790 #if !defined(QT_NO_TOOLBAR)
00791 QToolBar *tb = qobject_cast<QToolBar*>(q->parentWidget());
00792 if (tb && tb->orientation() == Qt::Vertical)
00793 horizontal = false;
00794 #endif
00795 QPoint p;
00796 QRect screen = qApp->desktop()->availableGeometry(q);
00797 QSize sh = actualMenu->sizeHint();
00798 QRect rect = q->rect();
00799 if (horizontal) {
00800 if (q->isRightToLeft()) {
00801 if (q->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height()) {
00802 p = q->mapToGlobal(rect.bottomRight());
00803 } else {
00804 p = q->mapToGlobal(rect.topRight() - QPoint(0, sh.height()));
00805 }
00806 p.rx() -= sh.width();
00807 } else {
00808 if (q->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height()) {
00809 p = q->mapToGlobal(rect.bottomLeft());
00810 } else {
00811 p = q->mapToGlobal(rect.topLeft() - QPoint(0, sh.height()));
00812 }
00813 }
00814 } else {
00815 if (q->isRightToLeft()) {
00816 if (q->mapToGlobal(QPoint(rect.left(), 0)).x() - sh.width() <= screen.x()) {
00817 p = q->mapToGlobal(rect.topRight());
00818 } else {
00819 p = q->mapToGlobal(rect.topLeft());
00820 p.rx() -= sh.width();
00821 }
00822 } else {
00823 if (q->mapToGlobal(QPoint(rect.right(), 0)).x() + sh.width() <= screen.right()) {
00824 p = q->mapToGlobal(rect.topRight());
00825 } else {
00826 p = q->mapToGlobal(rect.topLeft() - QPoint(sh.width(), 0));
00827 }
00828 }
00829 }
00830 p.rx() = qMax(screen.left(), qMin(p.x(), screen.right() - sh.width()));
00831 p.ry() += 1;
00832 QPointer<QToolButton> that = q;
00833 actualMenu->setNoReplayFor(q);
00834 actualMenu->exec(p);
00835 if (mustDeleteActualMenu)
00836 delete actualMenu;
00837 if (!that)
00838 return;
00839
00840 if (repeat)
00841 q->setAutoRepeat(true);
00842 menuButtonDown = false;
00843 if (q->isDown())
00844 q->setDown(false);
00845 else
00846 q->repaint();
00847 }
00848 #endif // QT_NO_MENU
00849
00850 #ifdef QT3_SUPPORT
00851
00856 void QToolButton::setPopupDelay(int delay)
00857 {
00858 Q_D(QToolButton);
00859 d->delay = delay;
00860
00861 update();
00862 }
00863
00867 int QToolButton::popupDelay() const
00868 {
00869 Q_D(const QToolButton);
00870 return d->delay;
00871 }
00872 #endif
00873
00874 #ifndef QT_NO_MENU
00875
00903 void QToolButton::setPopupMode(ToolButtonPopupMode mode)
00904 {
00905 Q_D(QToolButton);
00906 d->popupMode = mode;
00907 }
00908
00909 QToolButton::ToolButtonPopupMode QToolButton::popupMode() const
00910 {
00911 Q_D(const QToolButton);
00912 return d->popupMode;
00913 }
00914 #endif
00915
00924 void QToolButton::setAutoRaise(bool enable)
00925 {
00926 Q_D(QToolButton);
00927 d->autoRaise = enable;
00928
00929 update();
00930 }
00931
00932 bool QToolButton::autoRaise() const
00933 {
00934 Q_D(const QToolButton);
00935 return d->autoRaise;
00936 }
00937
00944 void QToolButton::setDefaultAction(QAction *action)
00945 {
00946 Q_D(QToolButton);
00947 #ifndef QT_NO_MENU
00948 bool hadMenu = false;
00949 hadMenu = d->hasMenu();
00950 #endif
00951 d->defaultAction = action;
00952 if (!action)
00953 return;
00954 if (!actions().contains(action))
00955 addAction(action);
00956 setText(action->iconText());
00957 setIcon(action->icon());
00958 #ifndef QT_NO_TOOLTIP
00959 setToolTip(action->toolTip());
00960 #endif
00961 #ifndef QT_NO_STATUSTIP
00962 setStatusTip(action->statusTip());
00963 #endif
00964 #ifndef QT_NO_WHATSTHIS
00965 setWhatsThis(action->whatsThis());
00966 #endif
00967 #ifndef QT_NO_MENU
00968 if (action->menu() && !hadMenu) {
00969
00970
00971
00972 setPopupMode(QToolButton::MenuButtonPopup);
00973 }
00974 #endif
00975 setCheckable(action->isCheckable());
00976 setChecked(action->isChecked());
00977 setEnabled(action->isEnabled());
00978 if (action->d_func()->fontSet)
00979 setFont(action->font());
00980 }
00981
00982
00988 QAction *QToolButton::defaultAction() const
00989 {
00990 Q_D(const QToolButton);
00991 return d->defaultAction;
00992 }
00993
00994
00995
00999 void QToolButton::nextCheckState()
01000 {
01001 Q_D(QToolButton);
01002 if (!d->defaultAction)
01003 QAbstractButton::nextCheckState();
01004 else
01005 d->defaultAction->trigger();
01006 }
01007
01009 bool QToolButton::event(QEvent *e)
01010 {
01011 return QAbstractButton::event(e);
01012 }
01013
01016 QToolButton::QToolButton(QToolButtonPrivate &dd, QWidget *parent)
01017 :QAbstractButton(dd, parent)
01018 {
01019 Q_D(QToolButton);
01020 d->init();
01021 }
01022
01106 #include "moc_qtoolbutton.cpp"
01107
01108 #endif