widgets/qmenu.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/****************************************************************************-
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/****************************************************************************
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Contact: http://www.qt-project.org/legal -
5** -
6** This file is part of the QtGui 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 Digia. For licensing terms and -
14** conditions see http://qt.digia.com/licensing. For further information -
15** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software -
20** Foundation and appearing in the file LICENSE.LGPL included in the -
21** packaging of this file. Please review the following information to -
22** ensure the GNU Lesser General Public License version 2.1 requirements -
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -
24** -
25** In addition, as a special exception, Digia gives you certain additional -
26** rights. These rights are described in the Digia Qt LGPL Exception -
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -
28** -
29** GNU General Public License Usage -
30** Alternatively, this file may be used under the terms of the GNU -
31** General Public License version 3.0 as published by the Free Software -
32** Foundation and appearing in the file LICENSE.GPL included in the -
33** packaging of this file. Please review the following information to -
34** ensure the GNU General Public License version 3.0 requirements will be -
35** met: http://www.gnu.org/copyleft/gpl.html. -
36** -
37** -
38** $QT_END_LICENSE$ -
39** -
40****************************************************************************/ -
41 -
42#include "qmenu.h" -
43 -
44#ifndef QT_NO_MENU -
45 -
46#include "qdebug.h" -
47#include "qstyle.h" -
48#include "qevent.h" -
49#include "qtimer.h" -
50#include "qlayout.h" -
51#include "qpainter.h" -
52#include <qpa/qplatformtheme.h> -
53#include "qapplication.h" -
54#include "qdesktopwidget.h" -
55#ifndef QT_NO_ACCESSIBILITY -
56# include "qaccessible.h" -
57#endif -
58#ifndef QT_NO_EFFECTS -
59# include <private/qeffects_p.h> -
60#endif -
61#ifndef QT_NO_WHATSTHIS -
62# include <qwhatsthis.h> -
63#endif -
64 -
65#include "qmenu_p.h" -
66#include "qmenubar_p.h" -
67#include "qwidgetaction.h" -
68#include "qtoolbutton.h" -
69#include "qpushbutton.h" -
70#include <private/qpushbutton_p.h> -
71#include <private/qaction_p.h> -
72#include <private/qguiapplication_p.h> -
73 -
74QT_BEGIN_NAMESPACE -
75 -
76QMenu *QMenuPrivate::mouseDown = 0; -
77int QMenuPrivate::sloppyDelayTimer = 0; -
78 -
79/* QMenu code */ -
80// internal class used for the torn off popup -
81class QTornOffMenu : public QMenu -
82{ -
83 Q_OBJECT -
84 class QTornOffMenuPrivate : public QMenuPrivate -
85 { -
86 Q_DECLARE_PUBLIC(QMenu) -
87 public: -
88 QTornOffMenuPrivate(QMenu *p) : causedMenu(p) { -
89 tornoff = 1; -
90 causedPopup.widget = 0; -
91 causedPopup.action = ((QTornOffMenu*)p)->d_func()->causedPopup.action; -
92 causedStack = ((QTornOffMenu*)p)->d_func()->calcCausedStack(); -
93 } -
94 QList<QPointer<QWidget> > calcCausedStack() const { return causedStack; } -
95 QPointer<QMenu> causedMenu; -
96 QList<QPointer<QWidget> > causedStack; -
97 }; -
98public: -
99 QTornOffMenu(QMenu *p) : QMenu(*(new QTornOffMenuPrivate(p))) -
100 { -
101 Q_D(QTornOffMenu); -
102 // make the torn-off menu a sibling of p (instead of a child) -
103 QWidget *parentWidget = d->causedStack.isEmpty() ? p : d->causedStack.last(); -
104 if (parentWidget->parentWidget()) -
105 parentWidget = parentWidget->parentWidget(); -
106 setParent(parentWidget, Qt::Window | Qt::Tool); -
107 setAttribute(Qt::WA_DeleteOnClose, true); -
108 setAttribute(Qt::WA_X11NetWmWindowTypeMenu, true); -
109 setWindowTitle(p->windowTitle()); -
110 setEnabled(p->isEnabled()); -
111 //QObject::connect(this, SIGNAL(triggered(QAction*)), this, SLOT(onTrigger(QAction*))); -
112 //QObject::connect(this, SIGNAL(hovered(QAction*)), this, SLOT(onHovered(QAction*))); -
113 QList<QAction*> items = p->actions(); -
114 for(int i = 0; i < items.count(); i++) -
115 addAction(items.at(i)); -
116 } -
117 void syncWithMenu(QMenu *menu, QActionEvent *act) -
118 { -
119 Q_D(QTornOffMenu); -
120 if(menu != d->causedMenu) -
121 return; -
122 if (act->type() == QEvent::ActionAdded) { -
123 insertAction(act->before(), act->action()); -
124 } else if (act->type() == QEvent::ActionRemoved) -
125 removeAction(act->action()); -
126 } -
127 void actionEvent(QActionEvent *e) -
128 { -
129 QMenu::actionEvent(e); -
130 setFixedSize(sizeHint()); -
131 } -
132public slots: -
133 void onTrigger(QAction *action) { d_func()->activateAction(action, QAction::Trigger, false); } -
134 void onHovered(QAction *action) { d_func()->activateAction(action, QAction::Hover, false); } -
135private: -
136 Q_DECLARE_PRIVATE(QTornOffMenu) -
137 friend class QMenuPrivate; -
138}; -
139 -
140void QMenuPrivate::init() -
141{ -
142 Q_Q(QMenu); -
143#ifndef QT_NO_WHATSTHIS -
144 q->setAttribute(Qt::WA_CustomWhatsThis); -
145#endif -
146 q->setAttribute(Qt::WA_X11NetWmWindowTypePopupMenu); -
147 defaultMenuAction = menuAction = new QAction(q); -
148 menuAction->d_func()->menu = q; -
149 q->setMouseTracking(q->style()->styleHint(QStyle::SH_Menu_MouseTracking, 0, q)); -
150 if (q->style()->styleHint(QStyle::SH_Menu_Scrollable, 0, q)) { -
151 scroll = new QMenuPrivate::QMenuScroller; -
152 scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone; -
153 } -
154 -
155 platformMenu = QGuiApplicationPrivate::platformTheme()->createPlatformMenu(); -
156 if (platformMenu) { -
157 QObject::connect(platformMenu, SIGNAL(aboutToShow()), q, SIGNAL(aboutToShow())); -
158 QObject::connect(platformMenu, SIGNAL(aboutToHide()), q, SIGNAL(aboutToHide())); -
159 } -
160} -
161 -
162int QMenuPrivate::scrollerHeight() const -
163{ -
164 Q_Q(const QMenu); -
165 return qMax(QApplication::globalStrut().height(), q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q)); -
166} -
167 -
168//Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't -
169QRect QMenuPrivate::popupGeometry(const QWidget *widget) const -
170{ -
171 if (QGuiApplicationPrivate::platformTheme() && -
172 QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::UseFullScreenForPopupMenu).toBool()) { -
173 return QApplication::desktop()->screenGeometry(widget); -
174 } else { -
175 return QApplication::desktop()->availableGeometry(widget); -
176 } -
177} -
178 -
179//Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't -
180QRect QMenuPrivate::popupGeometry(int screen) const -
181{ -
182 if (QGuiApplicationPrivate::platformTheme() && -
183 QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::UseFullScreenForPopupMenu).toBool()) { -
184 return QApplication::desktop()->screenGeometry(screen); -
185 } else { -
186 return QApplication::desktop()->availableGeometry(screen); -
187 } -
188} -
189 -
190QList<QPointer<QWidget> > QMenuPrivate::calcCausedStack() const -
191{ -
192 QList<QPointer<QWidget> > ret; -
193 for(QWidget *widget = causedPopup.widget; widget; ) { -
194 ret.append(widget); -
195 if (QTornOffMenu *qtmenu = qobject_cast<QTornOffMenu*>(widget)) -
196 ret += qtmenu->d_func()->causedStack; -
197 if (QMenu *qmenu = qobject_cast<QMenu*>(widget)) -
198 widget = qmenu->d_func()->causedPopup.widget; -
199 else -
200 break; -
201 } -
202 return ret; -
203} -
204 -
205void QMenuPrivate::updateActionRects() const -
206{ -
207 Q_Q(const QMenu); -
208 updateActionRects(popupGeometry(q)); -
209} -
210 -
211void QMenuPrivate::updateActionRects(const QRect &screen) const -
212{ -
213 Q_Q(const QMenu); -
214 if (!itemsDirty) -
215 return; -
216 -
217 q->ensurePolished(); -
218 -
219 //let's reinitialize the buffer -
220 actionRects.resize(actions.count()); -
221 actionRects.fill(QRect()); -
222 -
223 int lastVisibleAction = getLastVisibleAction(); -
224 -
225 int max_column_width = 0, -
226 dh = screen.height(), -
227 y = 0; -
228 QStyle *style = q->style(); -
229 QStyleOption opt; -
230 opt.init(q); -
231 const int hmargin = style->pixelMetric(QStyle::PM_MenuHMargin, &opt, q), -
232 vmargin = style->pixelMetric(QStyle::PM_MenuVMargin, &opt, q), -
233 icone = style->pixelMetric(QStyle::PM_SmallIconSize, &opt, q); -
234 const int fw = style->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, q); -
235 const int deskFw = style->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, &opt, q); -
236 const int tearoffHeight = tearoff ? style->pixelMetric(QStyle::PM_MenuTearoffHeight, &opt, q) : 0; -
237 -
238 //for compatibility now - will have to refactor this away -
239 tabWidth = 0; -
240 maxIconWidth = 0; -
241 hasCheckableItems = false; -
242 ncols = 1; -
243 sloppyAction = 0; -
244 -
245 for (int i = 0; i < actions.count(); ++i) { -
246 QAction *action = actions.at(i); -
247 if (action->isSeparator() || !action->isVisible() || widgetItems.contains(action)) -
248 continue; -
249 //..and some members -
250 hasCheckableItems |= action->isCheckable(); -
251 QIcon is = action->icon(); -
252 if (!is.isNull()) { -
253 maxIconWidth = qMax<uint>(maxIconWidth, icone + 4); -
254 } -
255 } -
256 -
257 //calculate size -
258 QFontMetrics qfm = q->fontMetrics(); -
259 bool previousWasSeparator = true; // this is true to allow removing the leading separators -
260 for(int i = 0; i <= lastVisibleAction; i++) { -
261 QAction *action = actions.at(i); -
262 -
263 if (!action->isVisible() || -
264 (collapsibleSeparators && previousWasSeparator && action->isSeparator())) -
265 continue; // we continue, this action will get an empty QRect -
266 -
267 previousWasSeparator = action->isSeparator(); -
268 -
269 //let the style modify the above size.. -
270 QStyleOptionMenuItem opt; -
271 q->initStyleOption(&opt, action); -
272 const QFontMetrics &fm = opt.fontMetrics; -
273 -
274 QSize sz; -
275 if (QWidget *w = widgetItems.value(action)) { -
276 sz = w->sizeHint().expandedTo(w->minimumSize()).expandedTo(w->minimumSizeHint()).boundedTo(w->maximumSize()); -
277 } else { -
278 //calc what I think the size is.. -
279 if (action->isSeparator()) { -
280 sz = QSize(2, 2); -
281 } else { -
282 QString s = action->text(); -
283 int t = s.indexOf(QLatin1Char('\t')); -
284 if (t != -1) { -
285 tabWidth = qMax(int(tabWidth), qfm.width(s.mid(t+1))); -
286 s = s.left(t); -
287 #ifndef QT_NO_SHORTCUT -
288 } else { -
289 QKeySequence seq = action->shortcut(); -
290 if (!seq.isEmpty()) -
291 tabWidth = qMax(int(tabWidth), qfm.width(seq.toString(QKeySequence::NativeText))); -
292 #endif -
293 } -
294 sz.setWidth(fm.boundingRect(QRect(), Qt::TextSingleLine | Qt::TextShowMnemonic, s).width()); -
295 sz.setHeight(qMax(fm.height(), qfm.height())); -
296 -
297 QIcon is = action->icon(); -
298 if (!is.isNull()) { -
299 QSize is_sz = QSize(icone, icone); -
300 if (is_sz.height() > sz.height()) -
301 sz.setHeight(is_sz.height()); -
302 } -
303 } -
304 sz = style->sizeFromContents(QStyle::CT_MenuItem, &opt, sz, q); -
305 } -
306 -
307 -
308 if (!sz.isEmpty()) { -
309 max_column_width = qMax(max_column_width, sz.width()); -
310 //wrapping -
311 if (!scroll && -
312 y+sz.height()+vmargin > dh - (deskFw * 2)) { -
313 ncols++; -
314 y = vmargin; -
315 } -
316 y += sz.height(); -
317 //update the item -
318 actionRects[i] = QRect(0, 0, sz.width(), sz.height()); -
319 } -
320 } -
321 -
322 max_column_width += tabWidth; //finally add in the tab width -
323 const int sfcMargin = style->sizeFromContents(QStyle::CT_Menu, &opt, QApplication::globalStrut(), q).width() - QApplication::globalStrut().width(); -
324 const int min_column_width = q->minimumWidth() - (sfcMargin + leftmargin + rightmargin + 2 * (fw + hmargin)); -
325 max_column_width = qMax(min_column_width, max_column_width); -
326 -
327 //calculate position -
328 const int base_y = vmargin + fw + topmargin + -
329 (scroll ? scroll->scrollOffset : 0) + -
330 tearoffHeight; -
331 int x = hmargin + fw + leftmargin; -
332 y = base_y; -
333 -
334 for(int i = 0; i < actions.count(); i++) { -
335 QRect &rect = actionRects[i]; -
336 if (rect.isNull()) -
337 continue; -
338 if (!scroll && -
339 y+rect.height() > dh - deskFw * 2) { -
340 x += max_column_width + hmargin; -
341 y = base_y; -
342 } -
343 rect.translate(x, y); //move -
344 rect.setWidth(max_column_width); //uniform width -
345 -
346 //we need to update the widgets geometry -
347 if (QWidget *widget = widgetItems.value(actions.at(i))) { -
348 widget->setGeometry(rect); -
349 widget->setVisible(actions.at(i)->isVisible()); -
350 } -
351 -
352 y += rect.height(); -
353 } -
354 itemsDirty = 0; -
355} -
356 -
357QSize QMenuPrivate::adjustMenuSizeForScreen(const QRect &screen) -
358{ -
359 Q_Q(QMenu); -
360 QSize ret = screen.size(); -
361 itemsDirty = true; -
362 updateActionRects(screen); -
363 const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, q); -
364 ret.setWidth(actionRects.at(getLastVisibleAction()).right() + fw); -
365 return ret; -
366} -
367 -
368int QMenuPrivate::getLastVisibleAction() const -
369{ -
370 //let's try to get the last visible action -
371 int lastVisibleAction = actions.count() - 1; -
372 for (;lastVisibleAction >= 0; --lastVisibleAction) { -
373 const QAction *action = actions.at(lastVisibleAction); -
374 if (action->isVisible()) { -
375 //removing trailing separators -
376 if (action->isSeparator() && collapsibleSeparators) -
377 continue; -
378 break; -
379 } -
380 } -
381 return lastVisibleAction; -
382} -
383 -
384 -
385QRect QMenuPrivate::actionRect(QAction *act) const -
386{ -
387 int index = actions.indexOf(act); -
388 if (index == -1) -
389 return QRect(); -
390 -
391 updateActionRects(); -
392 -
393 //we found the action -
394 return actionRects.at(index); -
395} -
396 -
397#if defined(Q_OS_MAC) -
398static const qreal MenuFadeTimeInSec = 0.150; -
399#endif -
400 -
401void QMenuPrivate::hideUpToMenuBar() -
402{ -
403 Q_Q(QMenu); -
404 bool fadeMenus = q->style()->styleHint(QStyle::SH_Menu_FadeOutOnHide); -
405 if (!tornoff) { -
406 QWidget *caused = causedPopup.widget; -
407 hideMenu(q); //hide after getting causedPopup -
408 while(caused) { -
409#ifndef QT_NO_MENUBAR -
410 if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) { -
411 mb->d_func()->setCurrentAction(0); -
412 mb->d_func()->setKeyboardMode(false); -
413 caused = 0; -
414 } else -
415#endif -
416 if (QMenu *m = qobject_cast<QMenu*>(caused)) { -
417 caused = m->d_func()->causedPopup.widget; -
418 if (!m->d_func()->tornoff) -
419 hideMenu(m, fadeMenus); -
420 if (!fadeMenus) // Mac doesn't clear the action until after hidden. -
421 m->d_func()->setCurrentAction(0); -
422 } else { caused = 0; -
423 } -
424 } -
425#if defined(Q_WS_MAC) -
426 if (fadeMenus) { -
427 QEventLoop eventLoop; -
428 QTimer::singleShot(int(MenuFadeTimeInSec * 1000), &eventLoop, SLOT(quit())); -
429 QMacWindowFader::currentFader()->performFade(); -
430 eventLoop.exec(); -
431 } -
432#endif -
433 } -
434 setCurrentAction(0); -
435} -
436 -
437void QMenuPrivate::hideMenu(QMenu *menu, bool justRegister) -
438{ -
439 if (!menu) -
440 return; -
441#if !defined(QT_NO_EFFECTS) -
442 menu->blockSignals(true); -
443 aboutToHide = true; -
444 // Flash item which is about to trigger (if any). -
445 if (menu->style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem) -
446 && currentAction && currentAction == actionAboutToTrigger -
447 && menu->actions().contains(currentAction)) { -
448 QEventLoop eventLoop; -
449 QAction *activeAction = currentAction; -
450 -
451 menu->setActiveAction(0); -
452 QTimer::singleShot(60, &eventLoop, SLOT(quit())); -
453 eventLoop.exec(); -
454 -
455 // Select and wait 20 ms. -
456 menu->setActiveAction(activeAction); -
457 QTimer::singleShot(20, &eventLoop, SLOT(quit())); -
458 eventLoop.exec(); -
459 } -
460 -
461 // Fade out. -
462 if (menu->style()->styleHint(QStyle::SH_Menu_FadeOutOnHide)) { -
463 // ### Qt 4.4: -
464 // Should be something like: q->transitionWindow(Qt::FadeOutTransition, MenuFadeTimeInSec); -
465 // Hopefully we'll integrate qt/research/windowtransitions into main before 4.4. -
466 // Talk to Richard, Trenton or Bjoern. -
467#if defined(Q_WS_MAC) -
468 if (justRegister) { -
469 QMacWindowFader::currentFader()->setFadeDuration(MenuFadeTimeInSec); -
470 QMacWindowFader::currentFader()->registerWindowToFade(menu); -
471 } else { -
472 macWindowFade(qt_mac_window_for(menu), MenuFadeTimeInSec); -
473 } -
474 -
475#endif // Q_WS_MAC -
476 } -
477 aboutToHide = false; -
478 menu->blockSignals(false); -
479#endif // QT_NO_EFFECTS -
480 if (!justRegister) -
481 menu->close(); -
482} -
483 -
484void QMenuPrivate::popupAction(QAction *action, int delay, bool activateFirst) -
485{ -
486 Q_Q(QMenu); -
487 if (action && action->isEnabled()) { -
488 if (!delay) -
489 q->internalDelayedPopup(); -
490 else if (!menuDelayTimer.isActive() && (!action->menu() || !action->menu()->isVisible())) -
491 menuDelayTimer.start(delay, q); -
492 if (activateFirst && action->menu()) -
493 action->menu()->d_func()->setFirstActionActive(); -
494 } else if (QMenu *menu = activeMenu) { //hide the current item -
495 activeMenu = 0; -
496 hideMenu(menu); -
497 } -
498} -
499 -
500void QMenuPrivate::setSyncAction() -
501{ -
502 Q_Q(QMenu); -
503 QAction *current = currentAction; -
504 if(current && (!current->isEnabled() || current->menu() || current->isSeparator())) -
505 current = 0; -
506 for(QWidget *caused = q; caused;) { -
507 if (QMenu *m = qobject_cast<QMenu*>(caused)) { -
508 caused = m->d_func()->causedPopup.widget; -
509 if (m->d_func()->eventLoop) -
510 m->d_func()->syncAction = current; // synchronous operation -
511 } else { -
512 break; -
513 } -
514 } -
515} -
516 -
517 -
518void QMenuPrivate::setFirstActionActive() -
519{ -
520 Q_Q(QMenu); -
521 updateActionRects(); -
522 for(int i = 0, saccum = 0; i < actions.count(); i++) { -
523 const QRect &rect = actionRects.at(i); -
524 if (rect.isNull()) -
525 continue; -
526 if (scroll && scroll->scrollFlags & QMenuScroller::ScrollUp) { -
527 saccum -= rect.height(); -
528 if (saccum > scroll->scrollOffset - scrollerHeight()) -
529 continue; -
530 } -
531 QAction *act = actions.at(i); -
532 if (!act->isSeparator() && -
533 (q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, q) -
534 || act->isEnabled())) { -
535 setCurrentAction(act); -
536 break; -
537 } -
538 } -
539} -
540 -
541// popup == -1 means do not popup, 0 means immediately, others mean use a timer -
542void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason reason, bool activateFirst) -
543{ -
544 Q_Q(QMenu); -
545 tearoffHighlighted = 0; -
546 // Reselect the currently active action in case mouse moved over other menu items when -
547 // moving from sub menu action to sub menu (QTBUG-20094). -
548 if (reason != SelectedFromKeyboard && action == currentAction && !(action && action->menu() && action->menu() != activeMenu)) { -
549 if (QMenu *menu = qobject_cast<QMenu*>(causedPopup.widget)) { -
550 if (causedPopup.action && menu->d_func()->activeMenu == q) -
551 menu->d_func()->setCurrentAction(causedPopup.action, 0, reason, false); -
552 } -
553 return; -
554 } -
555 -
556 if (currentAction) -
557 q->update(actionRect(currentAction)); -
558 -
559 sloppyAction = 0; -
560 if (!sloppyRegion.isEmpty()) -
561 sloppyRegion = QRegion(); -
562 QMenu *hideActiveMenu = activeMenu; -
563#ifndef QT_NO_STATUSTIP -
564 QAction *previousAction = currentAction; -
565#endif -
566 -
567 currentAction = action; -
568 if (action) { -
569 if (!action->isSeparator()) { -
570 activateAction(action, QAction::Hover); -
571 if (popup != -1) { -
572 hideActiveMenu = 0; //will be done "later" -
573 // if the menu is visible then activate the required action, -
574 // otherwise we just mark the action as currentAction -
575 // and activate it when the menu will be popuped. -
576 if (q->isVisible()) -
577 popupAction(currentAction, popup, activateFirst); -
578 } -
579 q->update(actionRect(action)); -
580 -
581 if (reason == SelectedFromKeyboard) { -
582 QWidget *widget = widgetItems.value(action); -
583 if (widget) { -
584 if (widget->focusPolicy() != Qt::NoFocus) -
585 widget->setFocus(Qt::TabFocusReason); -
586 } else { -
587 //when the action has no QWidget, the QMenu itself should -
588 // get the focus -
589 // Since the menu is a pop-up, it uses the popup reason. -
590 if (!q->hasFocus()) { -
591 q->setFocus(Qt::PopupFocusReason); -
592 } -
593 } -
594 } -
595 } else { //action is a separator -
596 if (popup != -1) -
597 hideActiveMenu = 0; //will be done "later" -
598 } -
599#ifndef QT_NO_STATUSTIP -
600 } else if (previousAction) { -
601 previousAction->d_func()->showStatusText(topCausedWidget(), QString()); -
602#endif -
603 } -
604 if (hideActiveMenu) { -
605 activeMenu = 0; -
606#ifndef QT_NO_EFFECTS -
607 // kill any running effect -
608 qFadeEffect(0); -
609 qScrollEffect(0); -
610#endif -
611 hideMenu(hideActiveMenu); -
612 } -
613} -
614 -
615//return the top causedPopup.widget that is not a QMenu -
616QWidget *QMenuPrivate::topCausedWidget() const -
617{ -
618 QWidget* top = causedPopup.widget; -
619 while (QMenu* m = qobject_cast<QMenu *>(top)) -
620 top = m->d_func()->causedPopup.widget; -
621 return top; -
622} -
623 -
624QAction *QMenuPrivate::actionAt(QPoint p) const -
625{ -
626 if (!q_func()->rect().contains(p)) //sanity check -
627 return 0; -
628 -
629 for(int i = 0; i < actionRects.count(); i++) { -
630 if (actionRects.at(i).contains(p)) -
631 return actions.at(i); -
632 } -
633 return 0; -
634} -
635 -
636void QMenuPrivate::setOverrideMenuAction(QAction *a) -
637{ -
638 Q_Q(QMenu); -
639 QObject::disconnect(menuAction, SIGNAL(destroyed()), q, SLOT(_q_overrideMenuActionDestroyed())); -
640 if (a) { -
641 menuAction = a; -
642 QObject::connect(a, SIGNAL(destroyed()), q, SLOT(_q_overrideMenuActionDestroyed())); -
643 } else { //we revert back to the default action created by the QMenu itself -
644 menuAction = defaultMenuAction; -
645 } -
646} -
647 -
648void QMenuPrivate::_q_overrideMenuActionDestroyed() -
649{ -
650 menuAction=defaultMenuAction; -
651} -
652 -
653 -
654void QMenuPrivate::updateLayoutDirection() -
655{ -
656 Q_Q(QMenu); -
657 //we need to mimic the cause of the popup's layout direction -
658 //to allow setting it on a mainwindow for example -
659 //we call setLayoutDirection_helper to not overwrite a user-defined value -
660 if (!q->testAttribute(Qt::WA_SetLayoutDirection)) { -
661 if (QWidget *w = causedPopup.widget) -
662 setLayoutDirection_helper(w->layoutDirection()); -
663 else if (QWidget *w = q->parentWidget()) -
664 setLayoutDirection_helper(w->layoutDirection()); -
665 else -
666 setLayoutDirection_helper(QApplication::layoutDirection()); -
667 } -
668} -
669 -
670 -
671/*! -
672 Returns the action associated with this menu. -
673*/ -
674QAction *QMenu::menuAction() const -
675{ -
676 return d_func()->menuAction; -
677} -
678 -
679/*! -
680 \property QMenu::title -
681 \brief The title of the menu -
682 -
683 This is equivalent to the QAction::text property of the menuAction(). -
684 -
685 By default, this property contains an empty string. -
686*/ -
687QString QMenu::title() const -
688{ -
689 return d_func()->menuAction->text(); -
690} -
691 -
692void QMenu::setTitle(const QString &text) -
693{ -
694 d_func()->menuAction->setText(text); -
695} -
696 -
697/*! -
698 \property QMenu::icon -
699 -
700 \brief The icon of the menu -
701 -
702 This is equivalent to the QAction::icon property of the menuAction(). -
703 -
704 By default, if no icon is explicitly set, this property contains a null icon. -
705*/ -
706QIcon QMenu::icon() const -
707{ -
708 return d_func()->menuAction->icon(); -
709} -
710 -
711void QMenu::setIcon(const QIcon &icon) -
712{ -
713 d_func()->menuAction->setIcon(icon); -
714} -
715 -
716 -
717//actually performs the scrolling -
718void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation location, bool active) -
719{ -
720 Q_Q(QMenu); -
721 if (!scroll || !scroll->scrollFlags) -
722 return; -
723 updateActionRects(); -
724 int newOffset = 0; -
725 const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollerHeight() : 0; -
726 const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollerHeight() : 0; -
727 const int vmargin = q->style()->pixelMetric(QStyle::PM_MenuVMargin, 0, q); -
728 const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, q); -
729 -
730 if (location == QMenuScroller::ScrollTop) { -
731 for(int i = 0, saccum = 0; i < actions.count(); i++) { -
732 if (actions.at(i) == action) { -
733 newOffset = topScroll - saccum; -
734 break; -
735 } -
736 saccum += actionRects.at(i).height(); -
737 } -
738 } else { -
739 for(int i = 0, saccum = 0; i < actions.count(); i++) { -
740 saccum += actionRects.at(i).height(); -
741 if (actions.at(i) == action) { -
742 if (location == QMenuScroller::ScrollCenter) -
743 newOffset = ((q->height() / 2) - botScroll) - (saccum - topScroll); -
744 else -
745 newOffset = (q->height() - botScroll) - saccum; -
746 break; -
747 } -
748 } -
749 if(newOffset) -
750 newOffset -= fw * 2; -
751 } -
752 -
753 //figure out which scroll flags -
754 uint newScrollFlags = QMenuScroller::ScrollNone; -
755 if (newOffset < 0) //easy and cheap one -
756 newScrollFlags |= QMenuScroller::ScrollUp; -
757 int saccum = newOffset; -
758 for(int i = 0; i < actionRects.count(); i++) { -
759 saccum += actionRects.at(i).height(); -
760 if (saccum > q->height()) { -
761 newScrollFlags |= QMenuScroller::ScrollDown; -
762 break; -
763 } -
764 } -
765 -
766 if (!(newScrollFlags & QMenuScroller::ScrollDown) && (scroll->scrollFlags & QMenuScroller::ScrollDown)) { -
767 newOffset = q->height() - (saccum - newOffset) - fw*2 - vmargin; //last item at bottom -
768 } -
769 -
770 if (!(newScrollFlags & QMenuScroller::ScrollUp) && (scroll->scrollFlags & QMenuScroller::ScrollUp)) { -
771 newOffset = 0; //first item at top -
772 } -
773 -
774 if (newScrollFlags & QMenuScroller::ScrollUp) -
775 newOffset -= vmargin; -
776 -
777 QRect screen = popupGeometry(q); -
778 const int desktopFrame = q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, q); -
779 if (q->height() < screen.height()-(desktopFrame*2)-1) { -
780 QRect geom = q->geometry(); -
781 if (newOffset > scroll->scrollOffset && (scroll->scrollFlags & newScrollFlags & QMenuScroller::ScrollUp)) { //scroll up -
782 const int newHeight = geom.height()-(newOffset-scroll->scrollOffset); -
783 if(newHeight > geom.height()) -
784 geom.setHeight(newHeight); -
785 } else if(scroll->scrollFlags & newScrollFlags & QMenuScroller::ScrollDown) { -
786 int newTop = geom.top() + (newOffset-scroll->scrollOffset); -
787 if (newTop < desktopFrame+screen.top()) -
788 newTop = desktopFrame+screen.top(); -
789 if (newTop < geom.top()) { -
790 geom.setTop(newTop); -
791 newOffset = 0; -
792 newScrollFlags &= ~QMenuScroller::ScrollUp; -
793 } -
794 } -
795 if (geom.bottom() > screen.bottom() - desktopFrame) -
796 geom.setBottom(screen.bottom() - desktopFrame); -
797 if (geom.top() < desktopFrame+screen.top()) -
798 geom.setTop(desktopFrame+screen.top()); -
799 if (geom != q->geometry()) { -
800#if 0 -
801 if (newScrollFlags & QMenuScroller::ScrollDown && -
802 q->geometry().top() - geom.top() >= -newOffset) -
803 newScrollFlags &= ~QMenuScroller::ScrollDown; -
804#endif -
805 q->setGeometry(geom); -
806 } -
807 } -
808 -
809 //actually update flags -
810 const int delta = qMin(0, newOffset) - scroll->scrollOffset; //make sure the new offset is always negative -
811 if (!itemsDirty && delta) { -
812 //we've scrolled so we need to update the action rects -
813 for (int i = 0; i < actionRects.count(); ++i) { -
814 QRect &current = actionRects[i]; -
815 current.moveTop(current.top() + delta); -
816 -
817 //we need to update the widgets geometry -
818 if (QWidget *w = widgetItems.value(actions.at(i))) -
819 w->setGeometry(current); -
820 } -
821 } -
822 scroll->scrollOffset += delta; -
823 scroll->scrollFlags = newScrollFlags; -
824 if (active) -
825 setCurrentAction(action); -
826 -
827 q->update(); //issue an update so we see all the new state.. -
828} -
829 -
830void QMenuPrivate::scrollMenu(QMenuScroller::ScrollLocation location, bool active) -
831{ -
832 Q_Q(QMenu); -
833 updateActionRects(); -
834 if(location == QMenuScroller::ScrollBottom) { -
835 for(int i = actions.size()-1; i >= 0; --i) { -
836 QAction *act = actions.at(i); -
837 if (actionRects.at(i).isNull()) -
838 continue; -
839 if (!act->isSeparator() && -
840 (q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, q) -
841 || act->isEnabled())) { -
842 if(scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown) -
843 scrollMenu(act, QMenuPrivate::QMenuScroller::ScrollBottom, active); -
844 else if(active) -
845 setCurrentAction(act, /*popup*/-1, QMenuPrivate::SelectedFromKeyboard); -
846 break; -
847 } -
848 } -
849 } else if(location == QMenuScroller::ScrollTop) { -
850 for(int i = 0; i < actions.size(); ++i) { -
851 QAction *act = actions.at(i); -
852 if (actionRects.at(i).isNull()) -
853 continue; -
854 if (!act->isSeparator() && -
855 (q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, q) -
856 || act->isEnabled())) { -
857 if(scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp) -
858 scrollMenu(act, QMenuPrivate::QMenuScroller::ScrollTop, active); -
859 else if(active) -
860 setCurrentAction(act, /*popup*/-1, QMenuPrivate::SelectedFromKeyboard); -
861 break; -
862 } -
863 } -
864 } -
865} -
866 -
867//only directional -
868void QMenuPrivate::scrollMenu(QMenuScroller::ScrollDirection direction, bool page, bool active) -
869{ -
870 Q_Q(QMenu); -
871 if (!scroll || !(scroll->scrollFlags & direction)) //not really possible... -
872 return; -
873 updateActionRects(); -
874 const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollerHeight() : 0; -
875 const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollerHeight() : 0; -
876 const int vmargin = q->style()->pixelMetric(QStyle::PM_MenuVMargin, 0, q); -
877 const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, q); -
878 const int offset = topScroll ? topScroll-vmargin : 0; -
879 if (direction == QMenuScroller::ScrollUp) { -
880 for(int i = 0, saccum = 0; i < actions.count(); i++) { -
881 saccum -= actionRects.at(i).height(); -
882 if (saccum <= scroll->scrollOffset-offset) { -
883 scrollMenu(actions.at(i), page ? QMenuScroller::ScrollBottom : QMenuScroller::ScrollTop, active); -
884 break; -
885 } -
886 } -
887 } else if (direction == QMenuScroller::ScrollDown) { -
888 bool scrolled = false; -
889 for(int i = 0, saccum = 0; i < actions.count(); i++) { -
890 const int iHeight = actionRects.at(i).height(); -
891 saccum -= iHeight; -
892 if (saccum <= scroll->scrollOffset-offset) { -
893 const int scrollerArea = q->height() - botScroll - fw*2; -
894 int visible = (scroll->scrollOffset-offset) - saccum; -
895 for(i++ ; i < actions.count(); i++) { -
896 visible += actionRects.at(i).height(); -
897 if (visible > scrollerArea - topScroll) { -
898 scrolled = true; -
899 scrollMenu(actions.at(i), page ? QMenuScroller::ScrollTop : QMenuScroller::ScrollBottom, active); -
900 break; -
901 } -
902 } -
903 break; -
904 } -
905 } -
906 if(!scrolled) { -
907 scroll->scrollFlags &= ~QMenuScroller::ScrollDown; -
908 q->update(); -
909 } -
910 } -
911} -
912 -
913/* This is poor-mans eventfilters. This avoids the use of -
914 eventFilter (which can be nasty for users of QMenuBar's). */ -
915bool QMenuPrivate::mouseEventTaken(QMouseEvent *e) -
916{ -
917 Q_Q(QMenu); -
918 QPoint pos = q->mapFromGlobal(e->globalPos()); -
919 if (scroll && !activeMenu) { //let the scroller "steal" the event -
920 bool isScroll = false; -
921 if (pos.x() >= 0 && pos.x() < q->width()) { -
922 for(int dir = QMenuScroller::ScrollUp; dir <= QMenuScroller::ScrollDown; dir = dir << 1) { -
923 if (scroll->scrollFlags & dir) { -
924 if (dir == QMenuScroller::ScrollUp) -
925 isScroll = (pos.y() <= scrollerHeight()); -
926 else if (dir == QMenuScroller::ScrollDown) -
927 isScroll = (pos.y() >= q->height() - scrollerHeight()); -
928 if (isScroll) { -
929 scroll->scrollDirection = dir; -
930 break; -
931 } -
932 } -
933 } -
934 } -
935 if (isScroll) { -
936 scroll->scrollTimer.start(50, q); -
937 return true; -
938 } else { -
939 scroll->scrollTimer.stop(); -
940 } -
941 } -
942 -
943 if (tearoff) { //let the tear off thingie "steal" the event.. -
944 QRect tearRect(0, 0, q->width(), q->style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, q)); -
945 if (scroll && scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp) -
946 tearRect.translate(0, scrollerHeight()); -
947 q->update(tearRect); -
948 if (tearRect.contains(pos) && hasMouseMoved(e->globalPos())) { -
949 setCurrentAction(0); -
950 tearoffHighlighted = 1; -
951 if (e->type() == QEvent::MouseButtonRelease) { -
952 if (!tornPopup) -
953 tornPopup = new QTornOffMenu(q); -
954 tornPopup->setGeometry(q->geometry()); -
955 tornPopup->show(); -
956 hideUpToMenuBar(); -
957 } -
958 return true; -
959 } -
960 tearoffHighlighted = 0; -
961 } -
962 -
963 if (q->frameGeometry().contains(e->globalPos())) //otherwise if the event is in our rect we want it.. -
964 return false; -
965 -
966 for(QWidget *caused = causedPopup.widget; caused;) { -
967 bool passOnEvent = false; -
968 QWidget *next_widget = 0; -
969 QPoint cpos = caused->mapFromGlobal(e->globalPos()); -
970#ifndef QT_NO_MENUBAR -
971 if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) { -
972 passOnEvent = mb->rect().contains(cpos); -
973 } else -
974#endif -
975 if (QMenu *m = qobject_cast<QMenu*>(caused)) { -
976 passOnEvent = m->rect().contains(cpos); -
977 next_widget = m->d_func()->causedPopup.widget; -
978 } -
979 if (passOnEvent) { -
980 if(e->type() != QEvent::MouseButtonRelease || mouseDown == caused) { -
981 QMouseEvent new_e(e->type(), cpos, caused->mapTo(caused->topLevelWidget(), cpos), e->screenPos(), -
982 e->button(), e->buttons(), e->modifiers()); -
983 QApplication::sendEvent(caused, &new_e); -
984 return true; -
985 } -
986 } -
987 if (!next_widget) -
988 break; -
989 caused = next_widget; -
990 } -
991 return false; -
992} -
993 -
994void QMenuPrivate::activateCausedStack(const QList<QPointer<QWidget> > &causedStack, QAction *action, QAction::ActionEvent action_e, bool self) -
995{ -
996 QBoolBlocker guard(activationRecursionGuard); -
997 if(self) -
998 action->activate(action_e); -
999 -
1000 for(int i = 0; i < causedStack.size(); ++i) { -
1001 QPointer<QWidget> widget = causedStack.at(i); -
1002 if (!widget) -
1003 continue; -
1004 //fire -
1005 if (QMenu *qmenu = qobject_cast<QMenu*>(widget)) { -
1006 widget = qmenu->d_func()->causedPopup.widget; -
1007 if (action_e == QAction::Trigger) { -
1008 emit qmenu->triggered(action); -
1009 } else if (action_e == QAction::Hover) { -
1010 emit qmenu->hovered(action); -
1011 } -
1012#ifndef QT_NO_MENUBAR -
1013 } else if (QMenuBar *qmenubar = qobject_cast<QMenuBar*>(widget)) { -
1014 if (action_e == QAction::Trigger) { -
1015 emit qmenubar->triggered(action); -
1016 } else if (action_e == QAction::Hover) { -
1017 emit qmenubar->hovered(action); -
1018 } -
1019 break; //nothing more.. -
1020#endif -
1021 } -
1022 } -
1023} -
1024 -
1025void QMenuPrivate::activateAction(QAction *action, QAction::ActionEvent action_e, bool self) -
1026{ -
1027 Q_Q(QMenu); -
1028#ifndef QT_NO_WHATSTHIS -
1029 bool inWhatsThisMode = QWhatsThis::inWhatsThisMode(); -
1030#endif -
1031 if (!action || !q->isEnabled() -
1032 || (action_e == QAction::Trigger -
1033#ifndef QT_NO_WHATSTHIS -
1034 && !inWhatsThisMode -
1035#endif -
1036 && (action->isSeparator() ||!action->isEnabled()))) -
1037 return; -
1038 -
1039 /* I have to save the caused stack here because it will be undone after popup execution (ie in the hide). -
1040 Then I iterate over the list to actually send the events. --Sam -
1041 */ -
1042 const QList<QPointer<QWidget> > causedStack = calcCausedStack(); -
1043 if (action_e == QAction::Trigger) { -
1044#ifndef QT_NO_WHATSTHIS -
1045 if (!inWhatsThisMode) -
1046 actionAboutToTrigger = action; -
1047#endif -
1048 -
1049 if (q->testAttribute(Qt::WA_DontShowOnScreen)) { -
1050 hideUpToMenuBar(); -
1051 } else { -
1052 for(QWidget *widget = QApplication::activePopupWidget(); widget; ) { -
1053 if (QMenu *qmenu = qobject_cast<QMenu*>(widget)) { -
1054 if(qmenu == q) -
1055 hideUpToMenuBar(); -
1056 widget = qmenu->d_func()->causedPopup.widget; -
1057 } else { -
1058 break; -
1059 } -
1060 } -
1061 } -
1062 -
1063#ifndef QT_NO_WHATSTHIS -
1064 if (inWhatsThisMode) { -
1065 QString s = action->whatsThis(); -
1066 if (s.isEmpty()) -
1067 s = whatsThis; -
1068 QWhatsThis::showText(q->mapToGlobal(actionRect(action).center()), s, q); -
1069 return; -
1070 } -
1071#endif -
1072 } -
1073 -
1074 -
1075 activateCausedStack(causedStack, action, action_e, self); -
1076 -
1077 -
1078 if (action_e == QAction::Hover) { -
1079#ifndef QT_NO_ACCESSIBILITY -
1080 if (QAccessible::isActive()) { -
1081 int actionIndex = indexOf(action); -
1082 QAccessibleEvent focusEvent(q, QAccessible::Focus); -
1083 focusEvent.setChild(actionIndex); -
1084 QAccessible::updateAccessibility(&focusEvent); -
1085 QAccessibleEvent selectionEvent(q, QAccessible::Selection); -
1086 focusEvent.setChild(actionIndex); -
1087 QAccessible::updateAccessibility(&selectionEvent); -
1088 } -
1089#endif -
1090 action->showStatusText(topCausedWidget()); -
1091 } else { -
1092 actionAboutToTrigger = 0; -
1093 } -
1094} -
1095 -
1096void QMenuPrivate::_q_actionTriggered() -
1097{ -
1098 Q_Q(QMenu); -
1099 if (QAction *action = qobject_cast<QAction *>(q->sender())) { -
1100 QPointer<QAction> actionGuard = action; -
1101 emit q->triggered(action); -
1102 if (!activationRecursionGuard && actionGuard) { -
1103 //in case the action has not been activated by the mouse -
1104 //we check the parent hierarchy -
1105 QList< QPointer<QWidget> > list; -
1106 for(QWidget *widget = q->parentWidget(); widget; ) { -
1107 if (qobject_cast<QMenu*>(widget) -
1108#ifndef QT_NO_MENUBAR -
1109 || qobject_cast<QMenuBar*>(widget) -
1110#endif -
1111 ) { -
1112 list.append(widget); -
1113 widget = widget->parentWidget(); -
1114 } else { -
1115 break; -
1116 } -
1117 } -
1118 activateCausedStack(list, action, QAction::Trigger, false); -
1119 } -
1120 } -
1121} -
1122 -
1123void QMenuPrivate::_q_actionHovered() -
1124{ -
1125 Q_Q(QMenu); -
1126 if (QAction * action = qobject_cast<QAction *>(q->sender())) { -
1127 emit q->hovered(action); -
1128 } -
1129} -
1130 -
1131bool QMenuPrivate::hasMouseMoved(const QPoint &globalPos) -
1132{ -
1133 //determines if the mouse has moved (ie its initial position has -
1134 //changed by more than QApplication::startDragDistance() -
1135 //or if there were at least 6 mouse motions) -
1136 return motions > 6 || -
1137 QApplication::startDragDistance() < (mousePopupPos - globalPos).manhattanLength(); -
1138} -
1139 -
1140 -
1141/*! -
1142 Initialize \a option with the values from this menu and information from \a action. This method -
1143 is useful for subclasses when they need a QStyleOptionMenuItem, but don't want -
1144 to fill in all the information themselves. -
1145 -
1146 \sa QStyleOption::initFrom(), QMenuBar::initStyleOption() -
1147*/ -
1148void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action) const -
1149{ -
1150 if (!option || !action) -
1151 return; -
1152 -
1153 Q_D(const QMenu); -
1154 option->initFrom(this); -
1155 option->palette = palette(); -
1156 option->state = QStyle::State_None; -
1157 -
1158 if (window()->isActiveWindow()) -
1159 option->state |= QStyle::State_Active; -
1160 if (isEnabled() && action->isEnabled() -
1161 && (!action->menu() || action->menu()->isEnabled())) -
1162 option->state |= QStyle::State_Enabled; -
1163 else -
1164 option->palette.setCurrentColorGroup(QPalette::Disabled); -
1165 -
1166 option->font = action->font().resolve(font()); -
1167 option->fontMetrics = QFontMetrics(option->font); -
1168 -
1169 if (d->currentAction && d->currentAction == action && !d->currentAction->isSeparator()) { -
1170 option->state |= QStyle::State_Selected -
1171 | (d->mouseDown ? QStyle::State_Sunken : QStyle::State_None); -
1172 } -
1173 -
1174 option->menuHasCheckableItems = d->hasCheckableItems; -
1175 if (!action->isCheckable()) { -
1176 option->checkType = QStyleOptionMenuItem::NotCheckable; -
1177 } else { -
1178 option->checkType = (action->actionGroup() && action->actionGroup()->isExclusive()) -
1179 ? QStyleOptionMenuItem::Exclusive : QStyleOptionMenuItem::NonExclusive; -
1180 option->checked = action->isChecked(); -
1181 } -
1182 if (action->menu()) -
1183 option->menuItemType = QStyleOptionMenuItem::SubMenu; -
1184 else if (action->isSeparator()) -
1185 option->menuItemType = QStyleOptionMenuItem::Separator; -
1186 else if (d->defaultAction == action) -
1187 option->menuItemType = QStyleOptionMenuItem::DefaultItem; -
1188 else -
1189 option->menuItemType = QStyleOptionMenuItem::Normal; -
1190 if (action->isIconVisibleInMenu()) -
1191 option->icon = action->icon(); -
1192 QString textAndAccel = action->text(); -
1193#ifndef QT_NO_SHORTCUT -
1194 if (textAndAccel.indexOf(QLatin1Char('\t')) == -1) { -
1195 QKeySequence seq = action->shortcut(); -
1196 if (!seq.isEmpty()) -
1197 textAndAccel += QLatin1Char('\t') + seq.toString(QKeySequence::NativeText); -
1198 } -
1199#endif -
1200 option->text = textAndAccel; -
1201 option->tabWidth = d->tabWidth; -
1202 option->maxIconWidth = d->maxIconWidth; -
1203 option->menuRect = rect(); -
1204} -
1205 -
1206/*! -
1207 \class QMenu -
1208 \brief The QMenu class provides a menu widget for use in menu -
1209 bars, context menus, and other popup menus. -
1210 -
1211 \ingroup mainwindow-classes -
1212 \ingroup basicwidgets -
1213 \inmodule QtWidgets -
1214 -
1215 A menu widget is a selection menu. It can be either a pull-down -
1216 menu in a menu bar or a standalone context menu. Pull-down menus -
1217 are shown by the menu bar when the user clicks on the respective -
1218 item or presses the specified shortcut key. Use -
1219 QMenuBar::addMenu() to insert a menu into a menu bar. Context -
1220 menus are usually invoked by some special keyboard key or by -
1221 right-clicking. They can be executed either asynchronously with -
1222 popup() or synchronously with exec(). Menus can also be invoked in -
1223 response to button presses; these are just like context menus -
1224 except for how they are invoked. -
1225 -
1226 \table 100% -
1227 \row -
1228 \li \inlineimage fusion-menu.png -
1229 \li \inlineimage windowsxp-menu.png -
1230 \li \inlineimage macintosh-menu.png -
1231 \endtable -
1232 \caption Fig. A menu shown in \l{Fusion Style Widget Gallery}{Fusion widget style}, -
1233 \l{Windows XP Style Widget Gallery}{Windows XP widget style}, -
1234 and \l{Macintosh Style Widget Gallery}{Macintosh widget style}. -
1235 -
1236 \section1 Actions -
1237 -
1238 A menu consists of a list of action items. Actions are added with -
1239 the addAction(), addActions() and insertAction() functions. An action -
1240 is represented vertically and rendered by QStyle. In addition, actions -
1241 can have a text label, an optional icon drawn on the very left side, -
1242 and shortcut key sequence such as "Ctrl+X". -
1243 -
1244 The existing actions held by a menu can be found with actions(). -
1245 -
1246 There are four kinds of action items: separators, actions that -
1247 show a submenu, widgets, and actions that perform an action. -
1248 Separators are inserted with addSeparator(), submenus with addMenu(), -
1249 and all other items are considered action items. -
1250 -
1251 When inserting action items you usually specify a receiver and a -
1252 slot. The receiver will be notifed whenever the item is -
1253 \l{QAction::triggered()}{triggered()}. In addition, QMenu provides -
1254 two signals, activated() and highlighted(), which signal the -
1255 QAction that was triggered from the menu. -
1256 -
1257 You clear a menu with clear() and remove individual action items -
1258 with removeAction(). -
1259 -
1260 A QMenu can also provide a tear-off menu. A tear-off menu is a -
1261 top-level window that contains a copy of the menu. This makes it -
1262 possible for the user to "tear off" frequently used menus and -
1263 position them in a convenient place on the screen. If you want -
1264 this functionality for a particular menu, insert a tear-off handle -
1265 with setTearOffEnabled(). When using tear-off menus, bear in mind -
1266 that the concept isn't typically used on Microsoft Windows so -
1267 some users may not be familiar with it. Consider using a QToolBar -
1268 instead. -
1269 -
1270 Widgets can be inserted into menus with the QWidgetAction class. -
1271 Instances of this class are used to hold widgets, and are inserted -
1272 into menus with the addAction() overload that takes a QAction. -
1273 -
1274 Conversely, actions can be added to widgets with the addAction(), -
1275 addActions() and insertAction() functions. -
1276 -
1277 \warning To make QMenu visible on the screen, exec() or popup() should be -
1278 used instead of show(). -
1279 -
1280 \section1 QMenu on Qt for Windows CE -
1281 -
1282 If a menu is integrated into the native menubar on Windows Mobile we -
1283 do not support the signals: aboutToHide (), aboutToShow () and hovered (). -
1284 It is not possible to display an icon in a native menu on Windows Mobile. -
1285 -
1286 \section1 QMenu on Mac OS X with Qt build against Cocoa -
1287 -
1288 QMenu can be inserted only once in a menu/menubar. Subsequent insertions will -
1289 have no effect or will result in a disabled menu item. -
1290 -
1291 See the \l{mainwindows/menus}{Menus} example for an example of how -
1292 to use QMenuBar and QMenu in your application. -
1293 -
1294 \b{Important inherited functions:} addAction(), removeAction(), clear(), -
1295 addSeparator(), and addMenu(). -
1296 -
1297 \sa QMenuBar, {fowler}{GUI Design Handbook: Menu, Drop-Down and Pop-Up}, -
1298 {Application Example}, {Menus Example}, {Recent Files Example} -
1299*/ -
1300 -
1301 -
1302/*! -
1303 Constructs a menu with parent \a parent. -
1304 -
1305 Although a popup menu is always a top-level widget, if a parent is -
1306 passed the popup menu will be deleted when that parent is -
1307 destroyed (as with any other QObject). -
1308*/ -
1309QMenu::QMenu(QWidget *parent) -
1310 : QWidget(*new QMenuPrivate, parent, Qt::Popup) -
1311{ -
1312 Q_D(QMenu); -
1313 d->init(); -
1314} -
1315 -
1316/*! -
1317 Constructs a menu with a \a title and a \a parent. -
1318 -
1319 Although a popup menu is always a top-level widget, if a parent is -
1320 passed the popup menu will be deleted when that parent is -
1321 destroyed (as with any other QObject). -
1322 -
1323 \sa title -
1324*/ -
1325QMenu::QMenu(const QString &title, QWidget *parent) -
1326 : QWidget(*new QMenuPrivate, parent, Qt::Popup) -
1327{ -
1328 Q_D(QMenu); -
1329 d->init(); -
1330 d->menuAction->setText(title); -
1331} -
1332 -
1333/*! \internal -
1334 */ -
1335QMenu::QMenu(QMenuPrivate &dd, QWidget *parent) -
1336 : QWidget(dd, parent, Qt::Popup) -
1337{ -
1338 Q_D(QMenu); -
1339 d->init(); -
1340} -
1341 -
1342/*! -
1343 Destroys the menu. -
1344*/ -
1345QMenu::~QMenu() -
1346{ -
1347 Q_D(QMenu); -
1348 if (!d->widgetItems.isEmpty()) { // avoid detach on shared null hash -
1349 QHash<QAction *, QWidget *>::iterator it = d->widgetItems.begin(); -
1350 for (; it != d->widgetItems.end(); ++it) { -
1351 if (QWidget *widget = it.value()) { -
1352 QWidgetAction *action = static_cast<QWidgetAction *>(it.key()); -
1353 action->releaseWidget(widget); -
1354 *it = 0; -
1355 } -
1356 } -
1357 } -
1358 -
1359 if (d->eventLoop) -
1360 d->eventLoop->exit(); -
1361 hideTearOffMenu(); -
1362} -
1363 -
1364/*! -
1365 \overload -
1366 -
1367 This convenience function creates a new action with \a text. -
1368 The function adds the newly created action to the menu's -
1369 list of actions, and returns it. -
1370 -
1371 QMenu takes ownership of the returned QAction. -
1372 -
1373 \sa QWidget::addAction() -
1374*/ -
1375QAction *QMenu::addAction(const QString &text) -
1376{ -
1377 QAction *ret = new QAction(text, this); -
1378 addAction(ret); -
1379 return ret; -
1380} -
1381 -
1382/*! -
1383 \overload -
1384 -
1385 This convenience function creates a new action with an \a icon -
1386 and some \a text. The function adds the newly created action to -
1387 the menu's list of actions, and returns it. -
1388 -
1389 QMenu takes ownership of the returned QAction. -
1390 -
1391 \sa QWidget::addAction() -
1392*/ -
1393QAction *QMenu::addAction(const QIcon &icon, const QString &text) -
1394{ -
1395 QAction *ret = new QAction(icon, text, this); -
1396 addAction(ret); -
1397 return ret; -
1398} -
1399 -
1400/*! -
1401 \overload -
1402 -
1403 This convenience function creates a new action with the text \a -
1404 text and an optional shortcut \a shortcut. The action's -
1405 \l{QAction::triggered()}{triggered()} signal is connected to the -
1406 \a receiver's \a member slot. The function adds the newly created -
1407 action to the menu's list of actions and returns it. -
1408 -
1409 QMenu takes ownership of the returned QAction. -
1410 -
1411 \sa QWidget::addAction() -
1412*/ -
1413QAction *QMenu::addAction(const QString &text, const QObject *receiver, const char* member, const QKeySequence &shortcut) -
1414{ -
1415 QAction *action = new QAction(text, this); -
1416#ifdef QT_NO_SHORTCUT -
1417 Q_UNUSED(shortcut); -
1418#else -
1419 action->setShortcut(shortcut); -
1420#endif -
1421 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member); -
1422 addAction(action); -
1423 return action; -
1424} -
1425 -
1426/*! -
1427 \overload -
1428 -
1429 This convenience function creates a new action with an \a icon and -
1430 some \a text and an optional shortcut \a shortcut. The action's -
1431 \l{QAction::triggered()}{triggered()} signal is connected to the -
1432 \a member slot of the \a receiver object. The function adds the -
1433 newly created action to the menu's list of actions, and returns it. -
1434 -
1435 QMenu takes ownership of the returned QAction. -
1436 -
1437 \sa QWidget::addAction() -
1438*/ -
1439QAction *QMenu::addAction(const QIcon &icon, const QString &text, const QObject *receiver, -
1440 const char* member, const QKeySequence &shortcut) -
1441{ -
1442 QAction *action = new QAction(icon, text, this); -
1443#ifdef QT_NO_SHORTCUT -
1444 Q_UNUSED(shortcut); -
1445#else -
1446 action->setShortcut(shortcut); -
1447#endif -
1448 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member); -
1449 addAction(action); -
1450 return action; -
1451} -
1452 -
1453/*! -
1454 This convenience function adds \a menu as a submenu to this menu. -
1455 It returns \a menu's menuAction(). This menu does not take -
1456 ownership of \a menu. -
1457 -
1458 \sa QWidget::addAction(), QMenu::menuAction() -
1459*/ -
1460QAction *QMenu::addMenu(QMenu *menu) -
1461{ -
1462 QAction *action = menu->menuAction(); -
1463 addAction(action); -
1464 return action; -
1465} -
1466 -
1467/*! -
1468 Appends a new QMenu with \a title to the menu. The menu -
1469 takes ownership of the menu. Returns the new menu. -
1470 -
1471 \sa QWidget::addAction(), QMenu::menuAction() -
1472*/ -
1473QMenu *QMenu::addMenu(const QString &title) -
1474{ -
1475 QMenu *menu = new QMenu(title, this); -
1476 addAction(menu->menuAction()); -
1477 return menu; -
1478} -
1479 -
1480/*! -
1481 Appends a new QMenu with \a icon and \a title to the menu. The menu -
1482 takes ownership of the menu. Returns the new menu. -
1483 -
1484 \sa QWidget::addAction(), QMenu::menuAction() -
1485*/ -
1486QMenu *QMenu::addMenu(const QIcon &icon, const QString &title) -
1487{ -
1488 QMenu *menu = new QMenu(title, this); -
1489 menu->setIcon(icon); -
1490 addAction(menu->menuAction()); -
1491 return menu; -
1492} -
1493 -
1494/*! -
1495 This convenience function creates a new separator action, i.e. an -
1496 action with QAction::isSeparator() returning true, and adds the new -
1497 action to this menu's list of actions. It returns the newly -
1498 created action. -
1499 -
1500 QMenu takes ownership of the returned QAction. -
1501 -
1502 \sa QWidget::addAction() -
1503*/ -
1504QAction *QMenu::addSeparator() -
1505{ -
1506 QAction *action = new QAction(this); -
1507 action->setSeparator(true); -
1508 addAction(action); -
1509 return action; -
1510} -
1511 -
1512/*! -
1513 This convenience function inserts \a menu before action \a before -
1514 and returns the menus menuAction(). -
1515 -
1516 \sa QWidget::insertAction(), addMenu() -
1517*/ -
1518QAction *QMenu::insertMenu(QAction *before, QMenu *menu) -
1519{ -
1520 QAction *action = menu->menuAction(); -
1521 insertAction(before, action); -
1522 return action; -
1523} -
1524 -
1525/*! -
1526 This convenience function creates a new separator action, i.e. an -
1527 action with QAction::isSeparator() returning true. The function inserts -
1528 the newly created action into this menu's list of actions before -
1529 action \a before and returns it. -
1530 -
1531 QMenu takes ownership of the returned QAction. -
1532 -
1533 \sa QWidget::insertAction(), addSeparator() -
1534*/ -
1535QAction *QMenu::insertSeparator(QAction *before) -
1536{ -
1537 QAction *action = new QAction(this); -
1538 action->setSeparator(true); -
1539 insertAction(before, action); -
1540 return action; -
1541} -
1542 -
1543/*! -
1544 This sets the default action to \a act. The default action may have -
1545 a visual cue, depending on the current QStyle. A default action -
1546 usually indicates what will happen by default when a drop occurs. -
1547 -
1548 \sa defaultAction() -
1549*/ -
1550void QMenu::setDefaultAction(QAction *act) -
1551{ -
1552 d_func()->defaultAction = act; -
1553} -
1554 -
1555/*! -
1556 Returns the current default action. -
1557 -
1558 \sa setDefaultAction() -
1559*/ -
1560QAction *QMenu::defaultAction() const -
1561{ -
1562 return d_func()->defaultAction; -
1563} -
1564 -
1565/*! -
1566 \property QMenu::tearOffEnabled -
1567 \brief whether the menu supports being torn off -
1568 -
1569 When true, the menu contains a special tear-off item (often shown as a dashed -
1570 line at the top of the menu) that creates a copy of the menu when it is -
1571 triggered. -
1572 -
1573 This "torn-off" copy lives in a separate window. It contains the same menu -
1574 items as the original menu, with the exception of the tear-off handle. -
1575 -
1576 By default, this property is false. -
1577*/ -
1578void QMenu::setTearOffEnabled(bool b) -
1579{ -
1580 Q_D(QMenu); -
1581 if (d->tearoff == b) -
1582 return; -
1583 if (!b) -
1584 hideTearOffMenu(); -
1585 d->tearoff = b; -
1586 -
1587 d->itemsDirty = true; -
1588 if (isVisible()) -
1589 resize(sizeHint()); -
1590} -
1591 -
1592bool QMenu::isTearOffEnabled() const -
1593{ -
1594 return d_func()->tearoff; -
1595} -
1596 -
1597/*! -
1598 When a menu is torn off a second menu is shown to display the menu -
1599 contents in a new window. When the menu is in this mode and the menu -
1600 is visible returns true; otherwise false. -
1601 -
1602 \sa hideTearOffMenu(), isTearOffEnabled() -
1603*/ -
1604bool QMenu::isTearOffMenuVisible() const -
1605{ -
1606 if (d_func()->tornPopup) -
1607 return d_func()->tornPopup->isVisible(); -
1608 return false; -
1609} -
1610 -
1611/*! -
1612 This function will forcibly hide the torn off menu making it -
1613 disappear from the users desktop. -
1614 -
1615 \sa isTearOffMenuVisible(), isTearOffEnabled() -
1616*/ -
1617void QMenu::hideTearOffMenu() -
1618{ -
1619 if (QWidget *w = d_func()->tornPopup) -
1620 w->close(); -
1621} -
1622 -
1623 -
1624/*! -
1625 Sets the currently highlighted action to \a act. -
1626*/ -
1627void QMenu::setActiveAction(QAction *act) -
1628{ -
1629 Q_D(QMenu); -
1630 d->setCurrentAction(act, 0); -
1631 if (d->scroll) -
1632 d->scrollMenu(act, QMenuPrivate::QMenuScroller::ScrollCenter); -
1633} -
1634 -
1635 -
1636/*! -
1637 Returns the currently highlighted action, or 0 if no -
1638 action is currently highlighted. -
1639*/ -
1640QAction *QMenu::activeAction() const -
1641{ -
1642 return d_func()->currentAction; -
1643} -
1644 -
1645/*! -
1646 \since 4.2 -
1647 -
1648 Returns true if there are no visible actions inserted into the menu, false -
1649 otherwise. -
1650 -
1651 \sa QWidget::actions() -
1652*/ -
1653 -
1654bool QMenu::isEmpty() const -
1655{ -
1656 bool ret = true; -
1657 for(int i = 0; ret && i < actions().count(); ++i) { -
1658 const QAction *action = actions().at(i); -
1659 if (!action->isSeparator() && action->isVisible()) { -
1660 ret = false; -
1661 } -
1662 } -
1663 return ret; -
1664} -
1665 -
1666/*! -
1667 Removes all the menu's actions. Actions owned by the menu and not -
1668 shown in any other widget are deleted. -
1669 -
1670 \sa removeAction() -
1671*/ -
1672void QMenu::clear() -
1673{ -
1674 QList<QAction*> acts = actions(); -
1675 -
1676 for(int i = 0; i < acts.size(); i++) { -
1677 removeAction(acts[i]); -
1678 if (acts[i]->parent() == this && acts[i]->d_func()->widgets.isEmpty()) -
1679 delete acts[i]; -
1680 } -
1681} -
1682 -
1683/*! -
1684 If a menu does not fit on the screen it lays itself out so that it -
1685 does fit. It is style dependent what layout means (for example, on -
1686 Windows it will use multiple columns). -
1687 -
1688 This functions returns the number of columns necessary. -
1689*/ -
1690int QMenu::columnCount() const -
1691{ -
1692 return d_func()->ncols; -
1693} -
1694 -
1695/*! -
1696 Returns the item at \a pt; returns 0 if there is no item there. -
1697*/ -
1698QAction *QMenu::actionAt(const QPoint &pt) const -
1699{ -
1700 if (QAction *ret = d_func()->actionAt(pt)) -
1701 return ret; -
1702 return 0; -
1703} -
1704 -
1705/*! -
1706 Returns the geometry of action \a act. -
1707*/ -
1708QRect QMenu::actionGeometry(QAction *act) const -
1709{ -
1710 return d_func()->actionRect(act); -
1711} -
1712 -
1713/*! -
1714 \reimp -
1715*/ -
1716QSize QMenu::sizeHint() const -
1717{ -
1718 Q_D(const QMenu); -
1719 d->updateActionRects(); -
1720 -
1721 QSize s; -
1722 for (int i = 0; i < d->actionRects.count(); ++i) { -
1723 const QRect &rect = d->actionRects.at(i); -
1724 if (rect.isNull()) -
1725 continue; -
1726 if (rect.bottom() >= s.height()) -
1727 s.setHeight(rect.y() + rect.height()); -
1728 if (rect.right() >= s.width()) -
1729 s.setWidth(rect.x() + rect.width()); -
1730 } -
1731 // Note that the action rects calculated above already include -
1732 // the top and left margins, so we only need to add margins for -
1733 // the bottom and right. -
1734 QStyleOption opt(0); -
1735 opt.init(this); -
1736 const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, this); -
1737 s.rwidth() += style()->pixelMetric(QStyle::PM_MenuHMargin, &opt, this) + fw + d->rightmargin; -
1738 s.rheight() += style()->pixelMetric(QStyle::PM_MenuVMargin, &opt, this) + fw + d->bottommargin; -
1739 -
1740 return style()->sizeFromContents(QStyle::CT_Menu, &opt, -
1741 s.expandedTo(QApplication::globalStrut()), this); -
1742} -
1743 -
1744/*! -
1745 Displays the menu so that the action \a atAction will be at the -
1746 specified \e global position \a p. To translate a widget's local -
1747 coordinates into global coordinates, use QWidget::mapToGlobal(). -
1748 -
1749 When positioning a menu with exec() or popup(), bear in mind that -
1750 you cannot rely on the menu's current size(). For performance -
1751 reasons, the menu adapts its size only when necessary, so in many -
1752 cases, the size before and after the show is different. Instead, -
1753 use sizeHint() which calculates the proper size depending on the -
1754 menu's current contents. -
1755 -
1756 \sa QWidget::mapToGlobal(), exec() -
1757*/ -
1758void QMenu::popup(const QPoint &p, QAction *atAction) -
1759{ -
1760 Q_D(QMenu); -
1761 if (d->scroll) { // reset scroll state from last popup -
1762 if (d->scroll->scrollOffset) -
1763 d->itemsDirty = 1; // sizeHint will be incorrect if there is previous scroll -
1764 d->scroll->scrollOffset = 0; -
1765 d->scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone; -
1766 } -
1767 d->tearoffHighlighted = 0; -
1768 d->motions = 0; -
1769 d->doChildEffects = true; -
1770 d->updateLayoutDirection(); -
1771 -
1772#ifndef QT_NO_MENUBAR -
1773 // if this menu is part of a chain attached to a QMenuBar, set the -
1774 // _NET_WM_WINDOW_TYPE_DROPDOWN_MENU X11 window type -
1775 setAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu, qobject_cast<QMenuBar *>(d->topCausedWidget()) != 0); -
1776#endif -
1777 -
1778 ensurePolished(); // Get the right font -
1779 emit aboutToShow(); -
1780 const bool actionListChanged = d->itemsDirty; -
1781 d->updateActionRects(); -
1782 QPoint pos; -
1783 QPushButton *causedButton = qobject_cast<QPushButton*>(d->causedPopup.widget); -
1784 if (actionListChanged && causedButton) -
1785 pos = QPushButtonPrivate::get(causedButton)->adjustedMenuPosition(); -
1786 else -
1787 pos = p; -
1788 -
1789 QSize size = sizeHint(); -
1790 QRect screen; -
1791#ifndef QT_NO_GRAPHICSVIEW -
1792 bool isEmbedded = !bypassGraphicsProxyWidget(this) && d->nearestGraphicsProxyWidget(this); -
1793 if (isEmbedded) -
1794 screen = d->popupGeometry(this); -
1795 else -
1796#endif -
1797 screen = d->popupGeometry(QApplication::desktop()->screenNumber(p)); -
1798 const int desktopFrame = style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, this); -
1799 bool adjustToDesktop = !window()->testAttribute(Qt::WA_DontShowOnScreen); -
1800 -
1801 // if the screens have very different geometries and the menu is too big, we have to recalculate -
1802 if (size.height() > screen.height() || size.width() > screen.width()) { -
1803 size = d->adjustMenuSizeForScreen(screen); -
1804 adjustToDesktop = true; -
1805 } -
1806 // Layout is not right, we might be able to save horizontal space -
1807 if (d->ncols >1 && size.height() < screen.height()) { -
1808 size = d->adjustMenuSizeForScreen(screen); -
1809 adjustToDesktop = true; -
1810 } -
1811 -
1812#ifdef QT_KEYPAD_NAVIGATION -
1813 if (!atAction && QApplication::keypadNavigationEnabled()) { -
1814 // Try to have one item activated -
1815 if (d->defaultAction && d->defaultAction->isEnabled()) { -
1816 atAction = d->defaultAction; -
1817 // TODO: This works for first level menus, not yet sub menus -
1818 } else { -
1819 foreach (QAction *action, d->actions) -
1820 if (action->isEnabled()) { -
1821 atAction = action; -
1822 break; -
1823 } -
1824 } -
1825 d->currentAction = atAction; -
1826 } -
1827#endif -
1828 if (d->ncols > 1) { -
1829 pos.setY(screen.top() + desktopFrame); -
1830 } else if (atAction) { -
1831 for (int i = 0, above_height = 0; i < d->actions.count(); i++) { -
1832 QAction *action = d->actions.at(i); -
1833 if (action == atAction) { -
1834 int newY = pos.y() - above_height; -
1835 if (d->scroll && newY < desktopFrame) { -
1836 d->scroll->scrollFlags = d->scroll->scrollFlags -
1837 | QMenuPrivate::QMenuScroller::ScrollUp; -
1838 d->scroll->scrollOffset = newY; -
1839 newY = desktopFrame; -
1840 } -
1841 pos.setY(newY); -
1842 -
1843 if (d->scroll && d->scroll->scrollFlags != QMenuPrivate::QMenuScroller::ScrollNone -
1844 && !style()->styleHint(QStyle::SH_Menu_FillScreenWithScroll, 0, this)) { -
1845 int below_height = above_height + d->scroll->scrollOffset; -
1846 for (int i2 = i; i2 < d->actionRects.count(); i2++) -
1847 below_height += d->actionRects.at(i2).height(); -
1848 size.setHeight(below_height); -
1849 } -
1850 break; -
1851 } else { -
1852 above_height += d->actionRects.at(i).height(); -
1853 } -
1854 } -
1855 } -
1856 -
1857 QPoint mouse = QCursor::pos(); -
1858 d->mousePopupPos = mouse; -
1859 const bool snapToMouse = !d->causedPopup.widget && (QRect(p.x() - 3, p.y() - 3, 6, 6).contains(mouse)); -
1860 -
1861 const QSize menuSize(sizeHint()); -
1862 if (adjustToDesktop) { -
1863 // handle popup falling "off screen" -
1864 if (isRightToLeft()) { -
1865 if (snapToMouse) // position flowing left from the mouse -
1866 pos.setX(mouse.x() - size.width()); -
1867 -
1868#ifndef QT_NO_MENUBAR -
1869 // if in a menubar, it should be right-aligned -
1870 if (qobject_cast<QMenuBar*>(d->causedPopup.widget)) -
1871 pos.rx() -= size.width(); -
1872#endif //QT_NO_MENUBAR -
1873 -
1874 if (pos.x() < screen.left() + desktopFrame) -
1875 pos.setX(qMax(p.x(), screen.left() + desktopFrame)); -
1876 if (pos.x() + size.width() - 1 > screen.right() - desktopFrame) -
1877 pos.setX(qMax(p.x() - size.width(), screen.right() - desktopFrame - size.width() + 1)); -
1878 } else { -
1879 if (pos.x() + size.width() - 1 > screen.right() - desktopFrame) -
1880 pos.setX(screen.right() - desktopFrame - size.width() + 1); -
1881 if (pos.x() < screen.left() + desktopFrame) -
1882 pos.setX(screen.left() + desktopFrame); -
1883 } -
1884 if (pos.y() + size.height() - 1 > screen.bottom() - desktopFrame) { -
1885 if(snapToMouse) -
1886 pos.setY(qMin(mouse.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1)); -
1887 else -
1888 pos.setY(qMax(p.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1)); -
1889 } else if (pos.y() < screen.top() + desktopFrame) { -
1890 pos.setY(screen.top() + desktopFrame); -
1891 } -
1892 -
1893 if (pos.y() < screen.top() + desktopFrame) -
1894 pos.setY(screen.top() + desktopFrame); -
1895 if (pos.y() + menuSize.height() - 1 > screen.bottom() - desktopFrame) { -
1896 if (d->scroll) { -
1897 d->scroll->scrollFlags |= uint(QMenuPrivate::QMenuScroller::ScrollDown); -
1898 int y = qMax(screen.y(),pos.y()); -
1899 size.setHeight(screen.bottom() - (desktopFrame * 2) - y); -
1900 } else { -
1901 // Too big for screen, bias to see bottom of menu (for some reason) -
1902 pos.setY(screen.bottom() - size.height() + 1); -
1903 } -
1904 } -
1905 } -
1906 const int subMenuOffset = style()->pixelMetric(QStyle::PM_SubMenuOverlap, 0, this); -
1907 QMenu *caused = qobject_cast<QMenu*>(d_func()->causedPopup.widget); -
1908 if (caused && caused->geometry().width() + menuSize.width() + subMenuOffset < screen.width()) { -
1909 QRect parentActionRect(caused->d_func()->actionRect(caused->d_func()->currentAction)); -
1910 const QPoint actionTopLeft = caused->mapToGlobal(parentActionRect.topLeft()); -
1911 parentActionRect.moveTopLeft(actionTopLeft); -
1912 if (isRightToLeft()) { -
1913 if ((pos.x() + menuSize.width() > parentActionRect.left() - subMenuOffset) -
1914 && (pos.x() < parentActionRect.right())) -
1915 { -
1916 pos.rx() = parentActionRect.left() - menuSize.width(); -
1917 if (pos.x() < screen.x()) -
1918 pos.rx() = parentActionRect.right(); -
1919 if (pos.x() + menuSize.width() > screen.x() + screen.width()) -
1920 pos.rx() = screen.x(); -
1921 } -
1922 } else { -
1923 if ((pos.x() < parentActionRect.right() + subMenuOffset) -
1924 && (pos.x() + menuSize.width() > parentActionRect.left())) -
1925 { -
1926 pos.rx() = parentActionRect.right(); -
1927 if (pos.x() + menuSize.width() > screen.x() + screen.width()) -
1928 pos.rx() = parentActionRect.left() - menuSize.width(); -
1929 if (pos.x() < screen.x()) -
1930 pos.rx() = screen.x() + screen.width() - menuSize.width(); -
1931 } -
1932 } -
1933 } -
1934 setGeometry(QRect(pos, size)); -
1935#ifndef QT_NO_EFFECTS -
1936 int hGuess = isRightToLeft() ? QEffects::LeftScroll : QEffects::RightScroll; -
1937 int vGuess = QEffects::DownScroll; -
1938 if (isRightToLeft()) { -
1939 if ((snapToMouse && (pos.x() + size.width() / 2 > mouse.x())) || -
1940 (qobject_cast<QMenu*>(d->causedPopup.widget) && pos.x() + size.width() / 2 > d->causedPopup.widget->x())) -
1941 hGuess = QEffects::RightScroll; -
1942 } else { -
1943 if ((snapToMouse && (pos.x() + size.width() / 2 < mouse.x())) || -
1944 (qobject_cast<QMenu*>(d->causedPopup.widget) && pos.x() + size.width() / 2 < d->causedPopup.widget->x())) -
1945 hGuess = QEffects::LeftScroll; -
1946 } -
1947 -
1948#ifndef QT_NO_MENUBAR -
1949 if ((snapToMouse && (pos.y() + size.height() / 2 < mouse.y())) || -
1950 (qobject_cast<QMenuBar*>(d->causedPopup.widget) && -
1951 pos.y() + size.width() / 2 < d->causedPopup.widget->mapToGlobal(d->causedPopup.widget->pos()).y())) -
1952 vGuess = QEffects::UpScroll; -
1953#endif -
1954 if (QApplication::isEffectEnabled(Qt::UI_AnimateMenu)) { -
1955 bool doChildEffects = true; -
1956#ifndef QT_NO_MENUBAR -
1957 if (QMenuBar *mb = qobject_cast<QMenuBar*>(d->causedPopup.widget)) { -
1958 doChildEffects = mb->d_func()->doChildEffects; -
1959 mb->d_func()->doChildEffects = false; -
1960 } else -
1961#endif -
1962 if (QMenu *m = qobject_cast<QMenu*>(d->causedPopup.widget)) { -
1963 doChildEffects = m->d_func()->doChildEffects; -
1964 m->d_func()->doChildEffects = false; -
1965 } -
1966 -
1967 if (doChildEffects) { -
1968 if (QApplication::isEffectEnabled(Qt::UI_FadeMenu)) -
1969 qFadeEffect(this); -
1970 else if (d->causedPopup.widget) -
1971 qScrollEffect(this, qobject_cast<QMenu*>(d->causedPopup.widget) ? hGuess : vGuess); -
1972 else -
1973 qScrollEffect(this, hGuess | vGuess); -
1974 } else { -
1975 // kill any running effect -
1976 qFadeEffect(0); -
1977 qScrollEffect(0); -
1978 -
1979 show(); -
1980 } -
1981 } else -
1982#endif -
1983 { -
1984 show(); -
1985 } -
1986 -
1987#ifndef QT_NO_ACCESSIBILITY -
1988 QAccessibleEvent event(this, QAccessible::PopupMenuStart); -
1989 QAccessible::updateAccessibility(&event); -
1990#endif -
1991} -
1992 -
1993/*! -
1994 Executes this menu synchronously. -
1995 -
1996 This is equivalent to \c{exec(pos())}. -
1997 -
1998 This returns the triggered QAction in either the popup menu or one -
1999 of its submenus, or 0 if no item was triggered (normally because -
2000 the user pressed Esc). -
2001 -
2002 In most situations you'll want to specify the position yourself, -
2003 for example, the current mouse position: -
2004 \snippet code/src_gui_widgets_qmenu.cpp 0 -
2005 or aligned to a widget: -
2006 \snippet code/src_gui_widgets_qmenu.cpp 1 -
2007 or in reaction to a QMouseEvent *e: -
2008 \snippet code/src_gui_widgets_qmenu.cpp 2 -
2009*/ -
2010QAction *QMenu::exec() -
2011{ -
2012 return exec(pos()); -
2013} -
2014 -
2015 -
2016/*! -
2017 \overload -
2018 -
2019 Executes this menu synchronously. -
2020 -
2021 Pops up the menu so that the action \a action will be at the -
2022 specified \e global position \a p. To translate a widget's local -
2023 coordinates into global coordinates, use QWidget::mapToGlobal(). -
2024 -
2025 This returns the triggered QAction in either the popup menu or one -
2026 of its submenus, or 0 if no item was triggered (normally because -
2027 the user pressed Esc). -
2028 -
2029 Note that all signals are emitted as usual. If you connect a -
2030 QAction to a slot and call the menu's exec(), you get the result -
2031 both via the signal-slot connection and in the return value of -
2032 exec(). -
2033 -
2034 Common usage is to position the menu at the current mouse -
2035 position: -
2036 \snippet code/src_gui_widgets_qmenu.cpp 3 -
2037 or aligned to a widget: -
2038 \snippet code/src_gui_widgets_qmenu.cpp 4 -
2039 or in reaction to a QMouseEvent *e: -
2040 \snippet code/src_gui_widgets_qmenu.cpp 5 -
2041 -
2042 When positioning a menu with exec() or popup(), bear in mind that -
2043 you cannot rely on the menu's current size(). For performance -
2044 reasons, the menu adapts its size only when necessary. So in many -
2045 cases, the size before and after the show is different. Instead, -
2046 use sizeHint() which calculates the proper size depending on the -
2047 menu's current contents. -
2048 -
2049 \sa popup(), QWidget::mapToGlobal() -
2050*/ -
2051QAction *QMenu::exec(const QPoint &p, QAction *action) -
2052{ -
2053 Q_D(QMenu); -
2054 createWinId(); -
2055 QEventLoop eventLoop; -
2056 d->eventLoop = &eventLoop; -
2057 popup(p, action); -
2058 -
2059 QPointer<QObject> guard = this; -
2060 (void) eventLoop.exec(); -
2061 if (guard.isNull()) -
2062 return 0; -
2063 -
2064 action = d->syncAction; -
2065 d->syncAction = 0; -
2066 d->eventLoop = 0; -
2067 return action; -
2068} -
2069 -
2070/*! -
2071 \overload -
2072 -
2073 Executes a menu synchronously. -
2074 -
2075 The menu's actions are specified by the list of \a actions. The menu will -
2076 pop up so that the specified action, \a at, appears at global position \a -
2077 pos. If \a at is not specified then the menu appears at position \a -
2078 pos. \a parent is the menu's parent widget; specifying the parent will -
2079 provide context when \a pos alone is not enough to decide where the menu -
2080 should go (e.g., with multiple desktops or when the parent is embedded in -
2081 QGraphicsView). -
2082 -
2083 The function returns the triggered QAction in either the popup -
2084 menu or one of its submenus, or 0 if no item was triggered -
2085 (normally because the user pressed Esc). -
2086 -
2087 This is equivalent to: -
2088 \snippet code/src_gui_widgets_qmenu.cpp 6 -
2089 -
2090 \sa popup(), QWidget::mapToGlobal() -
2091*/ -
2092QAction *QMenu::exec(QList<QAction*> actions, const QPoint &pos, QAction *at, QWidget *parent) -
2093{ -
2094 QMenu menu(parent); -
2095 menu.addActions(actions); -
2096 return menu.exec(pos, at); -
2097} -
2098 -
2099/*! -
2100 \reimp -
2101*/ -
2102void QMenu::hideEvent(QHideEvent *) -
2103{ -
2104 Q_D(QMenu); -
2105 emit aboutToHide(); -
2106 if (d->eventLoop) -
2107 d->eventLoop->exit(); -
2108 d->setCurrentAction(0); -
2109#ifndef QT_NO_ACCESSIBILITY -
2110 QAccessibleEvent event(this, QAccessible::PopupMenuEnd); -
2111 QAccessible::updateAccessibility(&event); -
2112#endif -
2113#ifndef QT_NO_MENUBAR -
2114 if (QMenuBar *mb = qobject_cast<QMenuBar*>(d->causedPopup.widget)) -
2115 mb->d_func()->setCurrentAction(0); -
2116#endif -
2117 d->mouseDown = 0; -
2118 d->hasHadMouse = false; -
2119 d->causedPopup.widget = 0; -
2120 d->causedPopup.action = 0; -
2121 if (d->scroll) -
2122 d->scroll->scrollTimer.stop(); //make sure the timer stops -
2123} -
2124 -
2125/*! -
2126 \reimp -
2127*/ -
2128void QMenu::paintEvent(QPaintEvent *e) -
2129{ -
2130 Q_D(QMenu); -
2131 d->updateActionRects(); -
2132 QPainter p(this); -
2133 QRegion emptyArea = QRegion(rect()); -
2134 -
2135 QStyleOptionMenuItem menuOpt; -
2136 menuOpt.initFrom(this); -
2137 menuOpt.state = QStyle::State_None; -
2138 menuOpt.checkType = QStyleOptionMenuItem::NotCheckable; -
2139 menuOpt.maxIconWidth = 0; -
2140 menuOpt.tabWidth = 0; -
2141 style()->drawPrimitive(QStyle::PE_PanelMenu, &menuOpt, &p, this); -
2142 -
2143 //draw the items that need updating.. -
2144 for (int i = 0; i < d->actions.count(); ++i) { -
2145 QAction *action = d->actions.at(i); -
2146 QRect adjustedActionRect = d->actionRects.at(i); -
2147 if (!e->rect().intersects(adjustedActionRect) -
2148 || d->widgetItems.value(action)) -
2149 continue; -
2150 //set the clip region to be extra safe (and adjust for the scrollers) -
2151 QRegion adjustedActionReg(adjustedActionRect); -
2152 emptyArea -= adjustedActionReg; -
2153 p.setClipRegion(adjustedActionReg); -
2154 -
2155 QStyleOptionMenuItem opt; -
2156 initStyleOption(&opt, action); -
2157 opt.rect = adjustedActionRect; -
2158 style()->drawControl(QStyle::CE_MenuItem, &opt, &p, this); -
2159 } -
2160 -
2161 const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, this); -
2162 //draw the scroller regions.. -
2163 if (d->scroll) { -
2164 menuOpt.menuItemType = QStyleOptionMenuItem::Scroller; -
2165 menuOpt.state |= QStyle::State_Enabled; -
2166 if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp) { -
2167 menuOpt.rect.setRect(fw, fw, width() - (fw * 2), d->scrollerHeight()); -
2168 emptyArea -= QRegion(menuOpt.rect); -
2169 p.setClipRect(menuOpt.rect); -
2170 style()->drawControl(QStyle::CE_MenuScroller, &menuOpt, &p, this); -
2171 } -
2172 if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown) { -
2173 menuOpt.rect.setRect(fw, height() - d->scrollerHeight() - fw, width() - (fw * 2), -
2174 d->scrollerHeight()); -
2175 emptyArea -= QRegion(menuOpt.rect); -
2176 menuOpt.state |= QStyle::State_DownArrow; -
2177 p.setClipRect(menuOpt.rect); -
2178 style()->drawControl(QStyle::CE_MenuScroller, &menuOpt, &p, this); -
2179 } -
2180 } -
2181 //paint the tear off.. -
2182 if (d->tearoff) { -
2183 menuOpt.menuItemType = QStyleOptionMenuItem::TearOff; -
2184 menuOpt.rect.setRect(fw, fw, width() - (fw * 2), -
2185 style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, this)); -
2186 if (d->scroll && d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp) -
2187 menuOpt.rect.translate(0, d->scrollerHeight()); -
2188 emptyArea -= QRegion(menuOpt.rect); -
2189 p.setClipRect(menuOpt.rect); -
2190 menuOpt.state = QStyle::State_None; -
2191 if (d->tearoffHighlighted) -
2192 menuOpt.state |= QStyle::State_Selected; -
2193 style()->drawControl(QStyle::CE_MenuTearoff, &menuOpt, &p, this); -
2194 } -
2195 //draw border -
2196 if (fw) { -
2197 QRegion borderReg; -
2198 borderReg += QRect(0, 0, fw, height()); //left -
2199 borderReg += QRect(width()-fw, 0, fw, height()); //right -
2200 borderReg += QRect(0, 0, width(), fw); //top -
2201 borderReg += QRect(0, height()-fw, width(), fw); //bottom -
2202 p.setClipRegion(borderReg); -
2203 emptyArea -= borderReg; -
2204 QStyleOptionFrame frame; -
2205 frame.rect = rect(); -
2206 frame.palette = palette(); -
2207 frame.state = QStyle::State_None; -
2208 frame.lineWidth = style()->pixelMetric(QStyle::PM_MenuPanelWidth); -
2209 frame.midLineWidth = 0; -
2210 style()->drawPrimitive(QStyle::PE_FrameMenu, &frame, &p, this); -
2211 } -
2212 -
2213 //finally the rest of the space -
2214 p.setClipRegion(emptyArea); -
2215 menuOpt.state = QStyle::State_None; -
2216 menuOpt.menuItemType = QStyleOptionMenuItem::EmptyArea; -
2217 menuOpt.checkType = QStyleOptionMenuItem::NotCheckable; -
2218 menuOpt.rect = rect(); -
2219 menuOpt.menuRect = rect(); -
2220 style()->drawControl(QStyle::CE_MenuEmptyArea, &menuOpt, &p, this); -
2221} -
2222 -
2223#ifndef QT_NO_WHEELEVENT -
2224/*! -
2225 \reimp -
2226*/ -
2227void QMenu::wheelEvent(QWheelEvent *e) -
2228{ -
2229 Q_D(QMenu); -
2230 if (d->scroll && rect().contains(e->pos())) -
2231 d->scrollMenu(e->delta() > 0 ? -
2232 QMenuPrivate::QMenuScroller::ScrollUp : QMenuPrivate::QMenuScroller::ScrollDown); -
2233} -
2234#endif -
2235 -
2236/*! -
2237 \reimp -
2238*/ -
2239void QMenu::mousePressEvent(QMouseEvent *e) -
2240{ -
2241 Q_D(QMenu); -
2242 if (d->aboutToHide || d->mouseEventTaken(e)) -
2243 return; -
2244 if (!rect().contains(e->pos())) { -
2245 if (d->noReplayFor -
2246 && QRect(d->noReplayFor->mapToGlobal(QPoint()), d->noReplayFor->size()).contains(e->globalPos())) -
2247 setAttribute(Qt::WA_NoMouseReplay); -
2248 if (d->eventLoop) // synchronous operation -
2249 d->syncAction = 0; -
2250 d->hideUpToMenuBar(); -
2251 return; -
2252 } -
2253 d->mouseDown = this; -
2254 -
2255 QAction *action = d->actionAt(e->pos()); -
2256 d->setCurrentAction(action, 20); -
2257 update(); -
2258} -
2259 -
2260/*! -
2261 \reimp -
2262*/ -
2263void QMenu::mouseReleaseEvent(QMouseEvent *e) -
2264{ -
2265 Q_D(QMenu); -
2266 if (d->aboutToHide || d->mouseEventTaken(e)) -
2267 return; -
2268 if(d->mouseDown != this) { -
2269 d->mouseDown = 0; -
2270 return; -
2271 } -
2272 -
2273 d->mouseDown = 0; -
2274 d->setSyncAction(); -
2275 QAction *action = d->actionAt(e->pos()); -
2276 -
2277 if (action && action == d->currentAction) { -
2278 if (!action->menu()){ -
2279#if defined(Q_OS_WIN) -
2280 //On Windows only context menus can be activated with the right button -
2281 if (e->button() == Qt::LeftButton || d->topCausedWidget() == 0) -
2282#endif -
2283 d->activateAction(action, QAction::Trigger); -
2284 } -
2285 } else if (d->hasMouseMoved(e->globalPos())) { -
2286 d->hideUpToMenuBar(); -
2287 } -
2288} -
2289 -
2290/*! -
2291 \reimp -
2292*/ -
2293void QMenu::changeEvent(QEvent *e) -
2294{ -
2295 Q_D(QMenu); -
2296 if (e->type() == QEvent::StyleChange || e->type() == QEvent::FontChange || -
2297 e->type() == QEvent::LayoutDirectionChange) { -
2298 d->itemsDirty = 1; -
2299 setMouseTracking(style()->styleHint(QStyle::SH_Menu_MouseTracking, 0, this)); -
2300 if (isVisible()) -
2301 resize(sizeHint()); -
2302 if (!style()->styleHint(QStyle::SH_Menu_Scrollable, 0, this)) { -
2303 delete d->scroll; -
2304 d->scroll = 0; -
2305 } else if (!d->scroll) { -
2306 d->scroll = new QMenuPrivate::QMenuScroller; -
2307 d->scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone; -
2308 } -
2309 } else if (e->type() == QEvent::EnabledChange) { -
2310 if (d->tornPopup) // torn-off menu -
2311 d->tornPopup->setEnabled(isEnabled()); -
2312 d->menuAction->setEnabled(isEnabled()); -
2313 if (d->platformMenu) -
2314 d->platformMenu->setEnabled(isEnabled()); -
2315 } -
2316 QWidget::changeEvent(e); -
2317} -
2318 -
2319 -
2320/*! -
2321 \reimp -
2322*/ -
2323bool -
2324QMenu::event(QEvent *e) -
2325{ -
2326 Q_D(QMenu); -
2327 switch (e->type()) { -
2328 case QEvent::Polish: -
2329 d->updateLayoutDirection(); -
2330 break; -
2331 case QEvent::ShortcutOverride: { -
2332 QKeyEvent *kev = static_cast<QKeyEvent*>(e); -
2333 if (kev->key() == Qt::Key_Up || kev->key() == Qt::Key_Down -
2334 || kev->key() == Qt::Key_Left || kev->key() == Qt::Key_Right -
2335 || kev->key() == Qt::Key_Enter || kev->key() == Qt::Key_Return -
2336 || kev->key() == Qt::Key_Escape) { -
2337 e->accept(); -
2338 return true; -
2339 } -
2340 } -
2341 break; -
2342 case QEvent::KeyPress: { -
2343 QKeyEvent *ke = (QKeyEvent*)e; -
2344 if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) { -
2345 keyPressEvent(ke); -
2346 return true; -
2347 } -
2348 } break; -
2349 case QEvent::ContextMenu: -
2350 if(d->menuDelayTimer.isActive()) { -
2351 d->menuDelayTimer.stop(); -
2352 internalDelayedPopup(); -
2353 } -
2354 break; -
2355 case QEvent::Resize: { -
2356 QStyleHintReturnMask menuMask; -
2357 QStyleOption option; -
2358 option.initFrom(this); -
2359 if (style()->styleHint(QStyle::SH_Menu_Mask, &option, this, &menuMask)) { -
2360 setMask(menuMask.region); -
2361 } -
2362 d->itemsDirty = 1; -
2363 d->updateActionRects(); -
2364 break; } -
2365 case QEvent::Show: -
2366 d->mouseDown = 0; -
2367 d->updateActionRects(); -
2368 if (d->currentAction) -
2369 d->popupAction(d->currentAction, 0, false); -
2370 break; -
2371#ifndef QT_NO_WHATSTHIS -
2372 case QEvent::QueryWhatsThis: -
2373 e->setAccepted(d->whatsThis.size()); -
2374 if (QAction *action = d->actionAt(static_cast<QHelpEvent*>(e)->pos())) { -
2375 if (action->whatsThis().size() || action->menu()) -
2376 e->accept(); -
2377 } -
2378 return true; -
2379#endif -
2380 default: -
2381 break; -
2382 } -
2383 return QWidget::event(e); -
2384} -
2385 -
2386/*! -
2387 \reimp -
2388*/ -
2389bool QMenu::focusNextPrevChild(bool next) -
2390{ -
2391 setFocus(); -
2392 QKeyEvent ev(QEvent::KeyPress, next ? Qt::Key_Tab : Qt::Key_Backtab, Qt::NoModifier); -
2393 keyPressEvent(&ev); -
2394 return true; -
2395} -
2396 -
2397/*! -
2398 \reimp -
2399*/ -
2400void QMenu::keyPressEvent(QKeyEvent *e) -
2401{ -
2402 Q_D(QMenu);
executed (the execution status of this line is deduced): QMenuPrivate * const d = d_func();
-
2403 d->updateActionRects();
executed (the execution status of this line is deduced): d->updateActionRects();
-
2404 int key = e->key();
executed (the execution status of this line is deduced): int key = e->key();
-
2405 if (isRightToLeft()) { // in reverse mode open/close key for submenues are reversed
partially evaluated: isRightToLeft()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:41
0-41
2406 if (key == Qt::Key_Left)
never evaluated: key == Qt::Key_Left
0
2407 key = Qt::Key_Right;
never executed: key = Qt::Key_Right;
0
2408 else if (key == Qt::Key_Right)
never evaluated: key == Qt::Key_Right
0
2409 key = Qt::Key_Left;
never executed: key = Qt::Key_Left;
0
2410 } -
2411#ifndef Q_OS_MAC -
2412 if (key == Qt::Key_Tab) //means down
evaluated: key == Qt::Key_Tab
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:40
1-40
2413 key = Qt::Key_Down;
executed: key = Qt::Key_Down;
Execution Count:1
1
2414 if (key == Qt::Key_Backtab) //means up
partially evaluated: key == Qt::Key_Backtab
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:41
0-41
2415 key = Qt::Key_Up;
never executed: key = Qt::Key_Up;
0
2416#endif -
2417 -
2418 bool key_consumed = false;
executed (the execution status of this line is deduced): bool key_consumed = false;
-
2419 switch(key) { -
2420 case Qt::Key_Home: -
2421 key_consumed = true;
never executed (the execution status of this line is deduced): key_consumed = true;
-
2422 if (d->scroll)
never evaluated: d->scroll
0
2423 d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollTop, true);
never executed: d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollTop, true);
0
2424 break;
never executed: break;
0
2425 case Qt::Key_End: -
2426 key_consumed = true;
never executed (the execution status of this line is deduced): key_consumed = true;
-
2427 if (d->scroll)
never evaluated: d->scroll
0
2428 d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollBottom, true);
never executed: d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollBottom, true);
0
2429 break;
never executed: break;
0
2430 case Qt::Key_PageUp: -
2431 key_consumed = true;
never executed (the execution status of this line is deduced): key_consumed = true;
-
2432 if (d->currentAction && d->scroll) {
never evaluated: d->currentAction
never evaluated: d->scroll
0
2433 if(d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
never evaluated: d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp
0
2434 d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollUp, true, true);
never executed: d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollUp, true, true);
0
2435 else -
2436 d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollTop, true);
never executed: d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollTop, true);
0
2437 } -
2438 break;
never executed: break;
0
2439 case Qt::Key_PageDown: -
2440 key_consumed = true;
never executed (the execution status of this line is deduced): key_consumed = true;
-
2441 if (d->currentAction && d->scroll) {
never evaluated: d->currentAction
never evaluated: d->scroll
0
2442 if(d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)
never evaluated: d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown
0
2443 d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollDown, true, true);
never executed: d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollDown, true, true);
0
2444 else -
2445 d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollBottom, true);
never executed: d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollBottom, true);
0
2446 } -
2447 break;
never executed: break;
0
2448 case Qt::Key_Up: -
2449 case Qt::Key_Down: { -
2450 key_consumed = true;
executed (the execution status of this line is deduced): key_consumed = true;
-
2451 QAction *nextAction = 0;
executed (the execution status of this line is deduced): QAction *nextAction = 0;
-
2452 QMenuPrivate::QMenuScroller::ScrollLocation scroll_loc = QMenuPrivate::QMenuScroller::ScrollStay;
executed (the execution status of this line is deduced): QMenuPrivate::QMenuScroller::ScrollLocation scroll_loc = QMenuPrivate::QMenuScroller::ScrollStay;
-
2453 if (!d->currentAction) {
evaluated: !d->currentAction
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:17
2-17
2454 if(key == Qt::Key_Down) {
partially evaluated: key == Qt::Key_Down
TRUEFALSE
yes
Evaluation Count:2
no
Evaluation Count:0
0-2
2455 for(int i = 0; i < d->actions.count(); ++i) {
partially evaluated: i < d->actions.count()
TRUEFALSE
yes
Evaluation Count:2
no
Evaluation Count:0
0-2
2456 QAction *act = d->actions.at(i);
executed (the execution status of this line is deduced): QAction *act = d->actions.at(i);
-
2457 if (d->actionRects.at(i).isNull())
partially evaluated: d->actionRects.at(i).isNull()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:2
0-2
2458 continue;
never executed: continue;
0
2459 if (!act->isSeparator() &&
partially evaluated: !act->isSeparator()
TRUEFALSE
yes
Evaluation Count:2
no
Evaluation Count:0
0-2
2460 (style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, this)
partially evaluated: style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, this)
TRUEFALSE
yes
Evaluation Count:2
no
Evaluation Count:0
0-2
2461 || act->isEnabled())) {
never evaluated: act->isEnabled()
0
2462 nextAction = act;
executed (the execution status of this line is deduced): nextAction = act;
-
2463 break;
executed: break;
Execution Count:2
2
2464 } -
2465 }
never executed: }
0
2466 } else {
executed: }
Execution Count:2
2
2467 for(int i = d->actions.count()-1; i >= 0; --i) {
never evaluated: i >= 0
0
2468 QAction *act = d->actions.at(i);
never executed (the execution status of this line is deduced): QAction *act = d->actions.at(i);
-
2469 if (d->actionRects.at(i).isNull())
never evaluated: d->actionRects.at(i).isNull()
0
2470 continue;
never executed: continue;
0
2471 if (!act->isSeparator() &&
never evaluated: !act->isSeparator()
0
2472 (style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, this)
never evaluated: style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, this)
0
2473 || act->isEnabled())) {
never evaluated: act->isEnabled()
0
2474 nextAction = act;
never executed (the execution status of this line is deduced): nextAction = act;
-
2475 break;
never executed: break;
0
2476 } -
2477 }
never executed: }
0
2478 }
never executed: }
0
2479 } else { -
2480 for(int i = 0, y = 0; !nextAction && i < d->actions.count(); i++) {
partially evaluated: !nextAction
TRUEFALSE
yes
Evaluation Count:35
no
Evaluation Count:0
partially evaluated: i < d->actions.count()
TRUEFALSE
yes
Evaluation Count:35
no
Evaluation Count:0
0-35
2481 QAction *act = d->actions.at(i);
executed (the execution status of this line is deduced): QAction *act = d->actions.at(i);
-
2482 if (act == d->currentAction) {
evaluated: act == d->currentAction
TRUEFALSE
yes
Evaluation Count:17
yes
Evaluation Count:18
17-18
2483 if (key == Qt::Key_Up) {
evaluated: key == Qt::Key_Up
TRUEFALSE
yes
Evaluation Count:4
yes
Evaluation Count:13
4-13
2484 for(int next_i = i-1; true; next_i--) {
partially evaluated: true
TRUEFALSE
yes
Evaluation Count:4
no
Evaluation Count:0
0-4
2485 if (next_i == -1) {
partially evaluated: next_i == -1
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:4
0-4
2486 if(!style()->styleHint(QStyle::SH_Menu_SelectionWrap, 0, this))
never evaluated: !style()->styleHint(QStyle::SH_Menu_SelectionWrap, 0, this)
0
2487 break;
never executed: break;
0
2488 if (d->scroll)
never evaluated: d->scroll
0
2489 scroll_loc = QMenuPrivate::QMenuScroller::ScrollBottom;
never executed: scroll_loc = QMenuPrivate::QMenuScroller::ScrollBottom;
0
2490 next_i = d->actionRects.count()-1;
never executed (the execution status of this line is deduced): next_i = d->actionRects.count()-1;
-
2491 }
never executed: }
0
2492 QAction *next = d->actions.at(next_i);
executed (the execution status of this line is deduced): QAction *next = d->actions.at(next_i);
-
2493 if (next == d->currentAction)
partially evaluated: next == d->currentAction
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:4
0-4
2494 break;
never executed: break;
0
2495 if (d->actionRects.at(next_i).isNull())
partially evaluated: d->actionRects.at(next_i).isNull()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:4
0-4
2496 continue;
never executed: continue;
0
2497 if (next->isSeparator() ||
partially evaluated: next->isSeparator()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:4
0-4
2498 (!next->isEnabled() &&
partially evaluated: !next->isEnabled()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:4
0-4
2499 !style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, this)))
never evaluated: !style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, this)
0
2500 continue;
never executed: continue;
0
2501 nextAction = next;
executed (the execution status of this line is deduced): nextAction = next;
-
2502 if (d->scroll && (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)) {
partially evaluated: d->scroll
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:4
never evaluated: (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
0-4
2503 int topVisible = d->scrollerHeight();
never executed (the execution status of this line is deduced): int topVisible = d->scrollerHeight();
-
2504 if (d->tearoff)
never evaluated: d->tearoff
0
2505 topVisible += style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, this);
never executed: topVisible += style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, this);
0
2506 if (((y + d->scroll->scrollOffset) - topVisible) <= d->actionRects.at(next_i).height())
never evaluated: ((y + d->scroll->scrollOffset) - topVisible) <= d->actionRects.at(next_i).height()
0
2507 scroll_loc = QMenuPrivate::QMenuScroller::ScrollTop;
never executed: scroll_loc = QMenuPrivate::QMenuScroller::ScrollTop;
0
2508 }
never executed: }
0
2509 break;
executed: break;
Execution Count:4
4
2510 } -
2511 if (!nextAction && d->tearoff)
partially evaluated: !nextAction
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:4
never evaluated: d->tearoff
0-4
2512 d->tearoffHighlighted = 1;
never executed: d->tearoffHighlighted = 1;
0
2513 } else {
executed: }
Execution Count:4
4
2514 y += d->actionRects.at(i).height();
executed (the execution status of this line is deduced): y += d->actionRects.at(i).height();
-
2515 for(int next_i = i+1; true; next_i++) {
partially evaluated: true
TRUEFALSE
yes
Evaluation Count:14
no
Evaluation Count:0
0-14
2516 if (next_i == d->actionRects.count()) {
partially evaluated: next_i == d->actionRects.count()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:14
0-14
2517 if(!style()->styleHint(QStyle::SH_Menu_SelectionWrap, 0, this))
never evaluated: !style()->styleHint(QStyle::SH_Menu_SelectionWrap, 0, this)
0
2518 break;
never executed: break;
0
2519 if (d->scroll)
never evaluated: d->scroll
0
2520 scroll_loc = QMenuPrivate::QMenuScroller::ScrollTop;
never executed: scroll_loc = QMenuPrivate::QMenuScroller::ScrollTop;
0
2521 next_i = 0;
never executed (the execution status of this line is deduced): next_i = 0;
-
2522 }
never executed: }
0
2523 QAction *next = d->actions.at(next_i);
executed (the execution status of this line is deduced): QAction *next = d->actions.at(next_i);
-
2524 if (next == d->currentAction)
partially evaluated: next == d->currentAction
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:14
0-14
2525 break;
never executed: break;
0
2526 if (d->actionRects.at(next_i).isNull())
partially evaluated: d->actionRects.at(next_i).isNull()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:14
0-14
2527 continue;
never executed: continue;
0
2528 if (next->isSeparator() ||
evaluated: next->isSeparator()
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:13
1-13
2529 (!next->isEnabled() &&
evaluated: !next->isEnabled()
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:12
1-12
2530 !style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, this)))
partially evaluated: !style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, this)
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:1
0-1
2531 continue;
executed: continue;
Execution Count:1
1
2532 nextAction = next;
executed (the execution status of this line is deduced): nextAction = next;
-
2533 if (d->scroll && (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)) {
partially evaluated: d->scroll
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:13
never evaluated: (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)
0-13
2534 int bottomVisible = height() - d->scrollerHeight();
never executed (the execution status of this line is deduced): int bottomVisible = height() - d->scrollerHeight();
-
2535 if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
never evaluated: d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp
0
2536 bottomVisible -= d->scrollerHeight();
never executed: bottomVisible -= d->scrollerHeight();
0
2537 if (d->tearoff)
never evaluated: d->tearoff
0
2538 bottomVisible -= style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, this);
never executed: bottomVisible -= style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, this);
0
2539 if ((y + d->scroll->scrollOffset + d->actionRects.at(next_i).height()) > bottomVisible)
never evaluated: (y + d->scroll->scrollOffset + d->actionRects.at(next_i).height()) > bottomVisible
0
2540 scroll_loc = QMenuPrivate::QMenuScroller::ScrollBottom;
never executed: scroll_loc = QMenuPrivate::QMenuScroller::ScrollBottom;
0
2541 }
never executed: }
0
2542 break;
executed: break;
Execution Count:13
13
2543 } -
2544 }
executed: }
Execution Count:13
13
2545 break;
executed: break;
Execution Count:17
17
2546 } -
2547 y += d->actionRects.at(i).height();
executed (the execution status of this line is deduced): y += d->actionRects.at(i).height();
-
2548 }
executed: }
Execution Count:18
18
2549 }
executed: }
Execution Count:17
17
2550 if (nextAction) {
partially evaluated: nextAction
TRUEFALSE
yes
Evaluation Count:19
no
Evaluation Count:0
0-19
2551 if (d->scroll && scroll_loc != QMenuPrivate::QMenuScroller::ScrollStay) {
partially evaluated: d->scroll
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:19
never evaluated: scroll_loc != QMenuPrivate::QMenuScroller::ScrollStay
0-19
2552 d->scroll->scrollTimer.stop();
never executed (the execution status of this line is deduced): d->scroll->scrollTimer.stop();
-
2553 d->scrollMenu(nextAction, scroll_loc);
never executed (the execution status of this line is deduced): d->scrollMenu(nextAction, scroll_loc);
-
2554 }
never executed: }
0
2555 d->setCurrentAction(nextAction, /*popup*/-1, QMenuPrivate::SelectedFromKeyboard);
executed (the execution status of this line is deduced): d->setCurrentAction(nextAction, -1, QMenuPrivate::SelectedFromKeyboard);
-
2556 }
executed: }
Execution Count:19
19
2557 break; }
executed: break;
Execution Count:19
19
2558 -
2559 case Qt::Key_Right: -
2560 if (d->currentAction && d->currentAction->isEnabled() && d->currentAction->menu()) {
partially evaluated: d->currentAction
TRUEFALSE
yes
Evaluation Count:3
no
Evaluation Count:0
evaluated: d->currentAction->isEnabled()
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:1
evaluated: d->currentAction->menu()
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:1
0-3
2561 d->popupAction(d->currentAction, 0, true);
executed (the execution status of this line is deduced): d->popupAction(d->currentAction, 0, true);
-
2562 key_consumed = true;
executed (the execution status of this line is deduced): key_consumed = true;
-
2563 break;
executed: break;
Execution Count:1
1
2564 } -
2565 //FALL THROUGH -
2566 case Qt::Key_Left: { -
2567 if (d->currentAction && !d->scroll) {
partially evaluated: d->currentAction
TRUEFALSE
yes
Evaluation Count:4
no
Evaluation Count:0
partially evaluated: !d->scroll
TRUEFALSE
yes
Evaluation Count:4
no
Evaluation Count:0
0-4
2568 QAction *nextAction = 0;
executed (the execution status of this line is deduced): QAction *nextAction = 0;
-
2569 if (key == Qt::Key_Left) {
evaluated: key == Qt::Key_Left
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:2
2
2570 QRect actionR = d->actionRect(d->currentAction);
executed (the execution status of this line is deduced): QRect actionR = d->actionRect(d->currentAction);
-
2571 for(int x = actionR.left()-1; !nextAction && x >= 0; x--)
partially evaluated: !nextAction
TRUEFALSE
yes
Evaluation Count:8
no
Evaluation Count:0
evaluated: x >= 0
TRUEFALSE
yes
Evaluation Count:6
yes
Evaluation Count:2
0-8
2572 nextAction = d->actionAt(QPoint(x, actionR.center().y()));
executed: nextAction = d->actionAt(QPoint(x, actionR.center().y()));
Execution Count:6
6
2573 } else {
executed: }
Execution Count:2
2
2574 QRect actionR = d->actionRect(d->currentAction);
executed (the execution status of this line is deduced): QRect actionR = d->actionRect(d->currentAction);
-
2575 for(int x = actionR.right()+1; !nextAction && x < width(); x++)
partially evaluated: !nextAction
TRUEFALSE
yes
Evaluation Count:8
no
Evaluation Count:0
evaluated: x < width()
TRUEFALSE
yes
Evaluation Count:6
yes
Evaluation Count:2
0-8
2576 nextAction = d->actionAt(QPoint(x, actionR.center().y()));
executed: nextAction = d->actionAt(QPoint(x, actionR.center().y()));
Execution Count:6
6
2577 }
executed: }
Execution Count:2
2
2578 if (nextAction) {
partially evaluated: nextAction
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:4
0-4
2579 d->setCurrentAction(nextAction, /*popup*/-1, QMenuPrivate::SelectedFromKeyboard);
never executed (the execution status of this line is deduced): d->setCurrentAction(nextAction, -1, QMenuPrivate::SelectedFromKeyboard);
-
2580 key_consumed = true;
never executed (the execution status of this line is deduced): key_consumed = true;
-
2581 }
never executed: }
0
2582 }
executed: }
Execution Count:4
4
2583 if (!key_consumed && key == Qt::Key_Left && qobject_cast<QMenu*>(d->causedPopup.widget)) {
partially evaluated: !key_consumed
TRUEFALSE
yes
Evaluation Count:4
no
Evaluation Count:0
evaluated: key == Qt::Key_Left
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:2
partially evaluated: qobject_cast<QMenu*>(d->causedPopup.widget)
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:2
0-4
2584 QPointer<QWidget> caused = d->causedPopup.widget;
never executed (the execution status of this line is deduced): QPointer<QWidget> caused = d->causedPopup.widget;
-
2585 d->hideMenu(this);
never executed (the execution status of this line is deduced): d->hideMenu(this);
-
2586 if (caused)
never evaluated: caused
0
2587 caused->setFocus();
never executed: caused->setFocus();
0
2588 key_consumed = true;
never executed (the execution status of this line is deduced): key_consumed = true;
-
2589 }
never executed: }
0
2590 break; }
executed: break;
Execution Count:4
4
2591 -
2592 case Qt::Key_Alt: -
2593 if (d->tornoff)
partially evaluated: d->tornoff
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:1
0-1
2594 break;
never executed: break;
0
2595 -
2596 key_consumed = true;
executed (the execution status of this line is deduced): key_consumed = true;
-
2597 if (style()->styleHint(QStyle::SH_MenuBar_AltKeyNavigation, 0, this))
partially evaluated: style()->styleHint(QStyle::SH_MenuBar_AltKeyNavigation, 0, this)
TRUEFALSE
yes
Evaluation Count:1
no
Evaluation Count:0
0-1
2598 { -
2599 d->hideMenu(this);
executed (the execution status of this line is deduced): d->hideMenu(this);
-
2600#ifndef QT_NO_MENUBAR -
2601 if (QMenuBar *mb = qobject_cast<QMenuBar*>(QApplication::focusWidget())) {
partially evaluated: QMenuBar *mb = qobject_cast<QMenuBar*>(QApplication::focusWidget())
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:1
0-1
2602 mb->d_func()->setKeyboardMode(false);
never executed (the execution status of this line is deduced): mb->d_func()->setKeyboardMode(false);
-
2603 }
never executed: }
0
2604#endif -
2605 }
executed: }
Execution Count:1
1
2606 break;
executed: break;
Execution Count:1
1
2607 -
2608 case Qt::Key_Escape: -
2609#ifdef QT_KEYPAD_NAVIGATION -
2610 case Qt::Key_Back: -
2611#endif -
2612 key_consumed = true;
executed (the execution status of this line is deduced): key_consumed = true;
-
2613 if (d->tornoff) {
partially evaluated: d->tornoff
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:6
0-6
2614 close();
never executed (the execution status of this line is deduced): close();
-
2615 return;
never executed: return;
0
2616 } -
2617 { -
2618 QPointer<QWidget> caused = d->causedPopup.widget;
executed (the execution status of this line is deduced): QPointer<QWidget> caused = d->causedPopup.widget;
-
2619 d->hideMenu(this); // hide after getting causedPopup
executed (the execution status of this line is deduced): d->hideMenu(this);
-
2620#ifndef QT_NO_MENUBAR -
2621 if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) {
evaluated: QMenuBar *mb = qobject_cast<QMenuBar*>(caused)
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:4
2-4
2622 mb->d_func()->setCurrentAction(d->menuAction);
executed (the execution status of this line is deduced): mb->d_func()->setCurrentAction(d->menuAction);
-
2623 mb->d_func()->setKeyboardMode(true);
executed (the execution status of this line is deduced): mb->d_func()->setKeyboardMode(true);
-
2624 }
executed: }
Execution Count:2
2
2625#endif -
2626 } -
2627 break;
executed: break;
Execution Count:6
6
2628 -
2629 case Qt::Key_Space: -
2630 if (!style()->styleHint(QStyle::SH_Menu_SpaceActivatesItem, 0, this))
never evaluated: !style()->styleHint(QStyle::SH_Menu_SpaceActivatesItem, 0, this)
0
2631 break;
never executed: break;
0
2632 // for motif, fall through -
2633#ifdef QT_KEYPAD_NAVIGATION -
2634 case Qt::Key_Select: -
2635#endif -
2636 case Qt::Key_Return: -
2637 case Qt::Key_Enter: { -
2638 if (!d->currentAction) {
partially evaluated: !d->currentAction
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:7
0-7
2639 d->setFirstActionActive();
never executed (the execution status of this line is deduced): d->setFirstActionActive();
-
2640 key_consumed = true;
never executed (the execution status of this line is deduced): key_consumed = true;
-
2641 break;
never executed: break;
0
2642 } -
2643 -
2644 d->setSyncAction();
executed (the execution status of this line is deduced): d->setSyncAction();
-
2645 -
2646 if (d->currentAction->menu())
partially evaluated: d->currentAction->menu()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:7
0-7
2647 d->popupAction(d->currentAction, 0, true);
never executed: d->popupAction(d->currentAction, 0, true);
0
2648 else -
2649 d->activateAction(d->currentAction, QAction::Trigger);
executed: d->activateAction(d->currentAction, QAction::Trigger);
Execution Count:7
7
2650 key_consumed = true;
executed (the execution status of this line is deduced): key_consumed = true;
-
2651 break; }
executed: break;
Execution Count:7
7
2652 -
2653#ifndef QT_NO_WHATSTHIS -
2654 case Qt::Key_F1: -
2655 if (!d->currentAction || d->currentAction->whatsThis().isNull())
never evaluated: !d->currentAction
never evaluated: d->currentAction->whatsThis().isNull()
0
2656 break;
never executed: break;
0
2657 QWhatsThis::enterWhatsThisMode();
never executed (the execution status of this line is deduced): QWhatsThis::enterWhatsThisMode();
-
2658 d->activateAction(d->currentAction, QAction::Trigger);
never executed (the execution status of this line is deduced): d->activateAction(d->currentAction, QAction::Trigger);
-
2659 return;
never executed: return;
0
2660#endif -
2661 default: -
2662 key_consumed = false;
executed (the execution status of this line is deduced): key_consumed = false;
-
2663 }
executed: }
Execution Count:3
3
2664 -
2665 if (!key_consumed) { // send to menu bar
evaluated: !key_consumed
TRUEFALSE
yes
Evaluation Count:7
yes
Evaluation Count:34
7-34
2666 if ((!e->modifiers() || e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ShiftModifier) &&
evaluated: !e->modifiers()
TRUEFALSE
yes
Evaluation Count:6
yes
Evaluation Count:1
partially evaluated: e->modifiers() == Qt::AltModifier
TRUEFALSE
yes
Evaluation Count:1
no
Evaluation Count:0
never evaluated: e->modifiers() == Qt::ShiftModifier
0-6
2667 e->text().length()==1) {
evaluated: e->text().length()==1
TRUEFALSE
yes
Evaluation Count:3
yes
Evaluation Count:4
3-4
2668 bool activateAction = false;
executed (the execution status of this line is deduced): bool activateAction = false;
-
2669 QAction *nextAction = 0;
executed (the execution status of this line is deduced): QAction *nextAction = 0;
-
2670 if (style()->styleHint(QStyle::SH_Menu_KeyboardSearch, 0, this) && !e->modifiers()) {
partially evaluated: style()->styleHint(QStyle::SH_Menu_KeyboardSearch, 0, this)
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:3
never evaluated: !e->modifiers()
0-3
2671 int best_match_count = 0;
never executed (the execution status of this line is deduced): int best_match_count = 0;
-
2672 d->searchBufferTimer.start(2000, this);
never executed (the execution status of this line is deduced): d->searchBufferTimer.start(2000, this);
-
2673 d->searchBuffer += e->text();
never executed (the execution status of this line is deduced): d->searchBuffer += e->text();
-
2674 for(int i = 0; i < d->actions.size(); ++i) {
never evaluated: i < d->actions.size()
0
2675 int match_count = 0;
never executed (the execution status of this line is deduced): int match_count = 0;
-
2676 if (d->actionRects.at(i).isNull())
never evaluated: d->actionRects.at(i).isNull()
0
2677 continue;
never executed: continue;
0
2678 QAction *act = d->actions.at(i);
never executed (the execution status of this line is deduced): QAction *act = d->actions.at(i);
-
2679 const QString act_text = act->text();
never executed (the execution status of this line is deduced): const QString act_text = act->text();
-
2680 for(int c = 0; c < d->searchBuffer.size(); ++c) {
never evaluated: c < d->searchBuffer.size()
0
2681 if(act_text.indexOf(d->searchBuffer.at(c), 0, Qt::CaseInsensitive) != -1)
never evaluated: act_text.indexOf(d->searchBuffer.at(c), 0, Qt::CaseInsensitive) != -1
0
2682 ++match_count;
never executed: ++match_count;
0
2683 }
never executed: }
0
2684 if(match_count > best_match_count) {
never evaluated: match_count > best_match_count
0
2685 best_match_count = match_count;
never executed (the execution status of this line is deduced): best_match_count = match_count;
-
2686 nextAction = act;
never executed (the execution status of this line is deduced): nextAction = act;
-
2687 }
never executed: }
0
2688 }
never executed: }
0
2689 }
never executed: }
0
2690#ifndef QT_NO_SHORTCUT -
2691 else { -
2692 int clashCount = 0;
executed (the execution status of this line is deduced): int clashCount = 0;
-
2693 QAction *first = 0, *currentSelected = 0, *firstAfterCurrent = 0;
executed (the execution status of this line is deduced): QAction *first = 0, *currentSelected = 0, *firstAfterCurrent = 0;
-
2694 QChar c = e->text().at(0).toUpper();
executed (the execution status of this line is deduced): QChar c = e->text().at(0).toUpper();
-
2695 for(int i = 0; i < d->actions.size(); ++i) {
evaluated: i < d->actions.size()
TRUEFALSE
yes
Evaluation Count:11
yes
Evaluation Count:3
3-11
2696 if (d->actionRects.at(i).isNull())
partially evaluated: d->actionRects.at(i).isNull()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:11
0-11
2697 continue;
never executed: continue;
0
2698 QAction *act = d->actions.at(i);
executed (the execution status of this line is deduced): QAction *act = d->actions.at(i);
-
2699 QKeySequence sequence = QKeySequence::mnemonic(act->text());
executed (the execution status of this line is deduced): QKeySequence sequence = QKeySequence::mnemonic(act->text());
-
2700 int key = sequence[0] & 0xffff;
executed (the execution status of this line is deduced): int key = sequence[0] & 0xffff;
-
2701 if (key == c.unicode()) {
evaluated: key == c.unicode()
TRUEFALSE
yes
Evaluation Count:3
yes
Evaluation Count:8
3-8
2702 clashCount++;
executed (the execution status of this line is deduced): clashCount++;
-
2703 if (!first)
partially evaluated: !first
TRUEFALSE
yes
Evaluation Count:3
no
Evaluation Count:0
0-3
2704 first = act;
executed: first = act;
Execution Count:3
3
2705 if (act == d->currentAction)
evaluated: act == d->currentAction
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:2
1-2
2706 currentSelected = act;
executed: currentSelected = act;
Execution Count:1
1
2707 else if (!firstAfterCurrent && currentSelected)
partially evaluated: !firstAfterCurrent
TRUEFALSE
yes
Evaluation Count:2
no
Evaluation Count:0
partially evaluated: currentSelected
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:2
0-2
2708 firstAfterCurrent = act;
never executed: firstAfterCurrent = act;
0
2709 } -
2710 }
executed: }
Execution Count:11
11
2711 if (clashCount == 1)
partially evaluated: clashCount == 1
TRUEFALSE
yes
Evaluation Count:3
no
Evaluation Count:0
0-3
2712 activateAction = true;
executed: activateAction = true;
Execution Count:3
3
2713 if (clashCount >= 1) {
partially evaluated: clashCount >= 1
TRUEFALSE
yes
Evaluation Count:3
no
Evaluation Count:0
0-3
2714 if (clashCount == 1 || !currentSelected || !firstAfterCurrent)
partially evaluated: clashCount == 1
TRUEFALSE
yes
Evaluation Count:3
no
Evaluation Count:0
never evaluated: !currentSelected
never evaluated: !firstAfterCurrent
0-3
2715 nextAction = first;
executed: nextAction = first;
Execution Count:3
3
2716 else -
2717 nextAction = firstAfterCurrent;
never executed: nextAction = firstAfterCurrent;
0
2718 } -
2719 }
executed: }
Execution Count:3
3
2720#endif -
2721 if (nextAction) {
partially evaluated: nextAction
TRUEFALSE
yes
Evaluation Count:3
no
Evaluation Count:0
0-3
2722 key_consumed = true;
executed (the execution status of this line is deduced): key_consumed = true;
-
2723 if(d->scroll)
partially evaluated: d->scroll
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:3
0-3
2724 d->scrollMenu(nextAction, QMenuPrivate::QMenuScroller::ScrollCenter, false);
never executed: d->scrollMenu(nextAction, QMenuPrivate::QMenuScroller::ScrollCenter, false);
0
2725 d->setCurrentAction(nextAction, 200, QMenuPrivate::SelectedFromElsewhere, true);
executed (the execution status of this line is deduced): d->setCurrentAction(nextAction, 0, QMenuPrivate::SelectedFromElsewhere, true);
-
2726 if (!nextAction->menu() && activateAction) {
evaluated: !nextAction->menu()
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:2
partially evaluated: activateAction
TRUEFALSE
yes
Evaluation Count:1
no
Evaluation Count:0
0-2
2727 d->setSyncAction();
executed (the execution status of this line is deduced): d->setSyncAction();
-
2728 d->activateAction(nextAction, QAction::Trigger);
executed (the execution status of this line is deduced): d->activateAction(nextAction, QAction::Trigger);
-
2729 }
executed: }
Execution Count:1
1
2730 }
executed: }
Execution Count:3
3
2731 }
executed: }
Execution Count:3
3
2732 if (!key_consumed) {
evaluated: !key_consumed
TRUEFALSE
yes
Evaluation Count:4
yes
Evaluation Count:3
3-4
2733#ifndef QT_NO_MENUBAR -
2734 if (QMenuBar *mb = qobject_cast<QMenuBar*>(d->topCausedWidget())) {
partially evaluated: QMenuBar *mb = qobject_cast<QMenuBar*>(d->topCausedWidget())
TRUEFALSE
yes
Evaluation Count:4
no
Evaluation Count:0
0-4
2735 QAction *oldAct = mb->d_func()->currentAction;
executed (the execution status of this line is deduced): QAction *oldAct = mb->d_func()->currentAction;
-
2736 QApplication::sendEvent(mb, e);
executed (the execution status of this line is deduced): QApplication::sendEvent(mb, e);
-
2737 if (mb->d_func()->currentAction != oldAct)
partially evaluated: mb->d_func()->currentAction != oldAct
TRUEFALSE
yes
Evaluation Count:4
no
Evaluation Count:0
0-4
2738 key_consumed = true;
executed: key_consumed = true;
Execution Count:4
4
2739 }
executed: }
Execution Count:4
4
2740#endif -
2741 }
executed: }
Execution Count:4
4
2742 -
2743#ifdef Q_OS_WIN32 -
2744 if (key_consumed && (e->key() == Qt::Key_Control || e->key() == Qt::Key_Shift || e->key() == Qt::Key_Meta)) -
2745 QApplication::beep(); -
2746#endif // Q_OS_WIN32 -
2747 }
executed: }
Execution Count:7
7
2748 if (key_consumed)
partially evaluated: key_consumed
TRUEFALSE
yes
Evaluation Count:41
no
Evaluation Count:0
0-41
2749 e->accept();
executed: e->accept();
Execution Count:41
41
2750 else -
2751 e->ignore();
never executed: e->ignore();
0
2752} -
2753 -
2754/*! -
2755 \reimp -
2756*/ -
2757void QMenu::mouseMoveEvent(QMouseEvent *e) -
2758{ -
2759 Q_D(QMenu); -
2760 if (!isVisible() || d->aboutToHide || d->mouseEventTaken(e)) -
2761 return; -
2762 d->motions++; -
2763 if (d->motions == 0) // ignore first mouse move event (see enterEvent()) -
2764 return; -
2765 d->hasHadMouse = d->hasHadMouse || rect().contains(e->pos()); -
2766 -
2767 QAction *action = d->actionAt(e->pos()); -
2768 if (!action) { -
2769 if (d->hasHadMouse -
2770 && (!d->currentAction -
2771 || !(d->currentAction->menu() && d->currentAction->menu()->isVisible()))) -
2772 d->setCurrentAction(0); -
2773 return; -
2774 } else if(e->buttons()) { -
2775 d->mouseDown = this; -
2776 } -
2777 if (d->sloppyRegion.contains(e->pos())) { -
2778 d->sloppyAction = action; -
2779 QMenuPrivate::sloppyDelayTimer = startTimer(style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)*6); -
2780 } else if (action != d->currentAction) { -
2781 d->setCurrentAction(action, style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)); -
2782 } -
2783} -
2784 -
2785/*! -
2786 \reimp -
2787*/ -
2788void QMenu::enterEvent(QEvent *) -
2789{ -
2790 d_func()->motions = -1; // force us to ignore the generate mouse move in mouseMoveEvent() -
2791} -
2792 -
2793/*! -
2794 \reimp -
2795*/ -
2796void QMenu::leaveEvent(QEvent *) -
2797{ -
2798 Q_D(QMenu); -
2799 d->sloppyAction = 0; -
2800 if (!d->sloppyRegion.isEmpty()) -
2801 d->sloppyRegion = QRegion(); -
2802 if (!d->activeMenu && d->currentAction) -
2803 setActiveAction(0); -
2804} -
2805 -
2806/*! -
2807 \reimp -
2808*/ -
2809void -
2810QMenu::timerEvent(QTimerEvent *e) -
2811{ -
2812 Q_D(QMenu); -
2813 if (d->scroll && d->scroll->scrollTimer.timerId() == e->timerId()) { -
2814 d->scrollMenu((QMenuPrivate::QMenuScroller::ScrollDirection)d->scroll->scrollDirection); -
2815 if (d->scroll->scrollFlags == QMenuPrivate::QMenuScroller::ScrollNone) -
2816 d->scroll->scrollTimer.stop(); -
2817 } else if(d->menuDelayTimer.timerId() == e->timerId()) { -
2818 d->menuDelayTimer.stop(); -
2819 internalDelayedPopup(); -
2820 } else if(QMenuPrivate::sloppyDelayTimer == e->timerId()) { -
2821 killTimer(QMenuPrivate::sloppyDelayTimer); -
2822 QMenuPrivate::sloppyDelayTimer = 0; -
2823 internalSetSloppyAction(); -
2824 } else if(d->searchBufferTimer.timerId() == e->timerId()) { -
2825 d->searchBuffer.clear(); -
2826 } -
2827} -
2828 -
2829void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem* item) -
2830{ -
2831 item->setText(action->text()); -
2832 item->setIsSeparator(action->isSeparator()); -
2833 if (action->isIconVisibleInMenu()) -
2834 item->setIcon(action->icon()); -
2835 item->setVisible(action->isVisible()); -
2836 item->setShortcut(action->shortcut()); -
2837 item->setChecked(action->isChecked()); -
2838 item->setFont(action->font()); -
2839 item->setRole((QPlatformMenuItem::MenuRole) action->menuRole()); -
2840 item->setEnabled(action->isEnabled()); -
2841 -
2842 if (action->menu()) { -
2843 item->setMenu(action->menu()->platformMenu()); -
2844 } else { -
2845 item->setMenu(0); -
2846 } -
2847} -
2848 -
2849/*! -
2850 \reimp -
2851*/ -
2852void QMenu::actionEvent(QActionEvent *e) -
2853{ -
2854 Q_D(QMenu); -
2855 d->itemsDirty = 1; -
2856 setAttribute(Qt::WA_Resized, false); -
2857 if (d->tornPopup) -
2858 d->tornPopup->syncWithMenu(this, e); -
2859 if (e->type() == QEvent::ActionAdded) { -
2860 if(!d->tornoff) { -
2861 connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered())); -
2862 connect(e->action(), SIGNAL(hovered()), this, SLOT(_q_actionHovered())); -
2863 } -
2864 if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) { -
2865 QWidget *widget = wa->requestWidget(this); -
2866 if (widget) -
2867 d->widgetItems.insert(wa, widget); -
2868 } -
2869 } else if (e->type() == QEvent::ActionRemoved) { -
2870 e->action()->disconnect(this); -
2871 if (e->action() == d->currentAction) -
2872 d->currentAction = 0; -
2873 if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) { -
2874 if (QWidget *widget = d->widgetItems.value(wa)) -
2875 wa->releaseWidget(widget); -
2876 } -
2877 d->widgetItems.remove(e->action()); -
2878 } -
2879 -
2880 if (d->platformMenu) { -
2881 if (e->type() == QEvent::ActionAdded) { -
2882 QPlatformMenuItem *menuItem = -
2883 QGuiApplicationPrivate::platformTheme()->createPlatformMenuItem(); -
2884 menuItem->setTag(reinterpret_cast<quintptr>(e->action())); -
2885 QObject::connect(menuItem, SIGNAL(activated()), e->action(), SLOT(trigger())); -
2886 copyActionToPlatformItem(e->action(), menuItem); -
2887 QPlatformMenuItem* beforeItem = d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->before())); -
2888 d->platformMenu->insertMenuItem(menuItem, beforeItem); -
2889 } else if (e->type() == QEvent::ActionRemoved) { -
2890 QPlatformMenuItem *menuItem = d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->action())); -
2891 d->platformMenu->removeMenuItem(menuItem); -
2892 } else if (e->type() == QEvent::ActionChanged) { -
2893 QPlatformMenuItem *menuItem = d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->action())); -
2894 copyActionToPlatformItem(e->action(), menuItem); -
2895 d->platformMenu->syncMenuItem(menuItem); -
2896 } -
2897 -
2898 d->platformMenu->syncSeparatorsCollapsible(d->collapsibleSeparators); -
2899 } -
2900 -
2901#if defined(Q_OS_WINCE) && !defined(QT_NO_MENUBAR) -
2902 if (!d->wce_menu) -
2903 d->wce_menu = new QMenuPrivate::QWceMenuPrivate; -
2904 if (e->type() == QEvent::ActionAdded) -
2905 d->wce_menu->addAction(e->action(), d->wce_menu->findAction(e->before())); -
2906 else if (e->type() == QEvent::ActionRemoved) -
2907 d->wce_menu->removeAction(e->action()); -
2908 else if (e->type() == QEvent::ActionChanged) -
2909 d->wce_menu->syncAction(e->action()); -
2910#endif -
2911 -
2912 if (isVisible()) { -
2913 d->updateActionRects(); -
2914 resize(sizeHint()); -
2915 update(); -
2916 } -
2917} -
2918 -
2919/*! -
2920 \internal -
2921*/ -
2922void QMenu::internalSetSloppyAction() -
2923{ -
2924 if (d_func()->sloppyAction) -
2925 d_func()->setCurrentAction(d_func()->sloppyAction, 0); -
2926} -
2927 -
2928/*! -
2929 \internal -
2930*/ -
2931void QMenu::internalDelayedPopup() -
2932{ -
2933 Q_D(QMenu); -
2934 -
2935 //hide the current item -
2936 if (QMenu *menu = d->activeMenu) { -
2937 d->activeMenu = 0; -
2938 d->hideMenu(menu); -
2939 } -
2940 -
2941 if (!d->currentAction || !d->currentAction->isEnabled() || !d->currentAction->menu() || -
2942 !d->currentAction->menu()->isEnabled() || d->currentAction->menu()->isVisible()) -
2943 return; -
2944 -
2945 //setup -
2946 d->activeMenu = d->currentAction->menu(); -
2947 d->activeMenu->d_func()->causedPopup.widget = this; -
2948 d->activeMenu->d_func()->causedPopup.action = d->currentAction; -
2949 -
2950 int subMenuOffset = style()->pixelMetric(QStyle::PM_SubMenuOverlap, 0, this); -
2951 const QRect actionRect(d->actionRect(d->currentAction)); -
2952 const QSize menuSize(d->activeMenu->sizeHint()); -
2953 const QPoint rightPos(mapToGlobal(QPoint(actionRect.right() + subMenuOffset + 1, actionRect.top()))); -
2954 -
2955 QPoint pos(rightPos); -
2956 -
2957 //calc sloppy focus buffer -
2958 if (style()->styleHint(QStyle::SH_Menu_SloppySubMenus, 0, this)) { -
2959 QPoint cur = QCursor::pos(); -
2960 if (actionRect.contains(mapFromGlobal(cur))) { -
2961 QPoint pts[4]; -
2962 pts[0] = QPoint(cur.x(), cur.y() - 2); -
2963 pts[3] = QPoint(cur.x(), cur.y() + 2); -
2964 if (pos.x() >= cur.x()) { -
2965 pts[1] = QPoint(geometry().right(), pos.y()); -
2966 pts[2] = QPoint(geometry().right(), pos.y() + menuSize.height()); -
2967 } else { -
2968 pts[1] = QPoint(pos.x() + menuSize.width(), pos.y()); -
2969 pts[2] = QPoint(pos.x() + menuSize.width(), pos.y() + menuSize.height()); -
2970 } -
2971 QPolygon points(4); -
2972 for(int i = 0; i < 4; i++) -
2973 points.setPoint(i, mapFromGlobal(pts[i])); -
2974 d->sloppyRegion = QRegion(points); -
2975 } -
2976 } -
2977 -
2978 //do the popup -
2979 d->activeMenu->popup(pos); -
2980} -
2981 -
2982/*! -
2983 \fn void QMenu::addAction(QAction *action) -
2984 \overload -
2985 -
2986 Appends the action \a action to the menu's list of actions. -
2987 -
2988 \sa QMenuBar::addAction(), QWidget::addAction() -
2989*/ -
2990 -
2991/*! -
2992 \fn void QMenu::aboutToHide() -
2993 \since 4.2 -
2994 -
2995 This signal is emitted just before the menu is hidden from the user. -
2996 -
2997 \sa aboutToShow(), hide() -
2998*/ -
2999 -
3000/*! -
3001 \fn void QMenu::aboutToShow() -
3002 -
3003 This signal is emitted just before the menu is shown to the user. -
3004 -
3005 \sa aboutToHide(), show() -
3006*/ -
3007 -
3008/*! -
3009 \fn void QMenu::triggered(QAction *action) -
3010 -
3011 This signal is emitted when an action in this menu is triggered. -
3012 -
3013 \a action is the action that caused the signal to be emitted. -
3014 -
3015 Normally, you connect each menu action's \l{QAction::}{triggered()} signal -
3016 to its own custom slot, but sometimes you will want to connect several -
3017 actions to a single slot, for example, when you have a group of closely -
3018 related actions, such as "left justify", "center", "right justify". -
3019 -
3020 \note This signal is emitted for the main parent menu in a hierarchy. -
3021 Hence, only the parent menu needs to be connected to a slot; sub-menus need -
3022 not be connected. -
3023 -
3024 \sa hovered(), QAction::triggered() -
3025*/ -
3026 -
3027/*! -
3028 \fn void QMenu::hovered(QAction *action) -
3029 -
3030 This signal is emitted when a menu action is highlighted; \a action -
3031 is the action that caused the signal to be emitted. -
3032 -
3033 Often this is used to update status information. -
3034 -
3035 \sa triggered(), QAction::hovered() -
3036*/ -
3037 -
3038 -
3039/*!\internal -
3040*/ -
3041void QMenu::setNoReplayFor(QWidget *noReplayFor) -
3042{ -
3043#ifdef Q_OS_WIN -
3044 d_func()->noReplayFor = noReplayFor; -
3045#else -
3046 Q_UNUSED(noReplayFor); -
3047#endif -
3048} -
3049 -
3050/*!\internal -
3051*/ -
3052QPlatformMenu *QMenu::platformMenu() -
3053{ -
3054 -
3055 return d_func()->platformMenu; -
3056} -
3057 -
3058/*! -
3059 \property QMenu::separatorsCollapsible -
3060 \since 4.2 -
3061 -
3062 \brief whether consecutive separators should be collapsed -
3063 -
3064 This property specifies whether consecutive separators in the menu -
3065 should be visually collapsed to a single one. Separators at the -
3066 beginning or the end of the menu are also hidden. -
3067 -
3068 By default, this property is true. -
3069*/ -
3070bool QMenu::separatorsCollapsible() const -
3071{ -
3072 Q_D(const QMenu); -
3073 return d->collapsibleSeparators; -
3074} -
3075 -
3076void QMenu::setSeparatorsCollapsible(bool collapse) -
3077{ -
3078 Q_D(QMenu); -
3079 if (d->collapsibleSeparators == collapse) -
3080 return; -
3081 -
3082 d->collapsibleSeparators = collapse; -
3083 d->itemsDirty = 1; -
3084 if (isVisible()) { -
3085 d->updateActionRects(); -
3086 update(); -
3087 } -
3088 if (d->platformMenu) -
3089 d->platformMenu->syncSeparatorsCollapsible(collapse); -
3090} -
3091 -
3092QT_END_NAMESPACE -
3093 -
3094// for private slots -
3095#include "moc_qmenu.cpp" -
3096#include "qmenu.moc" -
3097 -
3098#endif // QT_NO_MENU -
3099 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial