~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/gui/widgets/qmenubar.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/****************************************************************************
2
2
**
3
3
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
 
4
** All rights reserved.
4
5
** Contact: Nokia Corporation (qt-info@nokia.com)
5
6
**
6
7
** This file is part of the QtGui module of the Qt Toolkit.
7
8
**
8
9
** $QT_BEGIN_LICENSE:LGPL$
9
 
** Commercial Usage
10
 
** Licensees holding valid Qt Commercial licenses may use this file in
11
 
** accordance with the Qt Commercial License Agreement provided with the
12
 
** Software or, alternatively, in accordance with the terms contained in
13
 
** a written agreement between you and Nokia.
 
10
** No Commercial Usage
 
11
** This file contains pre-release code and may not be distributed.
 
12
** You may use this file in accordance with the terms and conditions
 
13
** contained in the Technology Preview License Agreement accompanying
 
14
** this package.
14
15
**
15
16
** GNU Lesser General Public License Usage
16
17
** Alternatively, this file may be used under the terms of the GNU Lesser
20
21
** ensure the GNU Lesser General Public License version 2.1 requirements
21
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22
23
**
23
 
** In addition, as a special exception, Nokia gives you certain
24
 
** additional rights. These rights are described in the Nokia Qt LGPL
25
 
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26
 
** package.
27
 
**
28
 
** GNU General Public License Usage
29
 
** Alternatively, this file may be used under the terms of the GNU
30
 
** General Public License version 3.0 as published by the Free Software
31
 
** Foundation and appearing in the file LICENSE.GPL included in the
32
 
** packaging of this file.  Please review the following information to
33
 
** ensure the GNU General Public License version 3.0 requirements will be
34
 
** met: http://www.gnu.org/copyleft/gpl.html.
35
 
**
36
 
** If you are unsure which license is appropriate for your use, please
37
 
** contact the sales department at http://www.qtsoftware.com/contact.
 
24
** In addition, as a special exception, Nokia gives you certain additional
 
25
** rights.  These rights are described in the Nokia Qt LGPL Exception
 
26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
27
**
 
28
** If you have questions regarding the use of this file, please contact
 
29
** Nokia at qt-info@nokia.com.
 
30
**
 
31
**
 
32
**
 
33
**
 
34
**
 
35
**
 
36
**
 
37
**
38
38
** $QT_END_LICENSE$
39
39
**
40
40
****************************************************************************/
67
67
#include "qmenubar_p.h"
68
68
#include "qdebug.h"
69
69
 
70
 
#ifdef Q_OS_WINCE
 
70
#ifdef Q_WS_WINCE
71
71
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wce.cpp
72
72
#endif
73
73
 
