Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/widgets/widgets/qabstractbutton.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||
---|---|---|---|---|---|---|---|---|
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 | - | |||||||
57 | QT_BEGIN_NAMESPACE | - | ||||||
58 | - | |||||||
59 | #define AUTO_REPEAT_DELAY 300 | - | ||||||
60 | #define AUTO_REPEAT_INTERVAL 100 | - | ||||||
61 | - | |||||||
62 | Q_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 | - | |||||||
167 | QAbstractButtonPrivate::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 | - | |||||||
182 | QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const | - | ||||||
183 | { | - | ||||||
184 | #ifndef QT_NO_BUTTONGROUP | - | ||||||
185 | if (group)
| 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) {
| 0 | ||||||
191 | for (int iauto isNoMemberOfMyAutoExclusiveGroup = candidates.count() - 1; i >= 0; --i) {[](QAbstractButton *candidate= candidates.at(i); | - | ||||||
if (!) { | ||||||||
192 | return ! never executed: candidate->autoExclusive()return !candidate->autoExclusive() || candidate->group() ; 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 | - | |||||||
205 | QAbstractButton *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 | - | |||||||
225 | void 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 | - | |||||||
242 | void 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 | - | |||||||
333 | void 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 | - | |||||||
354 | void 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 | - | |||||||
365 | void QAbstractButtonPrivate::refresh() | - | ||||||
366 | { | - | ||||||
367 | Q_Q(QAbstractButton); | - | ||||||
368 | - | |||||||
369 | if (blockRefresh) | - | ||||||
370 | return; | - | ||||||
371 | q->update(); | - | ||||||
372 | } | - | ||||||
373 | - | |||||||
374 | void 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 | - | |||||||
407 | void 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 | - | |||||||
421 | void 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 | - | |||||||
435 | void 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 | - | |||||||
449 | void 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 | */ | - | ||||||
466 | QAbstractButton::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 | */ | - | ||||||
488 | QAbstractButton::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 | - | |||||||
499 | If the button has no text, the text() function will return an empty | - | ||||||
500 | string. | - | ||||||
501 | - | |||||||
502 | If the text contains an ampersand character ('&'), a shortcut is | - | ||||||
503 | automatically created for it. The character that follows the '&' will | - | ||||||
504 | be used as the shortcut key. Any previous shortcut will be | - | ||||||
505 | overwritten or cleared if no shortcut is defined by the text. See the | - | ||||||
506 | \l {QShortcut#mnemonic}{QShortcut} documentation for details. To | - | ||||||
507 | display an actual ampersand, use '&&'. | - | ||||||
508 | - | |||||||
509 | There is no default text. | - | ||||||
510 | */ | - | ||||||
511 | - | |||||||
512 | void 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 | - | |||||||
531 | QString 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 | */ | - | ||||||
545 | void QAbstractButton::setIcon(const QIcon &icon) | - | ||||||
546 | { | - | ||||||
547 | Q_D(QAbstractButton); | - | ||||||
548 | d->icon = icon; | - | ||||||
549 | d->sizeHint = QSize(); | - | ||||||
550 | update(); | - | ||||||
551 | updateGeometry(); | - | ||||||
552 | } | - | ||||||
553 | - | |||||||
554 | QIcon 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 | - | |||||||
566 | void 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 | - | |||||||
575 | QKeySequence 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 | - | |||||||
586 | By default, the button is not checkable. | - | ||||||
587 | - | |||||||
588 | \sa checked | - | ||||||
589 | */ | - | ||||||
590 | void 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 | - | |||||||
600 | bool 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 | - | |||||||
610 | Only checkable buttons can be checked. By default, the button is unchecked. | - | ||||||
611 | - | |||||||
612 | \sa checkable | - | ||||||
613 | */ | - | ||||||
614 | void 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 | - | |||||||
657 | bool 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 | - | |||||||
672 | void 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 | - | |||||||
685 | bool 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 | - | |||||||
695 | If autoRepeat is enabled, then the pressed(), released(), and clicked() signals are emitted at | - | ||||||
696 | regular intervals when the button is down. autoRepeat is off by default. | - | ||||||
697 | The initial delay and the repetition interval are defined in milliseconds by \l | - | ||||||
698 | autoRepeatDelay and \l autoRepeatInterval. | - | ||||||
699 | - | |||||||
700 | Note: If a button is pressed down by a shortcut key, then auto-repeat is enabled and timed by the | - | ||||||
701 | system and not by this class. The pressed(), released(), and clicked() signals will be emitted | - | ||||||
702 | like in the normal case. | - | ||||||
703 | */ | - | ||||||
704 | - | |||||||
705 | void 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 | - | |||||||
717 | bool 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 | - | |||||||
734 | void QAbstractButton::setAutoRepeatDelay(int autoRepeatDelay) | - | ||||||
735 | { | - | ||||||
736 | Q_D(QAbstractButton); | - | ||||||
737 | d->autoRepeatDelay = autoRepeatDelay; | - | ||||||
738 | } | - | ||||||
739 | - | |||||||
740 | int 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 | - | |||||||
757 | void QAbstractButton::setAutoRepeatInterval(int autoRepeatInterval) | - | ||||||
758 | { | - | ||||||
759 | Q_D(QAbstractButton); | - | ||||||
760 | d->autoRepeatInterval = autoRepeatInterval; | - | ||||||
761 | } | - | ||||||
762 | - | |||||||
763 | int 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 | - | |||||||
775 | If auto-exclusivity is enabled, checkable buttons that belong to the | - | ||||||
776 | same parent widget behave as if they were part of the same | - | ||||||
777 | exclusive button group. In an exclusive button group, only one button | - | ||||||
778 | can be checked at any time; checking another button automatically | - | ||||||
779 | unchecks the previously checked one. | - | ||||||
780 | - | |||||||
781 | The property has no effect on buttons that belong to a button | - | ||||||
782 | group. | - | ||||||
783 | - | |||||||
784 | autoExclusive is off by default, except for radio buttons. | - | ||||||
785 | - | |||||||
786 | \sa QRadioButton | - | ||||||
787 | */ | - | ||||||
788 | void QAbstractButton::setAutoExclusive(bool autoExclusive) | - | ||||||
789 | { | - | ||||||
790 | Q_D(QAbstractButton); | - | ||||||
791 | d->autoExclusive = autoExclusive; | - | ||||||
792 | } | - | ||||||
793 | - | |||||||
794 | bool 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 | */ | - | ||||||
809 | QButtonGroup *QAbstractButton::group() const | - | ||||||
810 | { | - | ||||||
811 | Q_D(const QAbstractButton); | - | ||||||
812 | return d->group; | - | ||||||
813 | } | - | ||||||
814 | #endif // QT_NO_BUTTONGROUP | - | ||||||
815 | - | |||||||
816 | /*! | - | ||||||
817 | Performs an animated click: the button is pressed immediately, and | - | ||||||
818 | released \a msec milliseconds later (the default is 100 ms). | - | ||||||
819 | - | |||||||
820 | Calling this function again before the button is released resets | - | ||||||
821 | the release timer. | - | ||||||
822 | - | |||||||
823 | All signals associated with a click are emitted as appropriate. | - | ||||||
824 | - | |||||||
825 | This function does nothing if the button is \l{setEnabled()}{disabled.} | - | ||||||
826 | - | |||||||
827 | \sa click() | - | ||||||
828 | */ | - | ||||||
829 | void 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 | /*! | - | ||||||
845 | Performs a click. | - | ||||||
846 | - | |||||||
847 | All the usual signals associated with a click are emitted as | - | ||||||
848 | appropriate. If the button is checkable, the state of the button is | - | ||||||
849 | toggled. | - | ||||||
850 | - | |||||||
851 | This function does nothing if the button is \l{setEnabled()}{disabled.} | - | ||||||
852 | - | |||||||
853 | \sa animateClick() | - | ||||||
854 | */ | - | ||||||
855 | void 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 | */ | - | ||||||
879 | void QAbstractButton::toggle() | - | ||||||
880 | { | - | ||||||
881 | Q_D(QAbstractButton); | - | ||||||
882 | setChecked(!d->checked); | - | ||||||
883 | } | - | ||||||
884 | - | |||||||
885 | - | |||||||
886 | /*! This virtual handler is called when setChecked() is used, | - | ||||||
887 | unless it is called from within nextCheckState(). It allows | - | ||||||
888 | subclasses to reset their intermediate button states. | - | ||||||
889 | - | |||||||
890 | \sa nextCheckState() | - | ||||||
891 | */ | - | ||||||
892 | void QAbstractButton::checkStateSet() | - | ||||||
893 | { | - | ||||||
894 | } | - | ||||||
895 | - | |||||||
896 | /*! This virtual handler is called when a button is clicked. The | - | ||||||
897 | default implementation calls setChecked(!isChecked()) if the button | - | ||||||
898 | isCheckable(). It allows subclasses to implement intermediate button | - | ||||||
899 | states. | - | ||||||
900 | - | |||||||
901 | \sa checkStateSet() | - | ||||||
902 | */ | - | ||||||
903 | void QAbstractButton::nextCheckState() | - | ||||||
904 | { | - | ||||||
905 | if (isCheckable()) | - | ||||||
906 | setChecked(!isChecked()); | - | ||||||
907 | } | - | ||||||
908 | - | |||||||
909 | /*! | - | ||||||
910 | Returns \c true if \a pos is inside the clickable button rectangle; | - | ||||||
911 | otherwise returns \c false. | - | ||||||
912 | - | |||||||
913 | By default, the clickable area is the entire widget. Subclasses | - | ||||||
914 | may reimplement this function to provide support for clickable | - | ||||||
915 | areas of different shapes and sizes. | - | ||||||
916 | */ | - | ||||||
917 | bool QAbstractButton::hitButton(const QPoint &pos) const | - | ||||||
918 | { | - | ||||||
919 | return rect().contains(pos); | - | ||||||
920 | } | - | ||||||
921 | - | |||||||
922 | /*! \reimp */ | - | ||||||
923 | bool 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 */ | - | ||||||
970 | void 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 */ | - | ||||||
990 | void 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 */ | - | ||||||
1018 | void 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 */ | - | ||||||
1041 | void 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 */ | - | ||||||
1115 | void 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 | */ | - | ||||||
1135 | void 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 */ | - | ||||||
1157 | void 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 */ | - | ||||||
1168 | void 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 */ | - | ||||||
1179 | void 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 | - | |||||||
1220 | This signal is emitted when the button is activated (i.e., pressed down | - | ||||||
1221 | then released while the mouse cursor is inside the button), when the | - | ||||||
1222 | shortcut key is typed, or when click() or animateClick() is called. | - | ||||||
1223 | Notably, this signal is \e not emitted if you call setDown(), | - | ||||||
1224 | setChecked() or toggle(). | - | ||||||
1225 | - | |||||||
1226 | If the button is checkable, \a checked is true if the button is | - | ||||||
1227 | checked, or false if the button is unchecked. | - | ||||||
1228 | - | |||||||
1229 | \sa pressed(), released(), toggled() | - | ||||||
1230 | */ | - | ||||||
1231 | - | |||||||
1232 | /*! | - | ||||||
1233 | \fn void QAbstractButton::toggled(bool checked) | - | ||||||
1234 | - | |||||||
1235 | This 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 | - | ||||||
1237 | unchecked. | - | ||||||
1238 | - | |||||||
1239 | This may be the result of a user action, click() slot activation, | - | ||||||
1240 | or because setChecked() is called. | - | ||||||
1241 | - | |||||||
1242 | The states of buttons in exclusive button groups are updated before this | - | ||||||
1243 | signal is emitted. This means that slots can act on either the "off" | - | ||||||
1244 | signal or the "on" signal emitted by the buttons in the group whose | - | ||||||
1245 | states have changed. | - | ||||||
1246 | - | |||||||
1247 | For example, a slot that reacts to signals emitted by newly checked | - | ||||||
1248 | buttons but which ignores signals from buttons that have been unchecked | - | ||||||
1249 | can be implemented using the following pattern: | - | ||||||
1250 | - | |||||||
1251 | \snippet code/src_gui_widgets_qabstractbutton.cpp 2 | - | ||||||
1252 | - | |||||||
1253 | Button groups can be created using the QButtonGroup class, and | - | ||||||
1254 | updates 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 | - | |||||||
1268 | QSize 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 | - | |||||||
1277 | void 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 | - | |||||||
1293 | QT_END_NAMESPACE | - | ||||||
1294 | - | |||||||
1295 | #include "moc_qabstractbutton.cpp" | - | ||||||
Source code | Switch to Preprocessed file |