From c4571223a0ebb2f00a6c29477d0a4a55ae3cd2b5 Mon Sep 17 00:00:00 2001
From: axis <qt-info@nokia.com>
Date: Mon, 5 Oct 2009 15:56:57 +0200
Subject: Fixed a crash in menus on Symbian.

The reason for the crash was the following: When we make menu entries
in Qt, we assign each item an arbitrary command ID. This is because
Symbian usually puts the items in a resource file and refers to them
by ID, but we need to be dynamic. These command IDs are also assigned
to cascading menu items (sub menus). When we then get a callback in
RestoreMenuL with one of submenu IDs, we used to ask Symbian to
construct the menu items for them, but Symbian doesn't know about
them.

Fixed by avoiding call into S60 code if the ID belongs to Qt.

Also put a cap on the number of menu items. It's very unlikely that
anyone will reach it, but it's better to have an actual check.

Task:     QT-646
AutoTest: Manual testing went fine
RevBy:    mread
---
 src/gui/s60framework/qs60mainappui.cpp | 21 ++++++++++-----------
 src/gui/widgets/qmenu_p.h              |  2 ++
 src/gui/widgets/qmenu_symbian.cpp      | 12 +++++++-----
 3 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/src/gui/s60framework/qs60mainappui.cpp b/src/gui/s60framework/qs60mainappui.cpp
index 9e2333b..d8181f8 100644
--- a/src/gui/s60framework/qs60mainappui.cpp
+++ b/src/gui/s60framework/qs60mainappui.cpp
@@ -51,7 +51,9 @@
 #include "qs60mainappui.h"
 #include <QtGui/qapplication.h>
 #include <QtGui/qmenu.h>
-#include <QtGui/private/qt_s60_p.h>
+#include <private/qmenu_p.h>
+#include <private/qt_s60_p.h>
+#include <qdebug.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -226,17 +228,14 @@ void QS60MainAppUi::DynInitMenuPaneL(TInt resourceId, CEikMenuPane *menuPane)
  */
 void QS60MainAppUi::RestoreMenuL(CCoeControl* menuWindow, TInt resourceId, TMenuType menuType)
 {
-    if ((resourceId == R_QT_WRAPPERAPP_MENUBAR) || (resourceId == R_AVKON_MENUPANE_FEP_DEFAULT)) {
-        TResourceReader reader;
-        iCoeEnv->CreateResourceReaderLC(reader, resourceId);
-        menuWindow->ConstructFromResourceL(reader);
-        CleanupStack::PopAndDestroy();
+    if (resourceId >= QT_SYMBIAN_FIRST_MENU_ITEM && resourceId <= QT_SYMBIAN_LAST_MENU_ITEM) {
+        if (menuType == EMenuPane)
+            DynInitMenuPaneL(resourceId, (CEikMenuPane*)menuWindow);
+        else
+            DynInitMenuBarL(resourceId, (CEikMenuBar*)menuWindow);
+    } else {
+        CAknAppUi::RestoreMenuL(menuWindow, resourceId, menuType);
     }
-
-    if (menuType == EMenuPane)
-        DynInitMenuPaneL(resourceId, (CEikMenuPane*)menuWindow);
-    else
-        DynInitMenuBarL(resourceId, (CEikMenuBar*)menuWindow);
 }
 
 QT_END_NAMESPACE
diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h
index ea1ab47..9c4f260 100644
--- a/src/gui/widgets/qmenu_p.h
+++ b/src/gui/widgets/qmenu_p.h
@@ -63,6 +63,8 @@
 
 #ifdef Q_WS_S60
 class CEikMenuPane;
+#define QT_SYMBIAN_FIRST_MENU_ITEM 32000
+#define QT_SYMBIAN_LAST_MENU_ITEM 41999 // 10000 items ought to be enough for anybody...
 #endif
 QT_BEGIN_NAMESPACE
 
diff --git a/src/gui/widgets/qmenu_symbian.cpp b/src/gui/widgets/qmenu_symbian.cpp
index e0eb87e..c656ef8 100644
--- a/src/gui/widgets/qmenu_symbian.cpp
+++ b/src/gui/widgets/qmenu_symbian.cpp
@@ -66,8 +66,6 @@ QT_BEGIN_NAMESPACE
 typedef QMultiHash<QWidget *, QMenuBarPrivate *> MenuBarHash;
 Q_GLOBAL_STATIC(MenuBarHash, menubars)
 
-#define QT_FIRST_MENU_ITEM 32000
-
 struct SymbianMenuItem
 {
     int id;
@@ -78,7 +76,7 @@ struct SymbianMenuItem
 
 static QList<SymbianMenuItem*> symbianMenus;
 static QList<QMenuBar*> nativeMenuBars;
-static uint qt_symbian_menu_static_cmd_id = QT_FIRST_MENU_ITEM;
+static uint qt_symbian_menu_static_cmd_id = QT_SYMBIAN_FIRST_MENU_ITEM;
 static QPointer<QWidget> widgetWithContextMenu;
 static QList<QAction*> contextMenuActionList;
 static QAction contextAction(0);
@@ -145,6 +143,9 @@ static void qt_symbian_insert_action(QSymbianMenuAction* action, QList<SymbianMe
         if (action->action->isSeparator())
             return;
 
+        Q_ASSERT_X(action->command <= QT_SYMBIAN_LAST_MENU_ITEM, "qt_symbian_insert_action",
+                "Too many menu actions");
+
         const int underlineShortCut = QApplication::style()->styleHint(QStyle::SH_UnderlineShortcut);
         QString iconText = action->action->iconText();
         TPtrC menuItemText = qt_QString2TPtrC( underlineShortCut ? action->action->text() : iconText);
@@ -213,7 +214,7 @@ static void rebuildMenu()
 
     if (w) {
         mb = menubars()->value(w);
-        qt_symbian_menu_static_cmd_id = QT_FIRST_MENU_ITEM;
+        qt_symbian_menu_static_cmd_id = QT_SYMBIAN_FIRST_MENU_ITEM;
         deleteAll( &symbianMenus );
         if (!mb)
             return;
@@ -289,6 +290,7 @@ QMenuBarPrivate::QSymbianMenuBarPrivate::QSymbianMenuBarPrivate(QMenuBarPrivate
 
 QMenuBarPrivate::QSymbianMenuBarPrivate::~QSymbianMenuBarPrivate()
 {
+    qt_symbian_menu_static_cmd_id = QT_SYMBIAN_FIRST_MENU_ITEM;
     deleteAll( &symbianMenus );
     symbianMenus.clear();
     d = 0;
@@ -390,7 +392,7 @@ void QMenuBarPrivate::QSymbianMenuBarPrivate::insertNativeMenuItems(const QList<
 void QMenuBarPrivate::QSymbianMenuBarPrivate::rebuild()
 {
     contexMenuCommand = 0;
-    qt_symbian_menu_static_cmd_id = QT_FIRST_MENU_ITEM;
+    qt_symbian_menu_static_cmd_id = QT_SYMBIAN_FIRST_MENU_ITEM;
     deleteAll( &symbianMenus );
     if (d)
         insertNativeMenuItems(d->actions);
-- 
cgit v0.12