116
116
*/
117
117
QAction *QMenuBarPrivate::actionAt(QPoint p) const
118
118
{
119
 
    Q_Q(const QMenuBar);
120
 
    QList<QAction*> items = q->actions();
121
 
    for(int i = 0; i < items.size(); ++i) {
122
 
        if(actionRect(items.at(i)).contains(p))
123
 
            return items.at(i);
 
119
    for(int i = 0; i < actions.size(); ++i) {
 
120
        if(actionRect(actions.at(i)).contains(p))
 
121
            return actions.at(i);
124
122
    }
125
123
    return 0;
126
124
}
134
132
    result.adjust(hmargin, 0, -hmargin, 0);
135
133
 
136
134
    if (extVisible) {
137
 
        if (q->layoutDirection() == Qt::RightToLeft)
 
135
        if (q->isRightToLeft())
138
136
            result.setLeft(result.left() + extension->sizeHint().width());
139
137
        else
140
138
            result.setWidth(result.width() - extension->sizeHint().width());
142
140
 
143
141
    if (leftWidget && leftWidget->isVisible()) {
144
142
        QSize sz = leftWidget->sizeHint();
145
 
        if (q->layoutDirection() == Qt::RightToLeft)
 
143
        if (q->isRightToLeft())
146
144
            result.setRight(result.right() - sz.width());
147
145
        else
148
146
            result.setLeft(result.left() + sz.width());
150
148
 
151
149
    if (rightWidget && rightWidget->isVisible()) {
152
150
        QSize sz = rightWidget->sizeHint();
153
 
        if (q->layoutDirection() == Qt::RightToLeft)
 
151
        if (q->isRightToLeft())
154
152
            result.setLeft(result.left() + sz.width());
155
153
        else
156
154
            result.setRight(result.right() - sz.width());
194
192
    }
195
193
 
196
194
#ifdef Q_WS_MAC
197
 
    if(mac_menubar) {//nothing to see here folks, move along..
 
195
    if(q->isNativeMenuBar()) {//nothing to see here folks, move along..
198
196
        itemsDirty = false;
199
197
        return;
200
198
    }
201
199
#endif
202
 
    calcActionRects(q_width, q_start, actionRects, actionList);
203
 
    itemsWidth = q_width;
204
 
    itemsStart = q_start;
 
200
    calcActionRects(q_width, q_start);
205
201
    currentAction = 0;
206
202
#ifndef QT_NO_SHORTCUT
207
203
    if(itemsDirty) {
208
204
        for(int j = 0; j < shortcutIndexMap.size(); ++j)
209
205
            q->releaseShortcut(shortcutIndexMap.value(j));
210
206
        shortcutIndexMap.resize(0); // faster than clear
211
 
        for(int i = 0; i < actionList.count(); i++)
212
 
            shortcutIndexMap.append(q->grabShortcut(QKeySequence::mnemonic(actionList.at(i)->text())));
 
207
        for(int i = 0; i < actions.count(); i++)
 
208
            shortcutIndexMap.append(q->grabShortcut(QKeySequence::mnemonic(actions.at(i)->text())));
213
209
    }
214
210
#endif
215
211
    itemsDirty = false;
220
216
 
221
217
    //we try to see if the actions will fit there
222
218
    bool hasHiddenActions = false;
223
 
    foreach(QAction *action, actionList) {
224
 
        if (!menuRect.contains(actionRect(action))) {
 
219
    for (int i = 0; i < actions.count(); ++i) {
 
220
        const QRect &rect = actionRects.at(i);
 
221
        if (rect.isValid() && !menuRect.contains(rect)) {
225
222
            hasHiddenActions = true;
226
223
            break;
227
224
        }
230
227
    //...and if not, determine the ones that fit on the menu with the extension visible
231
228
    if (hasHiddenActions) {
232
229
        menuRect = this->menuRect(true);
233
 
        foreach(QAction *action, actionList) {
234
 
            if (!menuRect.contains(actionRect(action))) {
235
 
                hiddenActions.append(action);
 
230
        for (int i = 0; i < actions.count(); ++i) {
 
231
            const QRect &rect = actionRects.at(i);
 
232
            if (rect.isValid() && !menuRect.contains(rect)) {
 
233
                hiddenActions.append(actions.at(i));
236
234
            }
237
235
        }
238
236
    }
247
245
        pop->addActions(hiddenActions);
248
246
 
249
247
        int vmargin = q->style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, q);
250
 
        int x = q->layoutDirection() == Qt::RightToLeft
 
248
        int x = q->isRightToLeft()
251
249
                ? menuRect.left() - extension->sizeHint().width() + 1
252
250
                : menuRect.right();
253
251
        extension->setGeometry(x, vmargin, extension->sizeHint().width(), menuRect.height() - vmargin*2);
257
255
    }
258
256
    q->updateGeometry();
259
257
#ifdef QT3_SUPPORT
260
 
    if (q->parentWidget() != 0) {
 
258
    if (parent) {
261
259
        QMenubarUpdatedEvent menubarUpdated(q);
262
 
        QApplication::sendEvent(q->parentWidget(), &menubarUpdated);
 
260
        QApplication::sendEvent(parent, &menubarUpdated);
263
261
    }
264
262
#endif
265
263
}
267
265
QRect QMenuBarPrivate::actionRect(QAction *act) const
268
266
{
269
267
    Q_Q(const QMenuBar);
270
 
    QRect ret = actionRects.value(act);
271
 
    const int fw = q->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, q);
272
 
    ret.translate(fw, fw);
 
268
    const int index = actions.indexOf(act);
 
269
    if (index == -1)
 
270
        return QRect();
 
271
 
 
272
    //makes sure the geometries are up-to-date
 
273
    const_cast<QMenuBarPrivate*>(this)->updateGeometries();
 
274
 
 
275
    if (index >= actionRects.count())
 
276
        return QRect(); // that can happen in case of native menubar
 
277
 
 
278
    QRect ret = actionRects.at(index);
273
279
    return QStyle::visualRect(q->layoutDirection(), q->rect(), ret);
274
280
}
275
281
 
 
282
void QMenuBarPrivate::focusFirstAction()
 
283
{
 
284
    if(!currentAction) {
 
285
        updateGeometries();
 
286
        int index = 0;
 
287
        while (index < actions.count() && actionRects.at(index).isNull()) ++index;
 
288
        if (index < actions.count())
 
289
            setCurrentAction(actions.at(index));
 
290
    }
 
291
}
 
292
 
276
293
void QMenuBarPrivate::setKeyboardMode(bool b)
277
294
{
278
295
    Q_Q(QMenuBar);
282
299
    }
283
300
    keyboardState = b;
284
301
    if(b) {
285
 
        QWidget *fw = qApp->focusWidget();
 
302
        QWidget *fw = QApplication::focusWidget();
286
303
        if (fw != q)
287
304
            keyboardFocusWidget = fw;
288
 
        if(!currentAction && !actionList.isEmpty())
289
 
            setCurrentAction(actionList.first());
 
305
        focusFirstAction();
290
306
        q->setFocus(Qt::MenuBarFocusReason);
291
307
    } else {
292
308
        if(!popupState)
293
309
            setCurrentAction(0);
294
310
        if(keyboardFocusWidget) {
295
 
            if (qApp->focusWidget() == q)
 
311
            if (QApplication::focusWidget() == q)
296
312
                keyboardFocusWidget->setFocus(Qt::MenuBarFocusReason);
297
313
            keyboardFocusWidget = 0;
298
314
        }
398
414
        fw->setFocus(Qt::NoFocusReason);
399
415
}
400
416
 
401
 
void QMenuBarPrivate::calcActionRects(int max_width, int start, QMap<QAction*, QRect> &actionRects, QList<QAction*> &actionList) const
 
417
void QMenuBarPrivate::calcActionRects(int max_width, int start) const
402
418
{
403
419
    Q_Q(const QMenuBar);
404
420
 
405
 
    if(!itemsDirty && itemsWidth == max_width && itemsStart == start) {
406
 
        actionRects = actionRects;
407
 
        actionList = actionList;
 
421
    if(!itemsDirty)
408
422
        return;
409
 
    }
410
 
    actionRects.clear();
411
 
    actionList.clear();
412
 
    const int itemSpacing = q->style()->pixelMetric(QStyle::PM_MenuBarItemSpacing, 0, q);
 
423
 
 
424
    //let's reinitialize the buffer
 
425
    actionRects.resize(actions.count());
 
426
    actionRects.fill(QRect());
 
427
 
 
428
    const QStyle *style = q->style();
 
429
 
 
430
    const int itemSpacing = style->pixelMetric(QStyle::PM_MenuBarItemSpacing, 0, q);
413
431
    int max_item_height = 0, separator = -1, separator_start = 0, separator_len = 0;
414
 
    QList<QAction*> items = q->actions();
415
432
 
416
433
    //calculate size
417
434
    const QFontMetrics fm = q->fontMetrics();
418
 
    const int hmargin = q->style()->pixelMetric(QStyle::PM_MenuBarHMargin, 0, q),
419
 
              vmargin = q->style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, q),
420
 
                icone = q->style()->pixelMetric(QStyle::PM_SmallIconSize, 0, q);
421
 
    for(int i = 0; i < items.count(); i++) {
422
 
        QAction *action = items.at(i);
 
435
    const int hmargin = style->pixelMetric(QStyle::PM_MenuBarHMargin, 0, q),
 
436
              vmargin = style->pixelMetric(QStyle::PM_MenuBarVMargin, 0, q),
 
437
                icone = style->pixelMetric(QStyle::PM_SmallIconSize, 0, q);
 
438
    for(int i = 0; i < actions.count(); i++) {
 
439
        QAction *action = actions.at(i);
423
440
        if(!action->isVisible())
424
441
            continue;
425
442
 
427
444
 
428
445
        //calc what I think the size is..
429
446
        if(action->isSeparator()) {
430
 
            if (q->style()->styleHint(QStyle::SH_DrawMenuBarSeparator, 0, q))
431
 
                separator = actionRects.count();
 
447
            if (style->styleHint(QStyle::SH_DrawMenuBarSeparator, 0, q))
 
448
                separator = i;
432
449
            continue; //we don't really position these!
433
450
        } else {
434
 
            QString s = action->text();
435
 
            if(!s.isEmpty()) {
436
 
                int w = fm.width(s);
437
 
                w -= s.count(QLatin1Char('&')) * fm.width(QLatin1Char('&'));
438
 
                w += s.count(QLatin1String("&&")) * fm.width(QLatin1Char('&'));
439
 
                sz = QSize(w, fm.height());
440
 
            }
441
 
 
 
451
            const QString s = action->text();
442
452
            QIcon is = action->icon();
443
 
            if (!is.isNull()) {
444
 
                QSize is_sz = QSize(icone, icone);
445
 
                if (is_sz.height() > sz.height())
446
 
                    sz.setHeight(is_sz.height());
447
 
                if (is_sz.width() > sz.width())
448
 
                    sz.setWidth(is_sz.width());
449
 
            }
 
453
            // If an icon is set, only the icon is visible
 
454
            if (!is.isNull())
 
455
                sz = sz.expandedTo(QSize(icone, icone));
 
456
            else if (!s.isEmpty())
 
457
                sz = fm.size(Qt::TextShowMnemonic, s);
450
458
        }
451
459
 
452
460
        //let the style modify the above size..
456
464
 
457
465
        if(!sz.isEmpty()) {
458
466
            { //update the separator state
459
 
                int iWidth = sz.width();
460
 
                iWidth += itemSpacing;
 
467
                int iWidth = sz.width() + itemSpacing;
461
468
                if(separator == -1)
462
469
                    separator_start += iWidth;
463
470
                else
466
473
            //maximum height
467
474
            max_item_height = qMax(max_item_height, sz.height());
468
475
            //append
469
 
            actionRects.insert(action, QRect(0, 0, sz.width(), sz.height()));
470
 
            actionList.append(action);
 
476
            actionRects[i] = QRect(0, 0, sz.width(), sz.height());
471
477
        }
472
478
    }
473
479
 
474
480
    //calculate position
475
 
    int x = ((start == -1) ? hmargin : start) + itemSpacing;
476
 
    int y = vmargin;
477
 
    for(int i = 0; i < actionList.count(); i++) {
478
 
        QAction *action = actionList.at(i);
479
 
        QRect &rect = actionRects[action];
 
481
    const int fw = q->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, q);
 
482
    int x = fw + ((start == -1) ? hmargin : start) + itemSpacing;
 
483
    int y = fw + vmargin;
 
484
    for(int i = 0; i < actions.count(); i++) {
 
485
        QRect &rect = actionRects[i];
 
486
        if (rect.isNull())
 
487
            continue;
 
488
 
480
489
        //resize
481
490
        rect.setHeight(max_item_height);
482
491
 
532
541
        emit q->hovered(action);
533
542
#ifndef QT_NO_ACCESSIBILITY
534
543
        if (QAccessible::isActive()) {
535
 
            QList<QAction*> actions = q->actions();
536
544
            int actionIndex = actions.indexOf(action);
537
545
            ++actionIndex;
538
546
            QAccessible::updateAccessibility(q, actionIndex, QAccessible::Focus);
582
590
    \class QMenuBar
583
591
    \brief The QMenuBar class provides a horizontal menu bar.
584
592
 
585
 
    \ingroup application
586
 
    \mainclass
 
593
    \ingroup mainwindow-classes
587
594
 
588
595
    A menu bar consists of a list of pull-down menu items. You add
589
596
    menu items with addMenu(). For example, asuming that \c menubar
661
668
    \header \i String matches \i Placement \i Notes
662
669
    \row \i about.*
663
670
         \i Application Menu | About <application name>
664
 
         \i If this entry is not found no About item will appear in
665
 
            the Application Menu
 
671
         \i The application name is fetched from the \c {Info.plist} file
 
672
            (see note below). If this entry is not found no About item
 
673
            will appear in the Application Menu. 
666
674
    \row \i config, options, setup, settings or preferences
667
675
         \i Application Menu | Preferences
668
676
         \i If this entry is not found the Settings item will be disabled
706
714
    \section1 Examples
707
715
 
708
716
    The \l{mainwindows/menus}{Menus} example shows how to use QMenuBar
709
 
    and QMenu.  The other \l{Qt Examples#Main Windows}{main window
 
717
    and QMenu.  The other \l{Main Window Examples}{main window
710
718
    application examples} also provide menus using these classes.
711
719
 
712
720
    \sa QMenu, QShortcut, QAction,
713
 
        {http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/index.html}{Introduction to Apple Human Interface Guidelines},
 
721
        {http://developer.apple.com/documentation/UserExperience/Conceptual/AppleHIGuidelines/XHIGIntro/XHIGIntro.html}{Introduction to Apple Human Interface Guidelines},
714
722
        {fowler}{GUI Design Handbook: Menu Bar}, {Menus Example}
715
723
*/
716
724
 
725
733
    if(mac_menubar)
726
734
        q->hide();
727
735
#endif
728
 
#ifdef Q_OS_WINCE
 
736
#ifdef Q_WS_WINCE
729
737
    if (qt_wince_is_mobile()) {
730
738
        wceCreateMenuBar(q->parentWidget());
731
739
        if(wce_menubar)
732
740
            q->hide();
733
741
    }
734
742
#endif
 
743
#ifdef Q_WS_S60
 
744
    symbianCreateMenuBar(q->parentWidget());
 
745
    if(symbian_menubar)
 
746
        q->hide();
 
747
#endif
 
748
 
735
749
    q->setBackgroundRole(QPalette::Button);
736
750
    oldWindow = oldParent = 0;
737
751
#ifdef QT3_SUPPORT
745
759
    extension->hide();
746
760
}
747
761
 
 
762
//Gets the next action for keyboard navigation
 
763
QAction *QMenuBarPrivate::getNextAction(const int _start, const int increment) const
 
764
{
 
765
    Q_Q(const QMenuBar);
 
766
    const_cast<QMenuBarPrivate*>(this)->updateGeometries();
 
767
    bool allowActiveAndDisabled = q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, q);
 
768
    const int start = (_start == -1 && increment == -1) ? actions.count() : _start;
 
769
    const int end =  increment == -1 ? 0 : actions.count() - 1;
 
770
 
 
771
    for (int i = start; start != end;) {
 
772
        i += increment;
 
773
        QAction *current = actions.at(i);
 
774
        if (!actionRects.at(i).isNull() && (allowActiveAndDisabled || current->isEnabled()))
 
775
            return current;
 
776
    }
 
777
 
 
778
    if (_start != -1) //let's try from the beginning or the end
 
779
        return getNextAction(-1, increment);
 
780
 
 
781
    return 0;
 
782
}
 
783
 
748
784
/*!
749
785
    Constructs a menu bar with parent \a parent.
750
786
*/
776
812
    Q_D(QMenuBar);
777
813
    d->macDestroyMenuBar();
778
814
#endif
779
 
#ifdef Q_OS_WINCE
 
815
#ifdef Q_WS_WINCE
780
816
    Q_D(QMenuBar);
781
817
    if (qt_wince_is_mobile())
782
818
        d->wceDestroyMenuBar();
783
819
#endif
 
820
#ifdef Q_WS_S60
 
821
    Q_D(QMenuBar);
 
822
    d->symbianDestroyMenuBar();
 
823
#endif
784
824
}
785
825
 
786
826
/*!
924
964
/*!
925
965
    Removes all the actions from the menu bar.
926
966
 
 
967
    \note On Mac OS X, menu items that have been merged to the system
 
968
    menu bar are not removed by this function. One way to handle this
 
969
    would be to remove the extra actions yourself. You can set the
 
970
    \l{QAction::MenuRole}{menu role} on the different menus, so that
 
971
    you know ahead of time which menu items get merged and which do
 
972
    not. Then decide what to recreate or remove yourself.
 
973
 
927
974
    \sa removeAction()
928
975
*/
929
976
void QMenuBar::clear()
977
1024
    QRegion emptyArea(rect());
978
1025
 
979
1026
    //draw the items
980
 
    for (int i = 0; i < d->actionList.count(); ++i) {
981
 
        QAction *action = d->actionList.at(i);
 
1027
    for (int i = 0; i < d->actions.count(); ++i) {
 
1028
        QAction *action = d->actions.at(i);
982
1029
        QRect adjustedActionRect = d->actionRect(action);
983
1030
        if (adjustedActionRect.isEmpty() || !d->isVisible(action))
984
1031
            continue;
1025
1072
*/
1026
1073
void QMenuBar::setVisible(bool visible)
1027
1074
{
1028
 
#ifdef Q_WS_MAC
1029
 
    Q_D(QMenuBar);
1030
 
    if(d->mac_menubar)
1031
 
        return;
1032
 
#endif
1033
 
#ifdef Q_OS_WINCE
1034
 
    Q_D(QMenuBar);
1035
 
    if(d->wce_menubar)
 
1075
#if defined(Q_WS_MAC) || defined(Q_OS_WINCE) || defined(Q_WS_S60)
 
1076
    if (isNativeMenuBar())
1036
1077
        return;
1037
1078
#endif
1038
1079
    QWidget::setVisible(visible);
1047
1088
    if(e->button() != Qt::LeftButton)
1048
1089
        return;
1049
1090
 
 
1091
    d->mouseDown = true;
 
1092
 
1050
1093
    QAction *action = d->actionAt(e->pos());
1051
1094
    if (!action || !d->isVisible(action)) {
1052
1095
        d->setCurrentAction(0);
1057
1100
        return;
1058
1101
    }
1059
1102
 
1060
 
    d->mouseDown = true;
1061
 
 
1062
1103
    if(d->currentAction == action && d->popupState) {
1063
1104
        if(QMenu *menu = d->activeMenu) {
1064
1105
            d->activeMenu = 0;
1100
1141
void QMenuBar::keyPressEvent(QKeyEvent *e)
1101
1142
{
1102
1143
    Q_D(QMenuBar);
 
1144
    d->updateGeometries();
1103
1145
    int key = e->key();
1104
1146
    if(isRightToLeft()) {  // in reverse mode open/close key for submenues are reversed
1105
1147
        if(key == Qt::Key_Left)
1134
1176
    case Qt::Key_Right:
1135
1177
    case Qt::Key_Left: {
1136
1178
        if(d->currentAction) {
1137
 
            QAction *nextAction = 0;
1138
 
            bool allowActiveAndDisabled =
1139
 
                    style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, this);
1140
 
 
1141
 
            for(int i=0; i<(int)d->actionList.count(); i++) {
1142
 
                if(d->actionList.at(i) == (QAction*)d->currentAction) {
1143
 
                    if (key == Qt::Key_Left) {
1144
 
                        while (i > 0) {
1145
 
                            i--;
1146
 
                            if (allowActiveAndDisabled || d->actionList[i]->isEnabled()) {
1147
 
                                nextAction = d->actionList.at(i);
1148
 
                                break;
1149
 
                            }
1150
 
                        }
1151
 
                    } else {
1152
 
                        while (i < d->actionList.count()-1) {
1153
 
                            i++;
1154
 
                            if (allowActiveAndDisabled || d->actionList[i]->isEnabled()) {
1155
 
                                nextAction = d->actionList.at(i);
1156
 
                                break;
1157
 
                            }
1158
 
                        }
1159
 
                    }
1160
 
                    break;
1161
 
 
1162
 
                }
1163
 
            }
1164
 
 
1165
 
            if(!nextAction) {
1166
 
                if (key == Qt::Key_Left) {
1167
 
                    for (int i = d->actionList.size() - 1 ; i >= 0 ; --i) {
1168
 
                        if (allowActiveAndDisabled || d->actionList[i]->isEnabled()) {
1169
 
                            nextAction = d->actionList.at(i);
1170
 
                            i--;
1171
 
                            break;
1172
 
                        }
1173
 
                    }
1174
 
                } else {
1175
 
                    for (int i = 0 ; i < d->actionList.count() ; ++i) {
1176
 
                        if (allowActiveAndDisabled || d->actionList[i]->isEnabled()) {
1177
 
                            nextAction = d->actionList.at(i);
1178
 
                            i++;
1179
 
                            break;
1180
 
                        }
1181
 
                    }
1182
 
                }
1183
 
            }
1184
 
            if(nextAction) {
 
1179
            int index = d->actions.indexOf(d->currentAction);
 
1180
            if (QAction *nextAction = d->getNextAction(index, key == Qt::Key_Left ? -1 : +1)) {
1185
1181
                d->setCurrentAction(nextAction, d->popupState, true);
1186
1182
                key_consumed = true;
1187
1183
            }
1205
1201
        QAction *first = 0, *currentSelected = 0, *firstAfterCurrent = 0;
1206
1202
        {
1207
1203
            QChar c = e->text()[0].toUpper();
1208
 
            for(int i = 0; i < d->actionList.size(); ++i) {
1209
 
                register QAction *act = d->actionList.at(i);
 
1204
            for(int i = 0; i < d->actions.size(); ++i) {
 
1205
                if (d->actionRects.at(i).isNull())
 
1206
                    continue;
 
1207
                QAction *act = d->actions.at(i);
1210
1208
                QString s = act->text();
1211
1209
                if(!s.isEmpty()) {
1212
1210
                    int ampersand = s.indexOf(QLatin1Char('&'));
1248
1246
void QMenuBar::mouseMoveEvent(QMouseEvent *e)
1249
1247
{
1250
1248
    Q_D(QMenuBar);
1251
 
    d->mouseDown = e->buttons() & Qt::LeftButton;
1252
 
    QAction *action = d->actionAt(e->pos());
 
1249
    if (!(e->buttons() & Qt::LeftButton))
 
1250
        d->mouseDown = false;
1253
1251
    bool popupState = d->popupState || d->mouseDown;
 
1252
    QAction *action = d->actionAt(e->pos());
1254
1253
    if ((action && d->isVisible(action)) || !popupState)
1255
1254
        d->setCurrentAction(action, popupState);
1256
1255
}
1261
1260
void QMenuBar::leaveEvent(QEvent *)
1262
1261
{
1263
1262
    Q_D(QMenuBar);
1264
 
    if(!hasFocus() && !d->popupState)
 
1263
    if((!hasFocus() && !d->popupState) ||
 
1264
        (d->currentAction && d->currentAction->menu() == 0))
1265
1265
        d->setCurrentAction(0);
1266
1266
}
1267
1267
 
1272
1272
{
1273
1273
    Q_D(QMenuBar);
1274
1274
    d->itemsDirty = true;
 
1275
#if defined (Q_WS_MAC) || defined(Q_OS_WINCE) || defined(Q_WS_S60)
 
1276
    if (isNativeMenuBar()) {
1275
1277
#ifdef Q_WS_MAC
1276
 
    if(d->mac_menubar) {
1277
 
        if(e->type() == QEvent::ActionAdded)
1278
 
            d->mac_menubar->addAction(e->action(), d->mac_menubar->findAction(e->before()));
1279
 
        else if(e->type() == QEvent::ActionRemoved)
1280
 
            d->mac_menubar->removeAction(e->action());
1281
 
        else if(e->type() == QEvent::ActionChanged)
1282
 
            d->mac_menubar->syncAction(e->action());
1283
 
    }
1284
 
#endif
1285
 
#ifdef Q_OS_WINCE
1286
 
    if(d->wce_menubar) {
1287
 
        if(e->type() == QEvent::ActionAdded)
1288
 
            d->wce_menubar->addAction(e->action(), d->wce_menubar->findAction(e->before()));
1289
 
        else if(e->type() == QEvent::ActionRemoved)
1290
 
            d->wce_menubar->removeAction(e->action());
1291
 
        else if(e->type() == QEvent::ActionChanged)
1292
 
            d->wce_menubar->syncAction(e->action());
1293
 
    }
1294
 
#endif
 
1278
        QMenuBarPrivate::QMacMenuBarPrivate *nativeMenuBar = d->mac_menubar;
 
1279
#elif defined(Q_WS_S60)
 
1280
        QMenuBarPrivate::QSymbianMenuBarPrivate *nativeMenuBar = d->symbian_menubar;
 
1281
#else
 
1282
        QMenuBarPrivate::QWceMenuBarPrivate *nativeMenuBar = d->wce_menubar;
 
1283
#endif
 
1284
        if (!nativeMenuBar)
 
1285
            return;
 
1286
        if(e->type() == QEvent::ActionAdded)
 
1287
            nativeMenuBar->addAction(e->action(), nativeMenuBar->findAction(e->before()));
 
1288
        else if(e->type() == QEvent::ActionRemoved)
 
1289
            nativeMenuBar->removeAction(e->action());
 
1290
        else if(e->type() == QEvent::ActionChanged)
 
1291
            nativeMenuBar->syncAction(e->action());
 
1292
    }
 
1293
#endif
 
1294
 
1295
1295
    if(e->type() == QEvent::ActionAdded) {
1296
1296
        connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
1297
1297
        connect(e->action(), SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
1310
1310
void QMenuBar::focusInEvent(QFocusEvent *)
1311
1311
{
1312
1312
    Q_D(QMenuBar);
1313
 
    if(d->keyboardState && !d->currentAction && !d->actionList.isEmpty())
1314
 
        d->setCurrentAction(d->actionList.first());
 
1313
    if(d->keyboardState)
 
1314
        d->focusFirstAction();
1315
1315
}
1316
1316
 
1317
1317
/*!
1374
1374
    macCreateMenuBar(newParent);
1375
1375
#endif
1376
1376
 
1377
 
#ifdef Q_OS_WINCE
 
1377
#ifdef Q_WS_WINCE
1378
1378
    if (qt_wince_is_mobile() && wce_menubar)
1379
1379
        wce_menubar->rebuild();
1380
1380
#endif
 
1381
#ifdef Q_WS_S60
 
1382
    if (symbian_menubar)
 
1383
        symbian_menubar->rebuild();
 
1384
#endif
 
1385
 
1381
1386
}
1382
1387
 
1383
1388
#ifdef QT3_SUPPORT
1612
1617
QSize QMenuBar::minimumSizeHint() const
1613
1618
{
1614
1619
    Q_D(const QMenuBar);
1615
 
#ifdef Q_WS_MAC
1616
 
    const bool as_gui_menubar = !d->mac_menubar;
1617
 
#elif defined (Q_OS_WINCE)
1618
 
    const bool as_gui_menubar = !d->wce_menubar;
 
1620
#if defined(Q_WS_MAC) || defined(Q_WS_WINCE) || defined(Q_WS_S60)
 
1621
    const bool as_gui_menubar = !isNativeMenuBar();
1619
1622
#else
1620
1623
    const bool as_gui_menubar = true;
1621
1624
#endif
1622
1625
 
1623
1626
    ensurePolished();
1624
1627
    QSize ret(0, 0);
 
1628
    const_cast<QMenuBarPrivate*>(d)->updateGeometries();
1625
1629
    const int hmargin = style()->pixelMetric(QStyle::PM_MenuBarHMargin, 0, this);
1626
1630
    const int vmargin = style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, this);
1627
1631
    int fw = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, this);
1628
1632
    int spaceBelowMenuBar = style()->styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, 0, this);
1629
1633
    if(as_gui_menubar) {
1630
 
        QMap<QAction*, QRect> actionRects;
1631
 
        QList<QAction*> actionList;
1632
1634
        int w = parentWidget() ? parentWidget()->width() : QApplication::desktop()->width();
1633
 
        d->calcActionRects(w - (2 * fw), 0, actionRects, actionList);
1634
 
        if (d->actionList.count() > 0) {
1635
 
            ret = d->actionRect(d->actionList.at(0)).size();
1636
 
            if (!d->extension->isHidden())
1637
 
                ret += QSize(d->extension->sizeHint().width(), 0);
1638
 
        }
 
1635
        d->calcActionRects(w - (2 * fw), 0);
 
1636
        for (int i = 0; ret.isNull() && i < d->actions.count(); ++i)
 
1637
            ret = d->actionRects.at(i).size();
 
1638
        if (!d->extension->isHidden())
 
1639
            ret += QSize(d->extension->sizeHint().width(), 0);
1639
1640
        ret += QSize(2*fw + hmargin, 2*fw + vmargin);
1640
1641
    }
1641
1642
    int margin = 2*vmargin + 2*fw + spaceBelowMenuBar;
1672
1673
QSize QMenuBar::sizeHint() const
1673
1674
{
1674
1675
    Q_D(const QMenuBar);
1675
 
#ifdef Q_WS_MAC
1676
 
    const bool as_gui_menubar = !d->mac_menubar;
1677
 
#elif defined (Q_OS_WINCE)
1678
 
    const bool as_gui_menubar = !d->wce_menubar;
 
1676
#if defined(Q_WS_MAC) || defined(Q_WS_WINCE) || defined(Q_WS_S60)
 
1677
    const bool as_gui_menubar = !isNativeMenuBar();
1679
1678
#else
1680
1679
    const bool as_gui_menubar = true;
1681
1680
#endif
1682
1681
 
 
1682
 
1683
1683
    ensurePolished();
1684
1684
    QSize ret(0, 0);
 
1685
    const_cast<QMenuBarPrivate*>(d)->updateGeometries();
1685
1686
    const int hmargin = style()->pixelMetric(QStyle::PM_MenuBarHMargin, 0, this);
1686
1687
    const int vmargin = style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, this);
1687
1688
    int fw = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, this);
1688
1689
    int spaceBelowMenuBar = style()->styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, 0, this);
1689
1690
    if(as_gui_menubar) {
1690
 
        QMap<QAction*, QRect> actionRects;
1691
 
        QList<QAction*> actionList;
1692
1691
        const int w = parentWidget() ? parentWidget()->width() : QApplication::desktop()->width();
1693
 
        d->calcActionRects(w - (2 * fw), 0, actionRects, actionList);
1694
 
        for (QMap<QAction*, QRect>::const_iterator i = actionRects.constBegin();
1695
 
             i != actionRects.constEnd(); ++i) {
1696
 
            QRect actionRect(i.value());
1697
 
            if(actionRect.x() + actionRect.width() > ret.width())
1698
 
                ret.setWidth(actionRect.x() + actionRect.width());
1699
 
            if(actionRect.y() + actionRect.height() > ret.height())
1700
 
                ret.setHeight(actionRect.y() + actionRect.height());
 
1692
        d->calcActionRects(w - (2 * fw), 0);
 
1693
        for (int i = 0; i < d->actionRects.count(); ++i) {
 
1694
            const QRect &actionRect = d->actionRects.at(i);
 
1695
            ret = ret.expandedTo(QSize(actionRect.x() + actionRect.width(), actionRect.y() + actionRect.height()));
1701
1696
        }
1702
 
        ret += QSize(2*fw + 2*hmargin, 2*fw + 2*vmargin);
 
1697
        //the action geometries already contain the top and left
 
1698
        //margins. So we only need to add those from right and bottom.
 
1699
        ret += QSize(fw + hmargin, fw + vmargin);
1703
1700
    }
1704
1701
    int margin = 2*vmargin + 2*fw + spaceBelowMenuBar;
1705
1702
    if(d->leftWidget) {
1735
1732
int QMenuBar::heightForWidth(int) const
1736
1733
{
1737
1734
    Q_D(const QMenuBar);
1738
 
#ifdef Q_WS_MAC
1739
 
    const bool as_gui_menubar = !d->mac_menubar;
1740
 
#elif defined (Q_OS_WINCE)
1741
 
    const bool as_gui_menubar = !d->wce_menubar;
 
1735
#if defined(Q_WS_MAC) || defined(Q_WS_WINCE) || defined(Q_WS_S60)
 
1736
    const bool as_gui_menubar = !isNativeMenuBar();
1742
1737
#else
1743
1738
    const bool as_gui_menubar = true;
1744
1739
#endif
 
1740
 
 
1741
    const_cast<QMenuBarPrivate*>(d)->updateGeometries();
1745
1742
    int height = 0;
1746
1743
    const int vmargin = style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, this);
1747
1744
    int fw = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, this);
1748
1745
    int spaceBelowMenuBar = style()->styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, 0, this);
1749
1746
    if(as_gui_menubar) {
1750
 
        if (d->actionList.count()) {
1751
 
            // assume all actionrects have the same height
1752
 
            height = d->actionRect(d->actionList.first()).height();
 
1747
        for (int i = 0; i < d->actionRects.count(); ++i)
 
1748
            height = qMax(height, d->actionRects.at(i).height());
 
1749
        if (height) //there is at least one non-null item
1753
1750
            height += spaceBelowMenuBar;
1754
 
        }
1755
1751
        height += 2*fw;
1756
1752
        height += 2*vmargin;
1757
1753
    }
1778
1774
void QMenuBarPrivate::_q_internalShortcutActivated(int id)
1779
1775
{
1780
1776
    Q_Q(QMenuBar);
1781
 
    QAction *act = actionList.at(id);
 
1777
    QAction *act = actions.at(id);
1782
1778
    setCurrentAction(act, true, true);
1783
1779
    if (act && !act->menu()) {
1784
1780
        activateAction(act, QAction::Trigger);
1785
1781
        //100 is the same as the default value in QPushButton::animateClick
1786
1782
        autoReleaseTimer.start(100, q);
 
1783
    } else if (act && q->style()->styleHint(QStyle::SH_MenuBar_AltKeyNavigation, 0, q)) {
 
1784
        // When we open a menu using a shortcut, we should end up in keyboard state
 
1785
        setKeyboardMode(true);
1787
1786
    }
1788
1787
}
1789
1788
 
1856
1855
}
1857
1856
 
1858
1857
/*!
 
1858
    \property QMenuBar::nativeMenuBar
 
1859
    \brief Whether or not a menubar will be used as a native menubar on platforms that support it
 
1860
    \since 4.6
 
1861
 
 
1862
    This property specifies whether or not the menubar should be used as a native menubar on platforms
 
1863
    that support it. The currently supported platforms are Mac OS X and Windows CE. On these platforms
 
1864
    if this property is true, the menubar is used in the native menubar and is not in the window of
 
1865
    its parent, if false the menubar remains in the window. On other platforms the value of this
 
1866
    attribute has no effect.
 
1867
 
 
1868
    The default is to follow whether the Qt::AA_DontUseNativeMenuBar attribute
 
1869
    is set for the application. Explicitly settings this property overrides
 
1870
    the presence (or abscence) of the attribute.
 
1871
*/
 
1872
 
 
1873
void QMenuBar::setNativeMenuBar(bool nativeMenuBar)
 
1874
{
 
1875
    Q_D(QMenuBar);
 
1876
    if (d->nativeMenuBar == -1 || (nativeMenuBar != bool(d->nativeMenuBar))) {
 
1877
        d->nativeMenuBar = nativeMenuBar;
 
1878
#ifdef Q_WS_MAC
 
1879
        if (!d->nativeMenuBar) {
 
1880
            extern void qt_mac_clear_menubar();
 
1881
            qt_mac_clear_menubar();
 
1882
            d->macDestroyMenuBar();
 
1883
            const QList<QAction *> &menubarActions = actions();
 
1884
            for (int i = 0; i < menubarActions.size(); ++i) {
 
1885
                const QAction *action = menubarActions.at(i);
 
1886
                if (QMenu *menu = action->menu()) {
 
1887
                    delete menu->d_func()->mac_menu;
 
1888
                    menu->d_func()->mac_menu = 0;
 
1889
                }
 
1890
            }
 
1891
        } else {
 
1892
            d->macCreateMenuBar(parentWidget());
 
1893
        }
 
1894
        macUpdateMenuBar();
 
1895
        updateGeometry();
 
1896
        setVisible(false);
 
1897
        setVisible(true);
 
1898
#endif
 
1899
    }
 
1900
}
 
1901
 
 
1902
bool QMenuBar::isNativeMenuBar() const
 
1903
{
 
1904
    Q_D(const QMenuBar);
 
1905
    if (d->nativeMenuBar == -1) {
 
1906
        return !QApplication::instance()->testAttribute(Qt::AA_DontUseNativeMenuBar);
 
1907
    }
 
1908
    return d->nativeMenuBar;
 
1909
}
 
1910
 
 
1911
/*!
1859
1912
  \since 4.4
1860
1913
 
1861
1914
  Sets the default action to \a act.
1869
1922
  \sa defaultAction()
1870
1923
*/
1871
1924
 
1872
 
#ifdef Q_OS_WINCE
 
1925
#ifdef Q_WS_WINCE
1873
1926
void QMenuBar::setDefaultAction(QAction *act)
1874
1927
{
1875
1928
    Q_D(QMenuBar);
1876
1929
    if (d->defaultAction == act)
1877
1930
        return;
1878
 
#ifdef Q_OS_WINCE
 
1931
#ifdef Q_WS_WINCE
1879
1932
    if (qt_wince_is_mobile())
1880
1933
        if (d->defaultAction) {
1881
1934
            disconnect(d->defaultAction, SIGNAL(changed()), this, SLOT(_q_updateDefaultAction()));
1883
1936
        }
1884
1937
#endif
1885
1938
    d->defaultAction = act;
1886
 
#ifdef Q_OS_WINCE
 
1939
#ifdef Q_WS_WINCE
1887
1940
    if (qt_wince_is_mobile())
1888
1941
        if (d->defaultAction) {
1889
1942
            connect(d->defaultAction, SIGNAL(changed()), this, SLOT(_q_updateDefaultAction()));