summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPierre Rossi <pierre.rossi@nokia.com>2009-12-03 23:04:09 (GMT)
committerPierre Rossi <pierre.rossi@nokia.com>2009-12-04 18:43:37 (GMT)
commit8529a8cbb0c6404c758b5efc650186d740b0e09f (patch)
treed34ea445050b249573c006fde64dfbbc45178cab /src
parentf0bb9bc5b0f4c20536d6c77624bd148389b78c06 (diff)
downloadQt-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')
-rw-r--r--src/gui/widgets/qmenu.cpp35
-rw-r--r--src/gui/widgets/qmenu_p.h1
-rw-r--r--src/gui/widgets/qpushbutton.cpp33
-rw-r--r--src/gui/widgets/qpushbutton_p.h4
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;