qabstractbutton.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/widgets/widgets/qabstractbutton.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtWidgets module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "private/qabstractbutton_p.h"-
41-
42#include "private/qbuttongroup_p.h"-
43#include "qabstractitemview.h"-
44#include "qbuttongroup.h"-
45#include "qabstractbutton_p.h"-
46#include "qevent.h"-
47#include "qpainter.h"-
48#include "qapplication.h"-
49#include "qstyle.h"-
50#include "qaction.h"-
51#ifndef QT_NO_ACCESSIBILITY-
52#include "qaccessible.h"-
53#endif-
54-
55#include <algorithm>-
56-
57QT_BEGIN_NAMESPACE-
58-
59#define AUTO_REPEAT_DELAY 300-
60#define AUTO_REPEAT_INTERVAL 100-
61-
62Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets();-
63-
64/*!-
65 \class QAbstractButton-
66-
67 \brief The QAbstractButton class is the abstract base class of-
68 button widgets, providing functionality common to buttons.-
69-
70 \ingroup abstractwidgets-
71 \inmodule QtWidgets-
72-
73 This class implements an \e abstract button.-
74 Subclasses of this class handle user actions, and specify how the button-
75 is drawn.-
76-
77 QAbstractButton provides support for both push buttons and checkable-
78 (toggle) buttons. Checkable buttons are implemented in the QRadioButton-
79 and QCheckBox classes. Push buttons are implemented in the-
80 QPushButton and QToolButton classes; these also provide toggle-
81 behavior if required.-
82-
83 Any button can display a label containing text and an icon. setText()-
84 sets the text; setIcon() sets the icon. If a button is disabled, its label-
85 is changed to give the button a "disabled" appearance.-
86-
87 If the button is a text button with a string containing an-
88 ampersand ('&'), QAbstractButton automatically creates a shortcut-
89 key. For example:-
90-
91 \snippet code/src_gui_widgets_qabstractbutton.cpp 0-
92-
93 The \uicontrol Alt+C shortcut is assigned to the button, i.e., when the-
94 user presses \uicontrol Alt+C the button will call animateClick(). See-
95 the \l {QShortcut#mnemonic}{QShortcut} documentation for details. To-
96 display an actual ampersand, use '&&'.-
97-
98 You can also set a custom shortcut key using the setShortcut()-
99 function. This is useful mostly for buttons that do not have any-
100 text, and therefore can't have any automatic shortcut.-
101-
102 \snippet code/src_gui_widgets_qabstractbutton.cpp 1-
103-
104 All the buttons provided by Qt (QPushButton, QToolButton,-
105 QCheckBox, and QRadioButton) can display both \l text and \l{icon}{icons}.-
106-
107 A button can be made the default button in a dialog by means of-
108 QPushButton::setDefault() and QPushButton::setAutoDefault().-
109-
110 QAbstractButton provides most of the states used for buttons:-
111-
112 \list-
113-
114 \li isDown() indicates whether the button is \e pressed down.-
115-
116 \li isChecked() indicates whether the button is \e checked. Only-
117 checkable buttons can be checked and unchecked (see below).-
118-
119 \li isEnabled() indicates whether the button can be pressed by the-
120 user. \note As opposed to other widgets, buttons derived from-
121 QAbstractButton accept mouse and context menu events-
122 when disabled.-
123-
124 \li setAutoRepeat() sets whether the button will auto-repeat if the-
125 user holds it down. \l autoRepeatDelay and \l autoRepeatInterval-
126 define how auto-repetition is done.-
127-
128 \li setCheckable() sets whether the button is a toggle button or not.-
129-
130 \endlist-
131-
132 The difference between isDown() and isChecked() is as follows.-
133 When the user clicks a toggle button to check it, the button is first-
134 \e pressed then released into the \e checked state. When the user-
135 clicks it again (to uncheck it), the button moves first to the-
136 \e pressed state, then to the \e unchecked state (isChecked() and-
137 isDown() are both false).-
138-
139 QAbstractButton provides four signals:-
140-
141 \list 1-
142-
143 \li pressed() is emitted when the left mouse button is pressed while-
144 the mouse cursor is inside the button.-
145-
146 \li released() is emitted when the left mouse button is released.-
147-
148 \li clicked() is emitted when the button is first pressed and then-
149 released, when the shortcut key is typed, or when click() or-
150 animateClick() is called.-
151-
152 \li toggled() is emitted when the state of a toggle button changes.-
153-
154 \endlist-
155-
156 To subclass QAbstractButton, you must reimplement at least-
157 paintEvent() to draw the button's outline and its text or pixmap. It-
158 is generally advisable to reimplement sizeHint() as well, and-
159 sometimes hitButton() (to determine whether a button press is within-
160 the button). For buttons with more than two states (like tri-state-
161 buttons), you will also have to reimplement checkStateSet() and-
162 nextCheckState().-
163-
164 \sa QButtonGroup-
165*/-
166-
167QAbstractButtonPrivate::QAbstractButtonPrivate(QSizePolicy::ControlType type)-
168 :-
169#ifndef QT_NO_SHORTCUT-
170 shortcutId(0),-
171#endif-
172 checkable(false), checked(false), autoRepeat(false), autoExclusive(false),-
173 down(false), blockRefresh(false), pressed(false),-
174#ifndef QT_NO_BUTTONGROUP-
175 group(0),-
176#endif-
177 autoRepeatDelay(AUTO_REPEAT_DELAY),-
178 autoRepeatInterval(AUTO_REPEAT_INTERVAL),-
179 controlType(type)-
180{}-
181-
182QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const-
183{-
184#ifndef QT_NO_BUTTONGROUP-
185 if (group)
groupDescription
TRUEnever evaluated
FALSEnever evaluated
0
186 return group->d_func()->buttonList;
never executed: return group->d_func()->buttonList;
0
187#endif-
188-
189 QList<QAbstractButton*>candidates = parent->findChildren<QAbstractButton *>();-
190 if (autoExclusive) {
autoExclusiveDescription
TRUEnever evaluated
FALSEnever evaluated
0
191 for (int iauto isNoMemberOfMyAutoExclusiveGroup = candidates.count() - 1; i >= 0; --i) {[](QAbstractButton *candidate= candidates.at(i);-
if (!) {
192 return !
never executed: return !candidate->autoExclusive() || candidate->group() ;
candidate->autoExclusive()
never executed: return !candidate->autoExclusive() || candidate->group() ;
0
193#ifndef QT_NO_BUTTONGROUP
never executed: return !candidate->autoExclusive() || candidate->group() ;
0
194 || candidate->group()
never executed: return !candidate->autoExclusive() || candidate->group() ;
0
195#endif
never executed: return !candidate->autoExclusive() || candidate->group() ;
0
196 );
never executed: return !candidate->autoExclusive() || candidate->group() ;
0
197 };-
198 candidates.removeAterase(i);-
}std::remove_if(candidates.begin(), candidates.end(),
199 isNoMemberOfMyAutoExclusiveGroup),-
200 candidates.end());-
201 }
never executed: end of block
0
202 return candidates;
never executed: return candidates;
0
203}-
204-
205QAbstractButton *QAbstractButtonPrivate::queryCheckedButton() const-
206{-
207#ifndef QT_NO_BUTTONGROUP-
208 if (group)-
209 return group->d_func()->checkedButton;-
210#endif-
211-
212 Q_Q(const QAbstractButton);-
213 QList<QAbstractButton *> buttonList = queryButtonList();-
214 if (!autoExclusive || buttonList.count() == 1) // no group-
215 return 0;-
216-
217 for (int i = 0; i < buttonList.count(); ++i) {-
218 QAbstractButton *b = buttonList.at(i);-
219 if (b->d_func()->checked && b != q)-
220 return b;-
221 }-
222 return checked ? const_cast<QAbstractButton *>(q) : 0;-
223}-
224-
225void QAbstractButtonPrivate::notifyChecked()-
226{-
227#ifndef QT_NO_BUTTONGROUP-
228 Q_Q(QAbstractButton);-
229 if (group) {-
230 QAbstractButton *previous = group->d_func()->checkedButton;-
231 group->d_func()->checkedButton = q;-
232 if (group->d_func()->exclusive && previous && previous != q)-
233 previous->nextCheckState();-
234 } else-
235#endif-
236 if (autoExclusive) {-
237 if (QAbstractButton *b = queryCheckedButton())-
238 b->setChecked(false);-
239 }-
240}-
241-
242void QAbstractButtonPrivate::moveFocus(int key)-
243{-
244 QList<QAbstractButton *> buttonList = queryButtonList();;-
245#ifndef QT_NO_BUTTONGROUP-
246 bool exclusive = group ? group->d_func()->exclusive : autoExclusive;-
247#else-
248 bool exclusive = autoExclusive;-
249#endif-
250 QWidget *f = QApplication::focusWidget();-
251 QAbstractButton *fb = qobject_cast<QAbstractButton *>(f);-
252 if (!fb || !buttonList.contains(fb))-
253 return;-
254-
255 QAbstractButton *candidate = 0;-
256 int bestScore = -1;-
257 QRect target = f->rect().translated(f->mapToGlobal(QPoint(0,0)));-
258 QPoint goal = target.center();-
259 uint focus_flag = qt_tab_all_widgets() ? Qt::TabFocus : Qt::StrongFocus;-
260-
261 for (int i = 0; i < buttonList.count(); ++i) {-
262 QAbstractButton *button = buttonList.at(i);-
263 if (button != f && button->window() == f->window() && button->isEnabled() && !button->isHidden() &&-
264 (autoExclusive || (button->focusPolicy() & focus_flag) == focus_flag)) {-
265 QRect buttonRect = button->rect().translated(button->mapToGlobal(QPoint(0,0)));-
266 QPoint p = buttonRect.center();-
267-
268 //Priority to widgets that overlap on the same coordinate.-
269 //In that case, the distance in the direction will be used as significant score,-
270 //take also in account orthogonal distance in case two widget are in the same distance.-
271 int score;-
272 if ((buttonRect.x() < target.right() && target.x() < buttonRect.right())-
273 && (key == Qt::Key_Up || key == Qt::Key_Down)) {-
274 //one item's is at the vertical of the other-
275 score = (qAbs(p.y() - goal.y()) << 16) + qAbs(p.x() - goal.x());-
276 } else if ((buttonRect.y() < target.bottom() && target.y() < buttonRect.bottom())-
277 && (key == Qt::Key_Left || key == Qt::Key_Right) ) {-
278 //one item's is at the horizontal of the other-
279 score = (qAbs(p.x() - goal.x()) << 16) + qAbs(p.y() - goal.y());-
280 } else {-
281 score = (1 << 30) + (p.y() - goal.y()) * (p.y() - goal.y()) + (p.x() - goal.x()) * (p.x() - goal.x());-
282 }-
283-
284 if (score > bestScore && candidate)-
285 continue;-
286-
287 switch(key) {-
288 case Qt::Key_Up:-
289 if (p.y() < goal.y()) {-
290 candidate = button;-
291 bestScore = score;-
292 }-
293 break;-
294 case Qt::Key_Down:-
295 if (p.y() > goal.y()) {-
296 candidate = button;-
297 bestScore = score;-
298 }-
299 break;-
300 case Qt::Key_Left:-
301 if (p.x() < goal.x()) {-
302 candidate = button;-
303 bestScore = score;-
304 }-
305 break;-
306 case Qt::Key_Right:-
307 if (p.x() > goal.x()) {-
308 candidate = button;-
309 bestScore = score;-
310 }-
311 break;-
312 }-
313 }-
314 }-
315-
316 if (exclusive-
317#ifdef QT_KEYPAD_NAVIGATION-
318 && !QApplication::keypadNavigationEnabled()-
319#endif-
320 && candidate-
321 && fb->d_func()->checked-
322 && candidate->d_func()->checkable)-
323 candidate->click();-
324-
325 if (candidate) {-
326 if (key == Qt::Key_Up || key == Qt::Key_Left)-
327 candidate->setFocus(Qt::BacktabFocusReason);-
328 else-
329 candidate->setFocus(Qt::TabFocusReason);-
330 }-
331}-
332-
333void QAbstractButtonPrivate::fixFocusPolicy()-
334{-
335 Q_Q(QAbstractButton);-
336#ifndef QT_NO_BUTTONGROUP-
337 if (!group && !autoExclusive)-
338#else-
339 if (!autoExclusive)-
340#endif-
341 return;-
342-
343 QList<QAbstractButton *> buttonList = queryButtonList();-
344 for (int i = 0; i < buttonList.count(); ++i) {-
345 QAbstractButton *b = buttonList.at(i);-
346 if (!b->isCheckable())-
347 continue;-
348 b->setFocusPolicy((Qt::FocusPolicy) ((b == q || !q->isCheckable())-
349 ? (b->focusPolicy() | Qt::TabFocus)-
350 : (b->focusPolicy() & ~Qt::TabFocus)));-
351 }-
352}-
353-
354void QAbstractButtonPrivate::init()-
355{-
356 Q_Q(QAbstractButton);-
357-
358 q->setFocusPolicy(Qt::FocusPolicy(q->style()->styleHint(QStyle::SH_Button_FocusPolicy)));-
359 q->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed, controlType));-
360 q->setAttribute(Qt::WA_WState_OwnSizePolicy, false);-
361 q->setForegroundRole(QPalette::ButtonText);-
362 q->setBackgroundRole(QPalette::Button);-
363}-
364-
365void QAbstractButtonPrivate::refresh()-
366{-
367 Q_Q(QAbstractButton);-
368-
369 if (blockRefresh)-
370 return;-
371 q->update();-
372}-
373-
374void QAbstractButtonPrivate::click()-
375{-
376 Q_Q(QAbstractButton);-
377-
378 down = false;-
379 blockRefresh = true;-
380 bool changeState = true;-
381 if (checked && queryCheckedButton() == q) {-
382 // the checked button of an exclusive or autoexclusive group cannot be unchecked-
383#ifndef QT_NO_BUTTONGROUP-
384 if (group ? group->d_func()->exclusive : autoExclusive)-
385#else-
386 if (autoExclusive)-
387#endif-
388 changeState = false;-
389 }-
390-
391 QPointer<QAbstractButton> guard(q);-
392 if (changeState) {-
393 q->nextCheckState();-
394 if (!guard)-
395 return;-
396 }-
397 blockRefresh = false;-
398 refresh();-
399 q->repaint(); //flush paint event before invoking potentially expensive operation-
400 QApplication::flush();-
401 if (guard)-
402 emitReleased();-
403 if (guard)-
404 emitClicked();-
405}-
406-
407void QAbstractButtonPrivate::emitClicked()-
408{-
409 Q_Q(QAbstractButton);-
410 QPointer<QAbstractButton> guard(q);-
411 emit q->clicked(checked);-
412#ifndef QT_NO_BUTTONGROUP-
413 if (guard && group) {-
414 emit group->buttonClicked(group->id(q));-
415 if (guard && group)-
416 emit group->buttonClicked(q);-
417 }-
418#endif-
419}-
420-
421void QAbstractButtonPrivate::emitPressed()-
422{-
423 Q_Q(QAbstractButton);-
424 QPointer<QAbstractButton> guard(q);-
425 emit q->pressed();-
426#ifndef QT_NO_BUTTONGROUP-
427 if (guard && group) {-
428 emit group->buttonPressed(group->id(q));-
429 if (guard && group)-
430 emit group->buttonPressed(q);-
431 }-
432#endif-
433}-
434-
435void QAbstractButtonPrivate::emitReleased()-
436{-
437 Q_Q(QAbstractButton);-
438 QPointer<QAbstractButton> guard(q);-
439 emit q->released();-
440#ifndef QT_NO_BUTTONGROUP-
441 if (guard && group) {-
442 emit group->buttonReleased(group->id(q));-
443 if (guard && group)-
444 emit group->buttonReleased(q);-
445 }-
446#endif-
447}-
448-
449void QAbstractButtonPrivate::emitToggled(bool checked)-
450{-
451 Q_Q(QAbstractButton);-
452 QPointer<QAbstractButton> guard(q);-
453 emit q->toggled(checked);-
454#ifndef QT_NO_BUTTONGROUP-
455 if (guard && group) {-
456 emit group->buttonToggled(group->id(q), checked);-
457 if (guard && group)-
458 emit group->buttonToggled(q, checked);-
459 }-
460#endif-
461}-
462-
463/*!-
464 Constructs an abstract button with a \a parent.-
465*/-
466QAbstractButton::QAbstractButton(QWidget *parent)-
467 : QWidget(*new QAbstractButtonPrivate, parent, 0)-
468{-
469 Q_D(QAbstractButton);-
470 d->init();-
471}-
472-
473/*!-
474 Destroys the button.-
475 */-
476 QAbstractButton::~QAbstractButton()-
477{-
478#ifndef QT_NO_BUTTONGROUP-
479 Q_D(QAbstractButton);-
480 if (d->group)-
481 d->group->removeButton(this);-
482#endif-
483}-
484-
485-
486/*! \internal-
487 */-
488QAbstractButton::QAbstractButton(QAbstractButtonPrivate &dd, QWidget *parent)-
489 : QWidget(dd, parent, 0)-
490{-
491 Q_D(QAbstractButton);-
492 d->init();-
493}-
494-
495/*!-
496\property QAbstractButton::text-
497\brief the text shown on the button-
498-
499If the button has no text, the text() function will return an empty-
500string.-
501-
502If the text contains an ampersand character ('&'), a shortcut is-
503automatically created for it. The character that follows the '&' will-
504be used as the shortcut key. Any previous shortcut will be-
505overwritten or cleared if no shortcut is defined by the text. See the-
506\l {QShortcut#mnemonic}{QShortcut} documentation for details. To-
507display an actual ampersand, use '&&'.-
508-
509There is no default text.-
510*/-
511-
512void QAbstractButton::setText(const QString &text)-
513{-
514 Q_D(QAbstractButton);-
515 if (d->text == text)-
516 return;-
517 d->text = text;-
518#ifndef QT_NO_SHORTCUT-
519 QKeySequence newMnemonic = QKeySequence::mnemonic(text);-
520 setShortcut(newMnemonic);-
521#endif-
522 d->sizeHint = QSize();-
523 update();-
524 updateGeometry();-
525#ifndef QT_NO_ACCESSIBILITY-
526 QAccessibleEvent event(this, QAccessible::NameChanged);-
527 QAccessible::updateAccessibility(&event);-
528#endif-
529}-
530-
531QString QAbstractButton::text() const-
532{-
533 Q_D(const QAbstractButton);-
534 return d->text;-
535}-
536-
537-
538/*!-
539 \property QAbstractButton::icon-
540 \brief the icon shown on the button-
541-
542 The icon's default size is defined by the GUI style, but can be-
543 adjusted by setting the \l iconSize property.-
544*/-
545void QAbstractButton::setIcon(const QIcon &icon)-
546{-
547 Q_D(QAbstractButton);-
548 d->icon = icon;-
549 d->sizeHint = QSize();-
550 update();-
551 updateGeometry();-
552}-
553-
554QIcon QAbstractButton::icon() const-
555{-
556 Q_D(const QAbstractButton);-
557 return d->icon;-
558}-
559-
560#ifndef QT_NO_SHORTCUT-
561/*!-
562\property QAbstractButton::shortcut-
563\brief the mnemonic associated with the button-
564*/-
565-
566void QAbstractButton::setShortcut(const QKeySequence &key)-
567{-
568 Q_D(QAbstractButton);-
569 if (d->shortcutId != 0)-
570 releaseShortcut(d->shortcutId);-
571 d->shortcut = key;-
572 d->shortcutId = grabShortcut(key);-
573}-
574-
575QKeySequence QAbstractButton::shortcut() const-
576{-
577 Q_D(const QAbstractButton);-
578 return d->shortcut;-
579}-
580#endif // QT_NO_SHORTCUT-
581-
582/*!-
583\property QAbstractButton::checkable-
584\brief whether the button is checkable-
585-
586By default, the button is not checkable.-
587-
588\sa checked-
589*/-
590void QAbstractButton::setCheckable(bool checkable)-
591{-
592 Q_D(QAbstractButton);-
593 if (d->checkable == checkable)-
594 return;-
595-
596 d->checkable = checkable;-
597 d->checked = false;-
598}-
599-
600bool QAbstractButton::isCheckable() const-
601{-
602 Q_D(const QAbstractButton);-
603 return d->checkable;-
604}-
605-
606/*!-
607\property QAbstractButton::checked-
608\brief whether the button is checked-
609-
610Only checkable buttons can be checked. By default, the button is unchecked.-
611-
612\sa checkable-
613*/-
614void QAbstractButton::setChecked(bool checked)-
615{-
616 Q_D(QAbstractButton);-
617 if (!d->checkable || d->checked == checked) {-
618 if (!d->blockRefresh)-
619 checkStateSet();-
620 return;-
621 }-
622-
623 if (!checked && d->queryCheckedButton() == this) {-
624 // the checked button of an exclusive or autoexclusive group cannot be unchecked-
625#ifndef QT_NO_BUTTONGROUP-
626 if (d->group ? d->group->d_func()->exclusive : d->autoExclusive)-
627 return;-
628 if (d->group)-
629 d->group->d_func()->detectCheckedButton();-
630#else-
631 if (d->autoExclusive)-
632 return;-
633#endif-
634 }-
635-
636 QPointer<QAbstractButton> guard(this);-
637-
638 d->checked = checked;-
639 if (!d->blockRefresh)-
640 checkStateSet();-
641 d->refresh();-
642-
643 if (guard && checked)-
644 d->notifyChecked();-
645 if (guard)-
646 d->emitToggled(checked);-
647-
648-
649#ifndef QT_NO_ACCESSIBILITY-
650 QAccessible::State s;-
651 s.checked = true;-
652 QAccessibleStateChangeEvent event(this, s);-
653 QAccessible::updateAccessibility(&event);-
654#endif-
655}-
656-
657bool QAbstractButton::isChecked() const-
658{-
659 Q_D(const QAbstractButton);-
660 return d->checked;-
661}-
662-
663/*!-
664 \property QAbstractButton::down-
665 \brief whether the button is pressed down-
666-
667 If this property is \c true, the button is pressed down. The signals-
668 pressed() and clicked() are not emitted if you set this property-
669 to true. The default is false.-
670*/-
671-
672void QAbstractButton::setDown(bool down)-
673{-
674 Q_D(QAbstractButton);-
675 if (d->down == down)-
676 return;-
677 d->down = down;-
678 d->refresh();-
679 if (d->autoRepeat && d->down)-
680 d->repeatTimer.start(d->autoRepeatDelay, this);-
681 else-
682 d->repeatTimer.stop();-
683}-
684-
685bool QAbstractButton::isDown() const-
686{-
687 Q_D(const QAbstractButton);-
688 return d->down;-
689}-
690-
691/*!-
692\property QAbstractButton::autoRepeat-
693\brief whether autoRepeat is enabled-
694-
695If autoRepeat is enabled, then the pressed(), released(), and clicked() signals are emitted at-
696regular intervals when the button is down. autoRepeat is off by default.-
697The initial delay and the repetition interval are defined in milliseconds by \l-
698autoRepeatDelay and \l autoRepeatInterval.-
699-
700Note: If a button is pressed down by a shortcut key, then auto-repeat is enabled and timed by the-
701system and not by this class. The pressed(), released(), and clicked() signals will be emitted-
702like in the normal case.-
703*/-
704-
705void QAbstractButton::setAutoRepeat(bool autoRepeat)-
706{-
707 Q_D(QAbstractButton);-
708 if (d->autoRepeat == autoRepeat)-
709 return;-
710 d->autoRepeat = autoRepeat;-
711 if (d->autoRepeat && d->down)-
712 d->repeatTimer.start(d->autoRepeatDelay, this);-
713 else-
714 d->repeatTimer.stop();-
715}-
716-
717bool QAbstractButton::autoRepeat() const-
718{-
719 Q_D(const QAbstractButton);-
720 return d->autoRepeat;-
721}-
722-
723/*!-
724 \property QAbstractButton::autoRepeatDelay-
725 \brief the initial delay of auto-repetition-
726 \since 4.2-
727-
728 If \l autoRepeat is enabled, then autoRepeatDelay defines the initial-
729 delay in milliseconds before auto-repetition kicks in.-
730-
731 \sa autoRepeat, autoRepeatInterval-
732*/-
733-
734void QAbstractButton::setAutoRepeatDelay(int autoRepeatDelay)-
735{-
736 Q_D(QAbstractButton);-
737 d->autoRepeatDelay = autoRepeatDelay;-
738}-
739-
740int QAbstractButton::autoRepeatDelay() const-
741{-
742 Q_D(const QAbstractButton);-
743 return d->autoRepeatDelay;-
744}-
745-
746/*!-
747 \property QAbstractButton::autoRepeatInterval-
748 \brief the interval of auto-repetition-
749 \since 4.2-
750-
751 If \l autoRepeat is enabled, then autoRepeatInterval defines the-
752 length of the auto-repetition interval in millisecons.-
753-
754 \sa autoRepeat, autoRepeatDelay-
755*/-
756-
757void QAbstractButton::setAutoRepeatInterval(int autoRepeatInterval)-
758{-
759 Q_D(QAbstractButton);-
760 d->autoRepeatInterval = autoRepeatInterval;-
761}-
762-
763int QAbstractButton::autoRepeatInterval() const-
764{-
765 Q_D(const QAbstractButton);-
766 return d->autoRepeatInterval;-
767}-
768-
769-
770-
771/*!-
772\property QAbstractButton::autoExclusive-
773\brief whether auto-exclusivity is enabled-
774-
775If auto-exclusivity is enabled, checkable buttons that belong to the-
776same parent widget behave as if they were part of the same-
777exclusive button group. In an exclusive button group, only one button-
778can be checked at any time; checking another button automatically-
779unchecks the previously checked one.-
780-
781The property has no effect on buttons that belong to a button-
782group.-
783-
784autoExclusive is off by default, except for radio buttons.-
785-
786\sa QRadioButton-
787*/-
788void QAbstractButton::setAutoExclusive(bool autoExclusive)-
789{-
790 Q_D(QAbstractButton);-
791 d->autoExclusive = autoExclusive;-
792}-
793-
794bool QAbstractButton::autoExclusive() const-
795{-
796 Q_D(const QAbstractButton);-
797 return d->autoExclusive;-
798}-
799-
800#ifndef QT_NO_BUTTONGROUP-
801/*!-
802 Returns the group that this button belongs to.-
803-
804 If the button is not a member of any QButtonGroup, this function-
805 returns 0.-
806-
807 \sa QButtonGroup-
808*/-
809QButtonGroup *QAbstractButton::group() const-
810{-
811 Q_D(const QAbstractButton);-
812 return d->group;-
813}-
814#endif // QT_NO_BUTTONGROUP-
815-
816/*!-
817Performs an animated click: the button is pressed immediately, and-
818released \a msec milliseconds later (the default is 100 ms).-
819-
820Calling this function again before the button is released resets-
821the release timer.-
822-
823All signals associated with a click are emitted as appropriate.-
824-
825This function does nothing if the button is \l{setEnabled()}{disabled.}-
826-
827\sa click()-
828*/-
829void QAbstractButton::animateClick(int msec)-
830{-
831 if (!isEnabled())-
832 return;-
833 Q_D(QAbstractButton);-
834 if (d->checkable && focusPolicy() & Qt::ClickFocus)-
835 setFocus();-
836 setDown(true);-
837 repaint(); //flush paint event before invoking potentially expensive operation-
838 QApplication::flush();-
839 if (!d->animateTimer.isActive())-
840 d->emitPressed();-
841 d->animateTimer.start(msec, this);-
842}-
843-
844/*!-
845Performs a click.-
846-
847All the usual signals associated with a click are emitted as-
848appropriate. If the button is checkable, the state of the button is-
849toggled.-
850-
851This function does nothing if the button is \l{setEnabled()}{disabled.}-
852-
853\sa animateClick()-
854 */-
855void QAbstractButton::click()-
856{-
857 if (!isEnabled())-
858 return;-
859 Q_D(QAbstractButton);-
860 QPointer<QAbstractButton> guard(this);-
861 d->down = true;-
862 d->emitPressed();-
863 if (guard) {-
864 d->down = false;-
865 nextCheckState();-
866 if (guard)-
867 d->emitReleased();-
868 if (guard)-
869 d->emitClicked();-
870 }-
871}-
872-
873/*! \fn void QAbstractButton::toggle()-
874-
875 Toggles the state of a checkable button.-
876-
877 \sa checked-
878*/-
879void QAbstractButton::toggle()-
880{-
881 Q_D(QAbstractButton);-
882 setChecked(!d->checked);-
883}-
884-
885-
886/*! This virtual handler is called when setChecked() is used,-
887unless it is called from within nextCheckState(). It allows-
888subclasses to reset their intermediate button states.-
889-
890\sa nextCheckState()-
891 */-
892void QAbstractButton::checkStateSet()-
893{-
894}-
895-
896/*! This virtual handler is called when a button is clicked. The-
897default implementation calls setChecked(!isChecked()) if the button-
898isCheckable(). It allows subclasses to implement intermediate button-
899states.-
900-
901\sa checkStateSet()-
902*/-
903void QAbstractButton::nextCheckState()-
904{-
905 if (isCheckable())-
906 setChecked(!isChecked());-
907}-
908-
909/*!-
910Returns \c true if \a pos is inside the clickable button rectangle;-
911otherwise returns \c false.-
912-
913By default, the clickable area is the entire widget. Subclasses-
914may reimplement this function to provide support for clickable-
915areas of different shapes and sizes.-
916*/-
917bool QAbstractButton::hitButton(const QPoint &pos) const-
918{-
919 return rect().contains(pos);-
920}-
921-
922/*! \reimp */-
923bool QAbstractButton::event(QEvent *e)-
924{-
925 // as opposed to other widgets, disabled buttons accept mouse-
926 // events. This avoids surprising click-through scenarios-
927 if (!isEnabled()) {-
928 switch(e->type()) {-
929 case QEvent::TabletPress:-
930 case QEvent::TabletRelease:-
931 case QEvent::TabletMove:-
932 case QEvent::MouseButtonPress:-
933 case QEvent::MouseButtonRelease:-
934 case QEvent::MouseButtonDblClick:-
935 case QEvent::MouseMove:-
936 case QEvent::HoverMove:-
937 case QEvent::HoverEnter:-
938 case QEvent::HoverLeave:-
939 case QEvent::ContextMenu:-
940#ifndef QT_NO_WHEELEVENT-
941 case QEvent::Wheel:-
942#endif-
943 return true;-
944 default:-
945 break;-
946 }-
947 }-
948-
949#ifndef QT_NO_SHORTCUT-
950 if (e->type() == QEvent::Shortcut) {-
951 Q_D(QAbstractButton);-
952 QShortcutEvent *se = static_cast<QShortcutEvent *>(e);-
953 if (d->shortcutId != se->shortcutId())-
954 return false;-
955 if (!se->isAmbiguous()) {-
956 if (!d->animateTimer.isActive())-
957 animateClick();-
958 } else {-
959 if (focusPolicy() != Qt::NoFocus)-
960 setFocus(Qt::ShortcutFocusReason);-
961 window()->setAttribute(Qt::WA_KeyboardFocusChange);-
962 }-
963 return true;-
964 }-
965#endif-
966 return QWidget::event(e);-
967}-
968-
969/*! \reimp */-
970void QAbstractButton::mousePressEvent(QMouseEvent *e)-
971{-
972 Q_D(QAbstractButton);-
973 if (e->button() != Qt::LeftButton) {-
974 e->ignore();-
975 return;-
976 }-
977 if (hitButton(e->pos())) {-
978 setDown(true);-
979 d->pressed = true;-
980 repaint(); //flush paint event before invoking potentially expensive operation-
981 QApplication::flush();-
982 d->emitPressed();-
983 e->accept();-
984 } else {-
985 e->ignore();-
986 }-
987}-
988-
989/*! \reimp */-
990void QAbstractButton::mouseReleaseEvent(QMouseEvent *e)-
991{-
992 Q_D(QAbstractButton);-
993 d->pressed = false;-
994-
995 if (e->button() != Qt::LeftButton) {-
996 e->ignore();-
997 return;-
998 }-
999-
1000 if (!d->down) {-
1001 // refresh is required by QMacStyle to resume the default button animation-
1002 d->refresh();-
1003 e->ignore();-
1004 return;-
1005 }-
1006-
1007 if (hitButton(e->pos())) {-
1008 d->repeatTimer.stop();-
1009 d->click();-
1010 e->accept();-
1011 } else {-
1012 setDown(false);-
1013 e->ignore();-
1014 }-
1015}-
1016-
1017/*! \reimp */-
1018void QAbstractButton::mouseMoveEvent(QMouseEvent *e)-
1019{-
1020 Q_D(QAbstractButton);-
1021 if (!(e->buttons() & Qt::LeftButton) || !d->pressed) {-
1022 e->ignore();-
1023 return;-
1024 }-
1025-
1026 if (hitButton(e->pos()) != d->down) {-
1027 setDown(!d->down);-
1028 repaint(); //flush paint event before invoking potentially expensive operation-
1029 QApplication::flush();-
1030 if (d->down)-
1031 d->emitPressed();-
1032 else-
1033 d->emitReleased();-
1034 e->accept();-
1035 } else if (!hitButton(e->pos())) {-
1036 e->ignore();-
1037 }-
1038}-
1039-
1040/*! \reimp */-
1041void QAbstractButton::keyPressEvent(QKeyEvent *e)-
1042{-
1043 Q_D(QAbstractButton);-
1044 bool next = true;-
1045 switch (e->key()) {-
1046 case Qt::Key_Enter:-
1047 case Qt::Key_Return:-
1048 e->ignore();-
1049 break;-
1050 case Qt::Key_Select:-
1051 case Qt::Key_Space:-
1052 if (!e->isAutoRepeat()) {-
1053 setDown(true);-
1054 repaint(); //flush paint event before invoking potentially expensive operation-
1055 QApplication::flush();-
1056 d->emitPressed();-
1057 }-
1058 break;-
1059 case Qt::Key_Up:-
1060 next = false;-
1061 // fall through-
1062 case Qt::Key_Left:-
1063 case Qt::Key_Right:-
1064 case Qt::Key_Down: {-
1065#ifdef QT_KEYPAD_NAVIGATION-
1066 if ((QApplication::keypadNavigationEnabled()-
1067 && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right))-
1068 || (!QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional-
1069 || (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down))) {-
1070 e->ignore();-
1071 return;-
1072 }-
1073#endif-
1074 QWidget *pw = parentWidget();-
1075 if (d->autoExclusive-
1076#ifndef QT_NO_BUTTONGROUP-
1077 || d->group-
1078#endif-
1079#ifndef QT_NO_ITEMVIEWS-
1080 || (pw && qobject_cast<QAbstractItemView *>(pw->parentWidget()))-
1081#endif-
1082 ) {-
1083 // ### Using qobject_cast to check if the parent is a viewport of-
1084 // QAbstractItemView is a crude hack, and should be revisited and-
1085 // cleaned up when fixing task 194373. It's here to ensure that we-
1086 // keep compatibility outside QAbstractItemView.-
1087 d->moveFocus(e->key());-
1088 if (hasFocus()) // nothing happend, propagate-
1089 e->ignore();-
1090 } else {-
1091 // Prefer parent widget, use this if parent is absent-
1092 QWidget *w = pw ? pw : this;-
1093 bool reverse = (w->layoutDirection() == Qt::RightToLeft);-
1094 if ((e->key() == Qt::Key_Left && !reverse)-
1095 || (e->key() == Qt::Key_Right && reverse)) {-
1096 next = false;-
1097 }-
1098 focusNextPrevChild(next);-
1099 }-
1100 break;-
1101 }-
1102 default:-
1103 if (e->matches(QKeySequence::Cancel) && d->down) {-
1104 setDown(false);-
1105 repaint(); //flush paint event before invoking potentially expensive operation-
1106 QApplication::flush();-
1107 d->emitReleased();-
1108 return;-
1109 }-
1110 e->ignore();-
1111 }-
1112}-
1113-
1114/*! \reimp */-
1115void QAbstractButton::keyReleaseEvent(QKeyEvent *e)-
1116{-
1117 Q_D(QAbstractButton);-
1118-
1119 if (!e->isAutoRepeat())-
1120 d->repeatTimer.stop();-
1121-
1122 switch (e->key()) {-
1123 case Qt::Key_Select:-
1124 case Qt::Key_Space:-
1125 if (!e->isAutoRepeat() && d->down)-
1126 d->click();-
1127 break;-
1128 default:-
1129 e->ignore();-
1130 }-
1131}-
1132-
1133/*!\reimp-
1134 */-
1135void QAbstractButton::timerEvent(QTimerEvent *e)-
1136{-
1137 Q_D(QAbstractButton);-
1138 if (e->timerId() == d->repeatTimer.timerId()) {-
1139 d->repeatTimer.start(d->autoRepeatInterval, this);-
1140 if (d->down) {-
1141 QPointer<QAbstractButton> guard(this);-
1142 nextCheckState();-
1143 if (guard)-
1144 d->emitReleased();-
1145 if (guard)-
1146 d->emitClicked();-
1147 if (guard)-
1148 d->emitPressed();-
1149 }-
1150 } else if (e->timerId() == d->animateTimer.timerId()) {-
1151 d->animateTimer.stop();-
1152 d->click();-
1153 }-
1154}-
1155-
1156/*! \reimp */-
1157void QAbstractButton::focusInEvent(QFocusEvent *e)-
1158{-
1159 Q_D(QAbstractButton);-
1160#ifdef QT_KEYPAD_NAVIGATION-
1161 if (!QApplication::keypadNavigationEnabled())-
1162#endif-
1163 d->fixFocusPolicy();-
1164 QWidget::focusInEvent(e);-
1165}-
1166-
1167/*! \reimp */-
1168void QAbstractButton::focusOutEvent(QFocusEvent *e)-
1169{-
1170 Q_D(QAbstractButton);-
1171 if (e->reason() != Qt::PopupFocusReason && d->down) {-
1172 d->down = false;-
1173 d->emitReleased();-
1174 }-
1175 QWidget::focusOutEvent(e);-
1176}-
1177-
1178/*! \reimp */-
1179void QAbstractButton::changeEvent(QEvent *e)-
1180{-
1181 Q_D(QAbstractButton);-
1182 switch (e->type()) {-
1183 case QEvent::EnabledChange:-
1184 if (!isEnabled() && d->down) {-
1185 d->down = false;-
1186 d->emitReleased();-
1187 }-
1188 break;-
1189 default:-
1190 d->sizeHint = QSize();-
1191 break;-
1192 }-
1193 QWidget::changeEvent(e);-
1194}-
1195-
1196/*!-
1197 \fn void QAbstractButton::paintEvent(QPaintEvent *e)-
1198 \reimp-
1199*/-
1200-
1201/*!-
1202 \fn void QAbstractButton::pressed()-
1203-
1204 This signal is emitted when the button is pressed down.-
1205-
1206 \sa released(), clicked()-
1207*/-
1208-
1209/*!-
1210 \fn void QAbstractButton::released()-
1211-
1212 This signal is emitted when the button is released.-
1213-
1214 \sa pressed(), clicked(), toggled()-
1215*/-
1216-
1217/*!-
1218\fn void QAbstractButton::clicked(bool checked)-
1219-
1220This signal is emitted when the button is activated (i.e., pressed down-
1221then released while the mouse cursor is inside the button), when the-
1222shortcut key is typed, or when click() or animateClick() is called.-
1223Notably, this signal is \e not emitted if you call setDown(),-
1224setChecked() or toggle().-
1225-
1226If the button is checkable, \a checked is true if the button is-
1227checked, or false if the button is unchecked.-
1228-
1229\sa pressed(), released(), toggled()-
1230*/-
1231-
1232/*!-
1233\fn void QAbstractButton::toggled(bool checked)-
1234-
1235This signal is emitted whenever a checkable button changes its state.-
1236\a checked is true if the button is checked, or false if the button is-
1237unchecked.-
1238-
1239This may be the result of a user action, click() slot activation,-
1240or because setChecked() is called.-
1241-
1242The states of buttons in exclusive button groups are updated before this-
1243signal is emitted. This means that slots can act on either the "off"-
1244signal or the "on" signal emitted by the buttons in the group whose-
1245states have changed.-
1246-
1247For example, a slot that reacts to signals emitted by newly checked-
1248buttons but which ignores signals from buttons that have been unchecked-
1249can be implemented using the following pattern:-
1250-
1251\snippet code/src_gui_widgets_qabstractbutton.cpp 2-
1252-
1253Button groups can be created using the QButtonGroup class, and-
1254updates to the button states monitored with the-
1255\l{QButtonGroup::buttonClicked()} signal.-
1256-
1257\sa checked, clicked()-
1258*/-
1259-
1260/*!-
1261 \property QAbstractButton::iconSize-
1262 \brief the icon size used for this button.-
1263-
1264 The default size is defined by the GUI style. This is a maximum-
1265 size for the icons. Smaller icons will not be scaled up.-
1266*/-
1267-
1268QSize QAbstractButton::iconSize() const-
1269{-
1270 Q_D(const QAbstractButton);-
1271 if (d->iconSize.isValid())-
1272 return d->iconSize;-
1273 int e = style()->pixelMetric(QStyle::PM_ButtonIconSize, 0, this);-
1274 return QSize(e, e);-
1275}-
1276-
1277void QAbstractButton::setIconSize(const QSize &size)-
1278{-
1279 Q_D(QAbstractButton);-
1280 if (d->iconSize == size)-
1281 return;-
1282-
1283 d->iconSize = size;-
1284 d->sizeHint = QSize();-
1285 updateGeometry();-
1286 if (isVisible()) {-
1287 update();-
1288 }-
1289}-
1290-
1291-
1292-
1293QT_END_NAMESPACE-
1294-
1295#include "moc_qabstractbutton.cpp"-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9