/**************************************************************************** | |
** | |
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). | |
** All rights reserved. | |
** Contact: Nokia Corporation (qt-info@nokia.com) | |
** | |
** This file is part of the QtGui module of the Qt Toolkit. | |
** | |
** $QT_BEGIN_LICENSE:LGPL$ | |
** GNU Lesser General Public License Usage | |
** This file may be used under the terms of the GNU Lesser General Public | |
** License version 2.1 as published by the Free Software Foundation and | |
** appearing in the file LICENSE.LGPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU Lesser | |
** General Public License version 2.1 requirements will be met: | |
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | |
** | |
** In addition, as a special exception, Nokia gives you certain additional | |
** rights. These rights are described in the Nokia Qt LGPL Exception | |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | |
** | |
** GNU General Public License Usage | |
** Alternatively, this file may be used under the terms of the GNU General | |
** Public License version 3.0 as published by the Free Software Foundation | |
** and appearing in the file LICENSE.GPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU General | |
** Public License version 3.0 requirements will be met: | |
** http://www.gnu.org/copyleft/gpl.html. | |
** | |
** Other Usage | |
** Alternatively, this file may be used in accordance with the terms and | |
** conditions contained in a signed written agreement between you and Nokia. | |
** | |
** | |
** | |
** | |
** | |
** $QT_END_LICENSE$ | |
** | |
****************************************************************************/ | |
#include "qtoolbutton.h" | |
#ifndef QT_NO_TOOLBUTTON | |
#include <qapplication.h> | |
#include <qdesktopwidget.h> | |
#include <qdrawutil.h> | |
#include <qevent.h> | |
#include <qicon.h> | |
#include <qmenu.h> | |
#include <qpainter.h> | |
#include <qpointer.h> | |
#include <qstyle.h> | |
#include <qstyleoption.h> | |
#include <qtooltip.h> | |
#include <qmainwindow.h> | |
#include <qtoolbar.h> | |
#include <qvariant.h> | |
#include <qstylepainter.h> | |
#include <private/qabstractbutton_p.h> | |
#include <private/qaction_p.h> | |
#include <private/qmenu_p.h> | |
QT_BEGIN_NAMESPACE | |
class QToolButtonPrivate : public QAbstractButtonPrivate | |
{ | |
Q_DECLARE_PUBLIC(QToolButton) | |
public: | |
void init(); | |
#ifndef QT_NO_MENU | |
void _q_buttonPressed(); | |
void popupTimerDone(); | |
void _q_updateButtonDown(); | |
void _q_menuTriggered(QAction *); | |
#endif | |
bool updateHoverControl(const QPoint &pos); | |
void _q_actionTriggered(); | |
QStyle::SubControl newHoverControl(const QPoint &pos); | |
QStyle::SubControl hoverControl; | |
QRect hoverRect; | |
QPointer<QAction> menuAction; //the menu set by the user (setMenu) | |
QBasicTimer popupTimer; | |
int delay; | |
Qt::ArrowType arrowType; | |
Qt::ToolButtonStyle toolButtonStyle; | |
QToolButton::ToolButtonPopupMode popupMode; | |
enum { NoButtonPressed=0, MenuButtonPressed=1, ToolButtonPressed=2 }; | |
uint buttonPressed : 2; | |
uint menuButtonDown : 1; | |
uint autoRaise : 1; | |
uint repeat : 1; | |
QAction *defaultAction; | |
#ifndef QT_NO_MENU | |
bool hasMenu() const; | |
//workaround for task 177850 | |
QList<QAction *> actionsCopy; | |
#endif | |
#ifdef QT3_SUPPORT | |
bool userDefinedPopupDelay; | |
#endif | |
}; | |
#ifndef QT_NO_MENU | |
bool QToolButtonPrivate::hasMenu() const | |
{ | |
return ((defaultAction && defaultAction->menu()) | |
|| (menuAction && menuAction->menu()) | |
|| actions.size() > (defaultAction ? 1 : 0)); | |
} | |
#endif | |
/*! | |
\class QToolButton | |
\brief The QToolButton class provides a quick-access button to | |
commands or options, usually used inside a QToolBar. | |
\ingroup basicwidgets | |
A tool button is a special button that provides quick-access to | |
specific commands or options. As opposed to a normal command | |
button, a tool button usually doesn't show a text label, but shows | |
an icon instead. | |
Tool buttons are normally created when new QAction instances are | |
created with QToolBar::addAction() or existing actions are added | |
to a toolbar with QToolBar::addAction(). It is also possible to | |
construct tool buttons in the same way as any other widget, and | |
arrange them alongside other widgets in layouts. | |
One classic use of a tool button is to select tools; for example, | |
the "pen" tool in a drawing program. This would be implemented | |
by using a QToolButton as a toggle button (see setToggleButton()). | |
QToolButton supports auto-raising. In auto-raise mode, the button | |
draws a 3D frame only when the mouse points at it. The feature is | |
automatically turned on when a button is used inside a QToolBar. | |
Change it with setAutoRaise(). | |
A tool button's icon is set as QIcon. This makes it possible to | |
specify different pixmaps for the disabled and active state. The | |
disabled pixmap is used when the button's functionality is not | |
available. The active pixmap is displayed when the button is | |
auto-raised because the mouse pointer is hovering over it. | |
The button's look and dimension is adjustable with | |
setToolButtonStyle() and setIconSize(). When used inside a | |
QToolBar in a QMainWindow, the button automatically adjusts to | |
QMainWindow's settings (see QMainWindow::setToolButtonStyle() and | |
QMainWindow::setIconSize()). Instead of an icon, a tool button can | |
also display an arrow symbol, specified with | |
\l{QToolButton::arrowType} {arrowType}. | |
A tool button can offer additional choices in a popup menu. The | |
popup menu can be set using setMenu(). Use setPopupMode() to | |
configure the different modes available for tool buttons with a | |
menu set. The default mode is DelayedPopupMode which is sometimes | |
used with the "Back" button in a web browser. After pressing and | |
holding the button down for a while, a menu pops up showing a list | |
of possible pages to jump to. The default delay is 600 ms; you can | |
adjust it with setPopupDelay(). | |
\table 100% | |
\row \o \inlineimage assistant-toolbar.png Qt Assistant's toolbar with tool buttons | |
\row \o Qt Assistant's toolbar contains tool buttons that are associated | |
with actions used in other parts of the main window. | |
\endtable | |
\sa QPushButton, QToolBar, QMainWindow, QAction, | |
{fowler}{GUI Design Handbook: Push Button} | |
*/ | |
/*! | |
\fn void QToolButton::triggered(QAction *action) | |
This signal is emitted when the given \a action is triggered. | |
The action may also be associated with other parts of the user interface, | |
such as menu items and keyboard shortcuts. Sharing actions in this | |
way helps make the user interface more consistent and is often less work | |
to implement. | |
*/ | |
/*! | |
Constructs an empty tool button with parent \a | |
parent. | |
*/ | |
QToolButton::QToolButton(QWidget * parent) | |
: QAbstractButton(*new QToolButtonPrivate, parent) | |
{ | |
Q_D(QToolButton); | |
d->init(); | |
} | |
#ifdef QT3_SUPPORT | |
/*! | |
Constructs an empty tool button called \a name, with parent \a | |
parent. | |
*/ | |
QToolButton::QToolButton(QWidget * parent, const char *name) | |
: QAbstractButton(*new QToolButtonPrivate, parent) | |
{ | |
Q_D(QToolButton); | |
setObjectName(QString::fromAscii(name)); | |
d->init(); | |
} | |
/*! | |
Constructs a tool button called \a name, that is a child of \a | |
parent. | |
The tool button will display the given \a icon, with its text | |
label and tool tip set to \a textLabel and its status bar message | |
set to \a statusTip. It will be connected to the \a slot in | |
object \a receiver. | |
*/ | |
QToolButton::QToolButton(const QIcon& icon, const QString &textLabel, | |
const QString& statusTip, | |
QObject * receiver, const char *slot, | |
QWidget * parent, const char *name) | |
: QAbstractButton(*new QToolButtonPrivate, parent) | |
{ | |
Q_D(QToolButton); | |
setObjectName(QString::fromAscii(name)); | |
d->init(); | |
setIcon(icon); | |
setText(textLabel); | |
if (receiver && slot) | |
connect(this, SIGNAL(clicked()), receiver, slot); | |
#ifndef QT_NO_TOOLTIP | |
if (!textLabel.isEmpty()) | |
setToolTip(textLabel); | |
#endif | |
#ifndef QT_NO_STATUSTIP | |
if (!statusTip.isEmpty()) | |
setStatusTip(statusTip); | |
#else | |
Q_UNUSED(statusTip); | |
#endif | |
} | |
/*! | |
Constructs a tool button as an arrow button. The Qt::ArrowType \a | |
type defines the arrow direction. Possible values are | |
Qt::LeftArrow, Qt::RightArrow, Qt::UpArrow, and Qt::DownArrow. | |
An arrow button has auto-repeat turned on by default. | |
The \a parent and \a name arguments are sent to the QWidget | |
constructor. | |
*/ | |
QToolButton::QToolButton(Qt::ArrowType type, QWidget *parent, const char *name) | |
: QAbstractButton(*new QToolButtonPrivate, parent) | |
{ | |
Q_D(QToolButton); | |
setObjectName(QString::fromAscii(name)); | |
d->init(); | |
setAutoRepeat(true); | |
d->arrowType = type; | |
} | |
#endif | |
/* Set-up code common to all the constructors */ | |
void QToolButtonPrivate::init() | |
{ | |
Q_Q(QToolButton); | |
delay = q->style()->styleHint(QStyle::SH_ToolButton_PopupDelay, 0, q); | |
#ifdef QT3_SUPPORT | |
userDefinedPopupDelay = false; | |
#endif | |
defaultAction = 0; | |
#ifndef QT_NO_TOOLBAR | |
if (qobject_cast<QToolBar*>(parent)) | |
autoRaise = true; | |
else | |
#endif | |
autoRaise = false; | |
arrowType = Qt::NoArrow; | |
menuButtonDown = false; | |
popupMode = QToolButton::DelayedPopup; | |
buttonPressed = QToolButtonPrivate::NoButtonPressed; | |
toolButtonStyle = Qt::ToolButtonIconOnly; | |
hoverControl = QStyle::SC_None; | |
q->setFocusPolicy(Qt::TabFocus); | |
q->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed, | |
QSizePolicy::ToolButton)); | |
#ifndef QT_NO_MENU | |
QObject::connect(q, SIGNAL(pressed()), q, SLOT(_q_buttonPressed())); | |
#endif | |
setLayoutItemMargins(QStyle::SE_ToolButtonLayoutItem); | |
} | |
/*! | |
Initialize \a option with the values from this QToolButton. This method | |
is useful for subclasses when they need a QStyleOptionToolButton, but don't want | |
to fill in all the information themselves. | |
\sa QStyleOption::initFrom() | |
*/ | |
void QToolButton::initStyleOption(QStyleOptionToolButton *option) const | |
{ | |
if (!option) | |
return; | |
Q_D(const QToolButton); | |
option->initFrom(this); | |
bool forceNoText = false; | |
option->iconSize = iconSize(); //default value | |
#ifndef QT_NO_TOOLBAR | |
if (parentWidget()) { | |
if (QToolBar *toolBar = qobject_cast<QToolBar *>(parentWidget())) { | |
option->iconSize = toolBar->iconSize(); | |
} | |
#ifdef QT3_SUPPORT | |
else if (parentWidget()->inherits("Q3ToolBar")) { | |
if (!option->iconSize.isValid()) { | |
int iconSize = style()->pixelMetric(QStyle::PM_ToolBarIconSize, option, this); | |
option->iconSize = d->icon.actualSize(QSize(iconSize, iconSize)); | |
} | |
forceNoText = d->toolButtonStyle == Qt::ToolButtonIconOnly; | |
} | |
#endif | |
} | |
#endif // QT_NO_TOOLBAR | |
if (!forceNoText) | |
option->text = d->text; | |
option->icon = d->icon; | |
option->arrowType = d->arrowType; | |
if (d->down) | |
option->state |= QStyle::State_Sunken; | |
if (d->checked) | |
option->state |= QStyle::State_On; | |
if (d->autoRaise) | |
option->state |= QStyle::State_AutoRaise; | |
if (!d->checked && !d->down) | |
option->state |= QStyle::State_Raised; | |
option->subControls = QStyle::SC_ToolButton; | |
option->activeSubControls = QStyle::SC_None; | |
option->features = QStyleOptionToolButton::None; | |
if (d->popupMode == QToolButton::MenuButtonPopup) { | |
option->subControls |= QStyle::SC_ToolButtonMenu; | |
option->features |= QStyleOptionToolButton::MenuButtonPopup; | |
} | |
if (option->state & QStyle::State_MouseOver) { | |
option->activeSubControls = d->hoverControl; | |
} | |
if (d->menuButtonDown) { | |
option->state |= QStyle::State_Sunken; | |
option->activeSubControls |= QStyle::SC_ToolButtonMenu; | |
} | |
if (d->down) { | |
option->state |= QStyle::State_Sunken; | |
option->activeSubControls |= QStyle::SC_ToolButton; | |
} | |
if (d->arrowType != Qt::NoArrow) | |
option->features |= QStyleOptionToolButton::Arrow; | |
if (d->popupMode == QToolButton::DelayedPopup) | |
option->features |= QStyleOptionToolButton::PopupDelay; | |
#ifndef QT_NO_MENU | |
if (d->hasMenu()) | |
option->features |= QStyleOptionToolButton::HasMenu; | |
#endif | |
if (d->toolButtonStyle == Qt::ToolButtonFollowStyle) { | |
option->toolButtonStyle = Qt::ToolButtonStyle(style()->styleHint(QStyle::SH_ToolButtonStyle, option, this)); | |
} else | |
option->toolButtonStyle = d->toolButtonStyle; | |
if (option->toolButtonStyle == Qt::ToolButtonTextBesideIcon) { | |
// If the action is not prioritized, remove the text label to save space | |
if (d->defaultAction && d->defaultAction->priority() < QAction::NormalPriority) | |
option->toolButtonStyle = Qt::ToolButtonIconOnly; | |
} | |
if (d->icon.isNull() && d->arrowType == Qt::NoArrow && !forceNoText) { | |
if (!d->text.isEmpty()) | |
option->toolButtonStyle = Qt::ToolButtonTextOnly; | |
else if (option->toolButtonStyle != Qt::ToolButtonTextOnly) | |
option->toolButtonStyle = Qt::ToolButtonIconOnly; | |
} else { | |
if (d->text.isEmpty() && option->toolButtonStyle != Qt::ToolButtonIconOnly) | |
option->toolButtonStyle = Qt::ToolButtonIconOnly; | |
} | |
option->pos = pos(); | |
option->font = font(); | |
} | |
/*! | |
Destroys the object and frees any allocated resources. | |
*/ | |
QToolButton::~QToolButton() | |
{ | |
} | |
/*! | |
\reimp | |
*/ | |
QSize QToolButton::sizeHint() const | |
{ | |
Q_D(const QToolButton); | |
if (d->sizeHint.isValid()) | |
return d->sizeHint; | |
ensurePolished(); | |
int w = 0, h = 0; | |
QStyleOptionToolButton opt; | |
initStyleOption(&opt); | |
QFontMetrics fm = fontMetrics(); | |
if (opt.toolButtonStyle != Qt::ToolButtonTextOnly) { | |
QSize icon = opt.iconSize; | |
w = icon.width(); | |
h = icon.height(); | |
} | |
if (opt.toolButtonStyle != Qt::ToolButtonIconOnly) { | |
QSize textSize = fm.size(Qt::TextShowMnemonic, text()); | |
textSize.setWidth(textSize.width() + fm.width(QLatin1Char(' '))*2); | |
if (opt.toolButtonStyle == Qt::ToolButtonTextUnderIcon) { | |
h += 4 + textSize.height(); | |
if (textSize.width() > w) | |
w = textSize.width(); | |
} else if (opt.toolButtonStyle == Qt::ToolButtonTextBesideIcon) { | |
w += 4 + textSize.width(); | |
if (textSize.height() > h) | |
h = textSize.height(); | |
} else { // TextOnly | |
w = textSize.width(); | |
h = textSize.height(); | |
} | |
} | |
opt.rect.setSize(QSize(w, h)); // PM_MenuButtonIndicator depends on the height | |
if (d->popupMode == MenuButtonPopup) | |
w += style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &opt, this); | |
d->sizeHint = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, QSize(w, h), this). | |
expandedTo(QApplication::globalStrut()); | |
return d->sizeHint; | |
} | |
/*! | |
\reimp | |
*/ | |
QSize QToolButton::minimumSizeHint() const | |
{ | |
return sizeHint(); | |
} | |
/*! | |
\enum QToolButton::TextPosition | |
\compat | |
This enum describes the position of the tool button's text label in | |
relation to the tool button's icon. | |
\value BesideIcon The text appears beside the icon. | |
\value BelowIcon The text appears below the icon. | |
\omitvalue Right | |
\omitvalue Under | |
*/ | |
/*! | |
\property QToolButton::toolButtonStyle | |
\brief whether the tool button displays an icon only, text only, | |
or text beside/below the icon. | |
The default is Qt::ToolButtonIconOnly. | |
To have the style of toolbuttons follow the system settings (as available | |
in GNOME and KDE desktop environments), set this property to Qt::ToolButtonFollowStyle. | |
QToolButton automatically connects this slot to the relevant | |
signal in the QMainWindow in which is resides. | |
*/ | |
/*! | |
\property QToolButton::arrowType | |
\brief whether the button displays an arrow instead of a normal icon | |
This displays an arrow as the icon for the QToolButton. | |
By default, this property is set to Qt::NoArrow. | |
*/ | |
Qt::ToolButtonStyle QToolButton::toolButtonStyle() const | |
{ | |
Q_D(const QToolButton); | |
return d->toolButtonStyle; | |
} | |
Qt::ArrowType QToolButton::arrowType() const | |
{ | |
Q_D(const QToolButton); | |
return d->arrowType; | |
} | |
void QToolButton::setToolButtonStyle(Qt::ToolButtonStyle style) | |
{ | |
Q_D(QToolButton); | |
if (d->toolButtonStyle == style) | |
return; | |
d->toolButtonStyle = style; | |
d->sizeHint = QSize(); | |
updateGeometry(); | |
if (isVisible()) { | |
update(); | |
} | |
} | |
void QToolButton::setArrowType(Qt::ArrowType type) | |
{ | |
Q_D(QToolButton); | |
if (d->arrowType == type) | |
return; | |
d->arrowType = type; | |
d->sizeHint = QSize(); | |
updateGeometry(); | |
if (isVisible()) { | |
update(); | |
} | |
} | |
/*! | |
\fn void QToolButton::paintEvent(QPaintEvent *event) | |
Paints the button in response to the paint \a event. | |
*/ | |
void QToolButton::paintEvent(QPaintEvent *) | |
{ | |
QStylePainter p(this); | |
QStyleOptionToolButton opt; | |
initStyleOption(&opt); | |
p.drawComplexControl(QStyle::CC_ToolButton, opt); | |
} | |
/*! | |
\reimp | |
*/ | |
void QToolButton::actionEvent(QActionEvent *event) | |
{ | |
Q_D(QToolButton); | |
QAction *action = event->action(); | |
switch (event->type()) { | |
case QEvent::ActionChanged: | |
if (action == d->defaultAction) | |
setDefaultAction(action); // update button state | |
break; | |
case QEvent::ActionAdded: | |
connect(action, SIGNAL(triggered()), this, SLOT(_q_actionTriggered())); | |
break; | |
case QEvent::ActionRemoved: | |
if (d->defaultAction == action) | |
d->defaultAction = 0; | |
#ifndef QT_NO_MENU | |
if (action == d->menuAction) | |
d->menuAction = 0; | |
#endif | |
action->disconnect(this); | |
break; | |
default: | |
; | |
} | |
QAbstractButton::actionEvent(event); | |
} | |
QStyle::SubControl QToolButtonPrivate::newHoverControl(const QPoint &pos) | |
{ | |
Q_Q(QToolButton); | |
QStyleOptionToolButton opt; | |
q->initStyleOption(&opt); | |
opt.subControls = QStyle::SC_All; | |
hoverControl = q->style()->hitTestComplexControl(QStyle::CC_ToolButton, &opt, pos, q); | |
if (hoverControl == QStyle::SC_None) | |
hoverRect = QRect(); | |
else | |
hoverRect = q->style()->subControlRect(QStyle::CC_ToolButton, &opt, hoverControl, q); | |
return hoverControl; | |
} | |
bool QToolButtonPrivate::updateHoverControl(const QPoint &pos) | |
{ | |
Q_Q(QToolButton); | |
QRect lastHoverRect = hoverRect; | |
QStyle::SubControl lastHoverControl = hoverControl; | |
bool doesHover = q->testAttribute(Qt::WA_Hover); | |
if (lastHoverControl != newHoverControl(pos) && doesHover) { | |
q->update(lastHoverRect); | |
q->update(hoverRect); | |
return true; | |
} | |
return !doesHover; | |
} | |
void QToolButtonPrivate::_q_actionTriggered() | |
{ | |
Q_Q(QToolButton); | |
if (QAction *action = qobject_cast<QAction *>(q->sender())) | |
emit q->triggered(action); | |
} | |
/*! | |
\reimp | |
*/ | |
void QToolButton::enterEvent(QEvent * e) | |
{ | |
Q_D(QToolButton); | |
if (d->autoRaise) | |
update(); | |
if (d->defaultAction) | |
d->defaultAction->hover(); | |
QAbstractButton::enterEvent(e); | |
} | |
/*! | |
\reimp | |
*/ | |
void QToolButton::leaveEvent(QEvent * e) | |
{ | |
Q_D(QToolButton); | |
if (d->autoRaise) | |
update(); | |
QAbstractButton::leaveEvent(e); | |
} | |
/*! | |
\reimp | |
*/ | |
void QToolButton::timerEvent(QTimerEvent *e) | |
{ | |
#ifndef QT_NO_MENU | |
Q_D(QToolButton); | |
if (e->timerId() == d->popupTimer.timerId()) { | |
d->popupTimerDone(); | |
return; | |
} | |
#endif | |
QAbstractButton::timerEvent(e); | |
} | |
/*! | |
\reimp | |
*/ | |
void QToolButton::changeEvent(QEvent *e) | |
{ | |
#ifndef QT_NO_TOOLBAR | |
Q_D(QToolButton); | |
if (e->type() == QEvent::ParentChange) { | |
if (qobject_cast<QToolBar*>(parentWidget())) | |
d->autoRaise = true; | |
} else if (e->type() == QEvent::StyleChange | |
#ifdef Q_WS_MAC | |
|| e->type() == QEvent::MacSizeChange | |
#endif | |
) { | |
#ifdef QT3_SUPPORT | |
if (!d->userDefinedPopupDelay) | |
#endif | |
d->delay = style()->styleHint(QStyle::SH_ToolButton_PopupDelay, 0, this); | |
d->setLayoutItemMargins(QStyle::SE_ToolButtonLayoutItem); | |
} | |
#endif | |
QAbstractButton::changeEvent(e); | |
} | |
/*! | |
\reimp | |
*/ | |
void QToolButton::mousePressEvent(QMouseEvent *e) | |
{ | |
Q_D(QToolButton); | |
#ifndef QT_NO_MENU | |
QStyleOptionToolButton opt; | |
initStyleOption(&opt); | |
if (e->button() == Qt::LeftButton && (d->popupMode == MenuButtonPopup)) { | |
QRect popupr = style()->subControlRect(QStyle::CC_ToolButton, &opt, | |
QStyle::SC_ToolButtonMenu, this); | |
if (popupr.isValid() && popupr.contains(e->pos())) { | |
d->buttonPressed = QToolButtonPrivate::MenuButtonPressed; | |
showMenu(); | |
return; | |
} | |
} | |
#endif | |
d->buttonPressed = QToolButtonPrivate::ToolButtonPressed; | |
QAbstractButton::mousePressEvent(e); | |
} | |
/*! | |
\reimp | |
*/ | |
void QToolButton::mouseReleaseEvent(QMouseEvent *e) | |
{ | |
Q_D(QToolButton); | |
QAbstractButton::mouseReleaseEvent(e); | |
d->buttonPressed = QToolButtonPrivate::NoButtonPressed; | |
} | |
/*! | |
\reimp | |
*/ | |
bool QToolButton::hitButton(const QPoint &pos) const | |
{ | |
Q_D(const QToolButton); | |
if(QAbstractButton::hitButton(pos)) | |
return (d->buttonPressed != QToolButtonPrivate::MenuButtonPressed); | |
return false; | |
} | |
#ifdef QT3_SUPPORT | |
/*! | |
Use icon() instead. | |
*/ | |
QIcon QToolButton::onIconSet() const | |
{ | |
return icon(); | |
} | |
/*! | |
Use icon() instead. | |
*/ | |
QIcon QToolButton::offIconSet() const | |
{ | |
return icon(); | |
} | |
/*! | |
\obsolete | |
Use setIcon() instead. | |
*/ | |
void QToolButton::setOnIconSet(const QIcon& set) | |
{ | |
setIcon(set); | |
} | |
/*! | |
\obsolete | |
Use setIcon() instead. | |
*/ | |
void QToolButton::setOffIconSet(const QIcon& set) | |
{ | |
setIcon(set); | |
} | |
/*! \overload | |
\obsolete | |
Since Qt 3.0, QIcon contains both the On and Off icons. | |
For ease of porting, this function ignores the \a on parameter and | |
sets the \l{QAbstractButton::icon} {icon} property. If you relied on | |
the \a on parameter, you probably want to update your code to use | |
the QIcon On/Off mechanism. | |
\sa icon QIcon::State | |
*/ | |
void QToolButton::setIconSet(const QIcon & set, bool /* on */) | |
{ | |
QAbstractButton::setIcon(set); | |
} | |
/*! \overload | |
\obsolete | |
Since Qt 3.0, QIcon contains both the On and Off icons. | |
For ease of porting, this function ignores the \a on parameter and | |
returns the \l{QAbstractButton::icon} {icon} property. If you relied | |
on the \a on parameter, you probably want to update your code to use | |
the QIcon On/Off mechanism. | |
*/ | |
QIcon QToolButton::iconSet(bool /* on */) const | |
{ | |
return QAbstractButton::icon(); | |
} | |
#endif | |
#ifndef QT_NO_MENU | |
/*! | |
Associates the given \a menu with this tool button. | |
The menu will be shown according to the button's \l popupMode. | |
Ownership of the menu is not transferred to the tool button. | |
\sa menu() | |
*/ | |
void QToolButton::setMenu(QMenu* menu) | |
{ | |
Q_D(QToolButton); | |
if (d->menuAction) | |
removeAction(d->menuAction); | |
if (menu) { | |
d->menuAction = menu->menuAction(); | |
addAction(d->menuAction); | |
} else { | |
d->menuAction = 0; | |
} | |
update(); | |
} | |
/*! | |
Returns the associated menu, or 0 if no menu has been defined. | |
\sa setMenu() | |
*/ | |
QMenu* QToolButton::menu() const | |
{ | |
Q_D(const QToolButton); | |
if (d->menuAction) | |
return d->menuAction->menu(); | |
return 0; | |
} | |
/*! | |
Shows (pops up) the associated popup menu. If there is no such | |
menu, this function does nothing. This function does not return | |
until the popup menu has been closed by the user. | |
*/ | |
void QToolButton::showMenu() | |
{ | |
Q_D(QToolButton); | |
if (!d->hasMenu()) { | |
d->menuButtonDown = false; | |
return; // no menu to show | |
} | |
d->menuButtonDown = true; | |
repaint(); | |
d->popupTimer.stop(); | |
d->popupTimerDone(); | |
} | |
void QToolButtonPrivate::_q_buttonPressed() | |
{ | |
Q_Q(QToolButton); | |
if (!hasMenu()) | |
return; // no menu to show | |
if (popupMode == QToolButton::MenuButtonPopup) | |
return; | |
else if (delay > 0 && !popupTimer.isActive() && popupMode == QToolButton::DelayedPopup) | |
popupTimer.start(delay, q); | |
else if (delay == 0 || popupMode == QToolButton::InstantPopup) | |
q->showMenu(); | |
} | |
void QToolButtonPrivate::popupTimerDone() | |
{ | |
Q_Q(QToolButton); | |
popupTimer.stop(); | |
if (!menuButtonDown && !down) | |
return; | |
menuButtonDown = true; | |
QPointer<QMenu> actualMenu; | |
bool mustDeleteActualMenu = false; | |
if(menuAction) { | |
actualMenu = menuAction->menu(); | |
} else if (defaultAction && defaultAction->menu()) { | |
actualMenu = defaultAction->menu(); | |
} else { | |
actualMenu = new QMenu(q); | |
mustDeleteActualMenu = true; | |
for(int i = 0; i < actions.size(); i++) | |
actualMenu->addAction(actions.at(i)); | |
} | |
repeat = q->autoRepeat(); | |
q->setAutoRepeat(false); | |
bool horizontal = true; | |
#if !defined(QT_NO_TOOLBAR) | |
QToolBar *tb = qobject_cast<QToolBar*>(parent); | |
if (tb && tb->orientation() == Qt::Vertical) | |
horizontal = false; | |
#endif | |
QPoint p; | |
QRect screen = QApplication::desktop()->availableGeometry(q); | |
QSize sh = ((QToolButton*)(QMenu*)actualMenu)->receivers(SIGNAL(aboutToShow()))? QSize() : actualMenu->sizeHint(); | |
QRect rect = q->rect(); | |
if (horizontal) { | |
if (q->isRightToLeft()) { | |
if (q->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height()) { | |
p = q->mapToGlobal(rect.bottomRight()); | |
} else { | |
p = q->mapToGlobal(rect.topRight() - QPoint(0, sh.height())); | |
} | |
p.rx() -= sh.width(); | |
} else { | |
if (q->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height()) { | |
p = q->mapToGlobal(rect.bottomLeft()); | |
} else { | |
p = q->mapToGlobal(rect.topLeft() - QPoint(0, sh.height())); | |
} | |
} | |
} else { | |
if (q->isRightToLeft()) { | |
if (q->mapToGlobal(QPoint(rect.left(), 0)).x() - sh.width() <= screen.x()) { | |
p = q->mapToGlobal(rect.topRight()); | |
} else { | |
p = q->mapToGlobal(rect.topLeft()); | |
p.rx() -= sh.width(); | |
} | |
} else { | |
if (q->mapToGlobal(QPoint(rect.right(), 0)).x() + sh.width() <= screen.right()) { | |
p = q->mapToGlobal(rect.topRight()); | |
} else { | |
p = q->mapToGlobal(rect.topLeft() - QPoint(sh.width(), 0)); | |
} | |
} | |
} | |
p.rx() = qMax(screen.left(), qMin(p.x(), screen.right() - sh.width())); | |
p.ry() += 1; | |
QPointer<QToolButton> that = q; | |
actualMenu->setNoReplayFor(q); | |
if (!mustDeleteActualMenu) //only if action are not in this widget | |
QObject::connect(actualMenu, SIGNAL(triggered(QAction*)), q, SLOT(_q_menuTriggered(QAction*))); | |
QObject::connect(actualMenu, SIGNAL(aboutToHide()), q, SLOT(_q_updateButtonDown())); | |
actualMenu->d_func()->causedPopup.widget = q; | |
actualMenu->d_func()->causedPopup.action = defaultAction; | |
actionsCopy = q->actions(); //(the list of action may be modified in slots) | |
actualMenu->exec(p); | |
QObject::disconnect(actualMenu, SIGNAL(aboutToHide()), q, SLOT(_q_updateButtonDown())); | |
if (mustDeleteActualMenu) | |
delete actualMenu; | |
else | |
QObject::disconnect(actualMenu, SIGNAL(triggered(QAction*)), q, SLOT(_q_menuTriggered(QAction*))); | |
if (!that) | |
return; | |
actionsCopy.clear(); | |
if (repeat) | |
q->setAutoRepeat(true); | |
} | |
void QToolButtonPrivate::_q_updateButtonDown() | |
{ | |
Q_Q(QToolButton); | |
menuButtonDown = false; | |
if (q->isDown()) | |
q->setDown(false); | |
else | |
q->repaint(); | |
} | |
void QToolButtonPrivate::_q_menuTriggered(QAction *action) | |
{ | |
Q_Q(QToolButton); | |
if (action && !actionsCopy.contains(action)) | |
emit q->triggered(action); | |
} | |
#endif // QT_NO_MENU | |
#ifdef QT3_SUPPORT | |
/*! | |
\fn void QToolButton::setPopupDelay(int delay) | |
Use the style hint QStyle::SH_ToolButton_PopupDelay instead. | |
*/ | |
void QToolButton::setPopupDelay(int delay) | |
{ | |
Q_D(QToolButton); | |
d->userDefinedPopupDelay = true; | |
d->delay = delay; | |
update(); | |
} | |
/*! | |
Use the style hint QStyle::SH_ToolButton_PopupDelay instead. | |
*/ | |
int QToolButton::popupDelay() const | |
{ | |
Q_D(const QToolButton); | |
return d->delay; | |
} | |
#endif | |
#ifndef QT_NO_MENU | |
/*! \enum QToolButton::ToolButtonPopupMode | |
Describes how a menu should be popped up for tool buttons that has | |
a menu set or contains a list of actions. | |
\value DelayedPopup After pressing and holding the tool button | |
down for a certain amount of time (the timeout is style dependant, | |
see QStyle::SH_ToolButton_PopupDelay), the menu is displayed. A | |
typical application example is the "back" button in some web | |
browsers's tool bars. If the user clicks it, the browser simply | |
browses back to the previous page. If the user presses and holds | |
the button down for a while, the tool button shows a menu | |
containing the current history list | |
\value MenuButtonPopup In this mode the tool button displays a | |
special arrow to indicate that a menu is present. The menu is | |
displayed when the arrow part of the button is pressed. | |
\value InstantPopup The menu is displayed, without delay, when | |
the tool button is pressed. In this mode, the button's own action | |
is not triggered. | |
*/ | |
/*! | |
\property QToolButton::popupMode | |
\brief describes the way that popup menus are used with tool buttons | |
By default, this property is set to \l DelayedPopup. | |
*/ | |
void QToolButton::setPopupMode(ToolButtonPopupMode mode) | |
{ | |
Q_D(QToolButton); | |
d->popupMode = mode; | |
} | |
QToolButton::ToolButtonPopupMode QToolButton::popupMode() const | |
{ | |
Q_D(const QToolButton); | |
return d->popupMode; | |
} | |
#endif | |
/*! | |
\property QToolButton::autoRaise | |
\brief whether auto-raising is enabled or not. | |
The default is disabled (i.e. false). | |
This property is currently ignored on Mac OS X when using QMacStyle. | |
*/ | |
void QToolButton::setAutoRaise(bool enable) | |
{ | |
Q_D(QToolButton); | |
d->autoRaise = enable; | |
update(); | |
} | |
bool QToolButton::autoRaise() const | |
{ | |
Q_D(const QToolButton); | |
return d->autoRaise; | |
} | |
/*! | |
Sets the default action to \a action. | |
If a tool button has a default action, the action defines the | |
button's properties like text, icon, tool tip, etc. | |
*/ | |
void QToolButton::setDefaultAction(QAction *action) | |
{ | |
Q_D(QToolButton); | |
#ifndef QT_NO_MENU | |
bool hadMenu = false; | |
hadMenu = d->hasMenu(); | |
#endif | |
d->defaultAction = action; | |
if (!action) | |
return; | |
if (!actions().contains(action)) | |
addAction(action); | |
setText(action->iconText()); | |
setIcon(action->icon()); | |
#ifndef QT_NO_TOOLTIP | |
setToolTip(action->toolTip()); | |
#endif | |
#ifndef QT_NO_STATUSTIP | |
setStatusTip(action->statusTip()); | |
#endif | |
#ifndef QT_NO_WHATSTHIS | |
setWhatsThis(action->whatsThis()); | |
#endif | |
#ifndef QT_NO_MENU | |
if (action->menu() && !hadMenu) { | |
// new 'default' popup mode defined introduced by tool bar. We | |
// should have changed QToolButton's default instead. Do that | |
// in 4.2. | |
setPopupMode(QToolButton::MenuButtonPopup); | |
} | |
#endif | |
setCheckable(action->isCheckable()); | |
setChecked(action->isChecked()); | |
setEnabled(action->isEnabled()); | |
if (action->d_func()->fontSet) | |
setFont(action->font()); | |
} | |
/*! | |
Returns the default action. | |
\sa setDefaultAction() | |
*/ | |
QAction *QToolButton::defaultAction() const | |
{ | |
Q_D(const QToolButton); | |
return d->defaultAction; | |
} | |
/*! | |
\reimp | |
*/ | |
void QToolButton::nextCheckState() | |
{ | |
Q_D(QToolButton); | |
if (!d->defaultAction) | |
QAbstractButton::nextCheckState(); | |
else | |
d->defaultAction->trigger(); | |
} | |
/*! \reimp */ | |
bool QToolButton::event(QEvent *event) | |
{ | |
switch(event->type()) { | |
case QEvent::HoverEnter: | |
case QEvent::HoverLeave: | |
case QEvent::HoverMove: | |
if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event)) | |
d_func()->updateHoverControl(he->pos()); | |
break; | |
default: | |
break; | |
} | |
return QAbstractButton::event(event); | |
} | |
/*! \internal | |
*/ | |
QToolButton::QToolButton(QToolButtonPrivate &dd, QWidget *parent) | |
:QAbstractButton(dd, parent) | |
{ | |
Q_D(QToolButton); | |
d->init(); | |
} | |
/*! | |
\fn void QToolButton::setPixmap(const QPixmap &pixmap) | |
Use setIcon(QIcon(pixmap)) instead. | |
*/ | |
/*! | |
\fn void QToolButton::setIconSet(const QIcon &icon) | |
Use setIcon() instead. | |
*/ | |
/*! | |
\fn void QToolButton::setTextLabel(const QString &text, bool tooltip) | |
Use setText() and setToolTip() instead. | |
*/ | |
/*! | |
\fn QString QToolButton::textLabel() const | |
Use text() instead. | |
*/ | |
/*! | |
\fn QIcon QToolButton::iconSet() const | |
Use icon() instead. | |
*/ | |
/*! | |
\fn void QToolButton::openPopup() | |
Use showMenu() instead. | |
*/ | |
/*! | |
\fn void QToolButton::setPopup(QMenu* popup) | |
Use setMenu() instead. | |
*/ | |
/*! | |
\fn QMenu* QToolButton::popup() const | |
Use menu() instead. | |
*/ | |
/*! | |
\fn TextPosition QToolButton::textPosition() const | |
Use toolButtonStyle() instead. | |
*/ | |
/*! | |
\fn void QToolButton::setTextPosition(QToolButton::TextPosition pos) | |
Use setToolButtonStyle() instead. | |
*/ | |
/*! | |
\fn bool QToolButton::usesBigPixmap() const | |
Use iconSize() instead. | |
*/ | |
/*! | |
\fn void QToolButton::setUsesBigPixmap(bool enable) | |
Use setIconSize() instead. | |
*/ | |
/*! | |
\fn bool QToolButton::usesTextLabel() const | |
Use toolButtonStyle() instead. | |
*/ | |
/*! | |
\fn void QToolButton::setUsesTextLabel(bool enable) | |
Use setToolButtonStyle() instead. | |
*/ | |
QT_END_NAMESPACE | |
#include "moc_qtoolbutton.cpp" | |
#endif |