diff options
author | Pierre Rossi <pierre.rossi@nokia.com> | 2009-12-03 23:04:09 (GMT) |
---|---|---|
committer | Pierre Rossi <pierre.rossi@nokia.com> | 2009-12-04 18:43:37 (GMT) |
commit | 8529a8cbb0c6404c758b5efc650186d740b0e09f (patch) | |
tree | d34ea445050b249573c006fde64dfbbc45178cab /src/gui/widgets | |
parent | f0bb9bc5b0f4c20536d6c77624bd148389b78c06 (diff) | |
download | Qt-8529a8cbb0c6404c758b5efc650186d740b0e09f.zip Qt-8529a8cbb0c6404c758b5efc650186d740b0e09f.tar.gz Qt-8529a8cbb0c6404c758b5efc650186d740b0e09f.tar.bz2 |
Fixes problem with QMenu when it's populated on the aboutToShow
When the menu is populated that late, if the menu is to go off-screen,
then it is moved and ends up covering its originating button.
Includes some code cleanup thanks to Thierry's tips.
Reviewed-by: Gabriel
Reviewed-by: Thierry
Diffstat (limited to 'src/gui/widgets')
-rw-r--r-- | src/gui/widgets/qmenu.cpp | 35 | ||||
-rw-r--r-- | src/gui/widgets/qmenu_p.h | 1 | ||||
-rw-r--r-- | src/gui/widgets/qpushbutton.cpp | 33 | ||||
-rw-r--r-- | src/gui/widgets/qpushbutton_p.h | 4 |
4 files changed, 42 insertions, 31 deletions
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 2e27226..ec9683d 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -65,6 +65,8 @@ #include "qmenubar_p.h" #include "qwidgetaction.h" #include "qtoolbutton.h" +#include "qpushbutton.h" +#include <private/qpushbutton_p.h> #include <private/qaction_p.h> #include <private/qsoftkeymanager_p.h> #ifdef QT3_SUPPORT @@ -417,12 +419,7 @@ void QMenuPrivate::hideUpToMenuBar() hideMenu(m, fadeMenus); if (!fadeMenus) // Mac doesn't clear the action until after hidden. m->d_func()->setCurrentAction(0); - } else { -#ifndef QT_NO_TOOLBUTTON - if (qobject_cast<QToolButton*>(caused) == 0) -#endif - qWarning("QMenu: Internal error"); - caused = 0; + } else { caused = 0; } } #if defined(Q_WS_MAC) @@ -1825,8 +1822,15 @@ void QMenu::popup(const QPoint &p, QAction *atAction) ensurePolished(); // Get the right font emit aboutToShow(); + const bool actionListChanged = d->itemsDirty; d->updateActionRects(); - QPoint pos = p; + QPoint pos; + QPushButton *causedButton = qobject_cast<QPushButton*>(d->causedPopup.widget); + if (actionListChanged && causedButton) + pos = QPushButtonPrivate::get(causedButton)->adjustedMenuPosition(); + else + pos = p; + QSize size = sizeHint(); QRect screen; #ifndef QT_NO_GRAPHICSVIEW @@ -2302,22 +2306,9 @@ void QMenu::mouseReleaseEvent(QMouseEvent *e) if (action->menu()) action->menu()->d_func()->setFirstActionActive(); else { -#if defined(Q_WS_WIN) && !defined(QT_NO_MENUBAR) +#if defined(Q_WS_WIN) //On Windows only context menus can be activated with the right button - bool isContextMenu = true; - const QWidget *cause = d->causedPopup.widget; - while (cause) { - //if the popup was caused by either QMenuBar or a QToolButton, it is not a context menu - if (qobject_cast<const QMenuBar *>(cause) || qobject_cast<const QToolButton *>(cause)) { - isContextMenu = false; - break; - } else if (const QMenu *menu = qobject_cast<const QMenu *>(cause)) { - cause = menu->d_func()->causedPopup.widget; - } else { - break; - } - } - if (e->button() == Qt::LeftButton || isContextMenu) + if (e->button() == Qt::LeftButton || d->topCausedWidget() == 0) #endif d->activateAction(action, QAction::Trigger); } diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h index 5757885..93017f5 100644 --- a/src/gui/widgets/qmenu_p.h +++ b/src/gui/widgets/qmenu_p.h @@ -182,6 +182,7 @@ public: } void init(); + static QMenuPrivate *get(QMenu *m) { return m->d_func(); } int scrollerHeight() const; //item calculations diff --git a/src/gui/widgets/qpushbutton.cpp b/src/gui/widgets/qpushbutton.cpp index eb34336..849bc43 100644 --- a/src/gui/widgets/qpushbutton.cpp +++ b/src/gui/widgets/qpushbutton.cpp @@ -63,6 +63,7 @@ #include "qaccessible.h" #endif +#include "private/qmenu_p.h" #include "private/qpushbutton_p.h" QT_BEGIN_NAMESPACE @@ -575,12 +576,33 @@ void QPushButtonPrivate::_q_popupPressed() return; menu->setNoReplayFor(q); + + QPoint menuPos = adjustedMenuPosition(); + + QPointer<QPushButton> guard(q); + QMenuPrivate::get(menu)->causedPopup.widget = guard; + + //Because of a delay in menu effects, we must keep track of the + //menu visibility to avoid flicker on button release + menuOpen = true; + menu->exec(menuPos); + if (guard) { + menuOpen = false; + q->setDown(false); + } +} + +QPoint QPushButtonPrivate::adjustedMenuPosition() +{ + Q_Q(QPushButton); + bool horizontal = true; #if !defined(QT_NO_TOOLBAR) QToolBar *tb = qobject_cast<QToolBar*>(parent); if (tb && tb->orientation() == Qt::Vertical) horizontal = false; #endif + QWidgetItem item(q); QRect rect = item.geometry(); rect.setRect(rect.x() - q->x(), rect.y() - q->y(), rect.width(), rect.height()); @@ -603,17 +625,10 @@ void QPushButtonPrivate::_q_popupPressed() else x -= menuSize.width(); } - QPointer<QPushButton> guard(q); - //Because of a delay in menu effects, we must keep track of the - //menu visibility to avoid flicker on button release - menuOpen = true; - menu->exec(QPoint(x, y)); - if (guard) { - menuOpen = false; - q->setDown(false); - } + return QPoint(x,y); } + #endif // QT_NO_MENU void QPushButtonPrivate::resetLayoutItemMargins() diff --git a/src/gui/widgets/qpushbutton_p.h b/src/gui/widgets/qpushbutton_p.h index f448027..2510e05 100644 --- a/src/gui/widgets/qpushbutton_p.h +++ b/src/gui/widgets/qpushbutton_p.h @@ -68,6 +68,10 @@ public: defaultButton(false), flat(false), menuOpen(false), lastAutoDefault(false) {} inline void init() { resetLayoutItemMargins(); } + static QPushButtonPrivate* get(QPushButton *b) { return b->d_func(); } +#ifndef QT_NO_MENU + QPoint adjustedMenuPosition(); +#endif void resetLayoutItemMargins(); void _q_popupPressed(); QDialog *dialogParent() const; |