Patch from Qing Zhao to add context menu support for Qt.
authorstaikos <staikos@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Jul 2007 01:43:21 +0000 (01:43 +0000)
committerstaikos <staikos@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Jul 2007 01:43:21 +0000 (01:43 +0000)
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@24131 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/WebCore.pro
WebCore/platform/ContextMenu.h
WebCore/platform/ContextMenuItem.h
WebCore/platform/qt/ContextMenuItemQt.cpp
WebCore/platform/qt/ContextMenuQt.cpp
WebCore/platform/qt/MenuEventProxy.h [new file with mode: 0644]

index ee7e9a087236691d21d04bd95b63b8a6f6cf3d91..01495d07e533d2942d120254a96f724ab5575365 100644 (file)
@@ -1,3 +1,37 @@
+2007-07-09  Qing Zhao  <qing@staikos.net>
+
+        Reviewed by George Staikos.
+
+        Add qt context menu support.
+
+        * WebCore.pro:
+        * platform/ContextMenu.h:
+        * platform/ContextMenuItem.h:
+        (WebCore::PlatformMenuItemDescriptionType::PlatformMenuItemDescriptionType):
+        * platform/qt/ContextMenuItemQt.cpp:
+        (WebCore::ContextMenuItem::ContextMenuItem):
+        (WebCore::ContextMenuItem::~ContextMenuItem):
+        (WebCore::ContextMenuItem::releasePlatformDescription):
+        (WebCore::ContextMenuItem::type):
+        (WebCore::ContextMenuItem::setType):
+        (WebCore::ContextMenuItem::action):
+        (WebCore::ContextMenuItem::setAction):
+        (WebCore::ContextMenuItem::title):
+        (WebCore::ContextMenuItem::setTitle):
+        (WebCore::ContextMenuItem::platformSubMenu):
+        (WebCore::ContextMenuItem::setSubMenu):
+        (WebCore::ContextMenuItem::setChecked):
+        (WebCore::ContextMenuItem::setEnabled):
+        (WebCore::ContextMenuItem::enabled):
+        * platform/qt/ContextMenuQt.cpp:
+        (WebCore::ContextMenu::ContextMenu):
+        (WebCore::ContextMenu::~ContextMenu):
+        (WebCore::ContextMenu::appendItem):
+        (WebCore::ContextMenu::itemCount):
+        (WebCore::ContextMenu::insertItem):
+        (WebCore::ContextMenu::setPlatformDescription):
+        (WebCore::ContextMenu::platformDescription):
+
 2007-07-09  Anders Carlsson  <andersca@apple.com>
 
         Build fix.
index e5b602f426ea9a940984e987a21577de1f382528..2f2f15b0291ea994157010270521f4edd5bd28f4 100644 (file)
@@ -731,6 +731,7 @@ gdk-port {
 
 qt-port:HEADERS += \
     $$PWD/platform/qt/QWebPopup.h \
+    $$PWD/platform/qt/MenuEventProxy.h \
     $$PWD/platform/qt/SharedTimerQt.h \
     $$PWD/../WebKitQt/Api/qwebframe.h \
     $$PWD/../WebKitQt/Api/qwebpage.h \
index e88e526e31ed82cd8e2345501e1ea1fdde91b645..6ba27a9901b25148cf7c5a5fd7998df2fac60834 100644 (file)
 #include <wtf/RetainPtr.h>
 #elif PLATFORM(QT)
 #include <QMenu>
-typedef QMenu* PlatformMenuDescription;
 #endif
 
 namespace WebCore {
+class MenuEventProxy;
 
     class ContextMenuController;
 
@@ -75,6 +75,7 @@ namespace WebCore {
         RetainPtr<NSMutableArray> m_platformDescription;
 #elif PLATFORM(QT)
         QMenu *m_menu;
+        MenuEventProxy *m_proxy;
 #else
         PlatformMenuDescription m_platformDescription;
 #endif
index 2c69afdbac17e9aa3f62f96acbdd8aa4593acd3f..c70854565386edd095cf7a9fbb9ec1183df7a9cd 100644 (file)
@@ -42,22 +42,14 @@ class NSMenuItem;
 typedef struct tagMENUITEMINFOW* LPMENUITEMINFO;
 #elif PLATFORM(GDK)
 typedef struct _GtkMenuItem GtkMenuItem;
+#elif PLATFORM(QT)
+#include <QAction>
 #endif
 
 namespace WebCore {
 
     class ContextMenu;
 
-#if PLATFORM(MAC)
-    typedef NSMenuItem* PlatformMenuItemDescription;
-#elif PLATFORM(WIN)
-    typedef LPMENUITEMINFO PlatformMenuItemDescription;
-#elif PLATFORM(QT)
-    typedef void* PlatformMenuItemDescription;
-#elif PLATFORM(GDK)
-    typedef GtkMenuItem* PlatformMenuItemDescription;
-#endif
-
     // This enum needs to be in sync with the WebMenuItemTag enum in WebUIDelegate.h and the
     // extra values in WebUIDelegatePrivate.h
     enum ContextMenuAction {
@@ -129,6 +121,25 @@ namespace WebCore {
         SubmenuType
     };
 
+#if PLATFORM(MAC)
+    typedef NSMenuItem* PlatformMenuItemDescription;
+#elif PLATFORM(WIN)
+    typedef LPMENUITEMINFO PlatformMenuItemDescription;
+#elif PLATFORM(QT)
+    struct PlatformMenuItemDescriptionType {
+        PlatformMenuItemDescriptionType() : qaction(0), menu(0), action(ContextMenuItemTagNoAction), type(ActionType), subMenu(0) {}
+        QAction *qaction;
+        QMenu *menu;
+        ContextMenuAction action;
+        QString title;
+        ContextMenuItemType type;
+        PlatformMenuDescription subMenu;
+    };
+    typedef PlatformMenuItemDescriptionType* PlatformMenuItemDescription;
+#elif PLATFORM(GDK)
+    typedef GtkMenuItem* PlatformMenuItemDescription;
+#endif
+
     class ContextMenuItem {
     public:
         ContextMenuItem(PlatformMenuItemDescription);
index 690ed2676149dedcaa0274b1b109cacf553298ba..52841a84356da456cf243e7cb6fda6e5e23ea689 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #include "config.h"
 #include "ContextMenuItem.h"
-
 #include "ContextMenu.h"
 
 namespace WebCore {
 
 ContextMenuItem::ContextMenuItem(ContextMenu* subMenu)
 {
+    m_platformDescription = new PlatformMenuItemDescriptionType;
 }
 
 ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action,
                                  const String& title, ContextMenu* subMenu)
 {
+    m_platformDescription = new PlatformMenuItemDescriptionType;
+    m_platformDescription->type = type;
+    m_platformDescription->action = action;
+    m_platformDescription->title = title;
 }
 
 ContextMenuItem::~ContextMenuItem()
 {
+    delete m_platformDescription;
 }
 
 PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription()
 {
-    return PlatformMenuItemDescription();
+    return m_platformDescription;
 }
 
 ContextMenuItemType ContextMenuItem::type() const
 {
-    return ActionType;
+    return m_platformDescription->type;
 }
 
-void ContextMenuItem::setType(ContextMenuItemType)
+void ContextMenuItem::setType(ContextMenuItemType type)
 {
+    m_platformDescription->type = type;
 }
 
 ContextMenuAction ContextMenuItem::action() const
 { 
-    return ContextMenuAction();
+    return m_platformDescription->action;
 }
 
 void ContextMenuItem::setAction(ContextMenuAction action)
 {
+    m_platformDescription->action = action;
 }
 
 String ContextMenuItem::title() const 
 {
-    return String();
+    return m_platformDescription->title;
 }
 
 void ContextMenuItem::setTitle(const String& title)
 {
+#ifndef QT_NO_MENU
+    m_platformDescription->title = title;
+    if (m_platformDescription->qaction)
+        m_platformDescription->qaction->setText(title);
+#endif
 }
 
 
 PlatformMenuDescription ContextMenuItem::platformSubMenu() const
 {
-    return PlatformMenuDescription();
+    return m_platformDescription->subMenu;
 }
 
 void ContextMenuItem::setSubMenu(ContextMenu* menu)
 {
+#ifndef QT_NO_MENU
+    m_platformDescription->subMenu = menu->platformDescription();
+#endif
 }
 
-void ContextMenuItem::setChecked(bool)
+void ContextMenuItem::setChecked(bool on)
 {
+#ifndef QT_NO_MENU
+    if (m_platformDescription->qaction) {
+        m_platformDescription->qaction->setCheckable(true);
+        m_platformDescription->qaction->setChecked(on);
+    }
+#endif
 }
 
-void ContextMenuItem::setEnabled(bool)
+void ContextMenuItem::setEnabled(bool on)
 {
+#ifndef QT_NO_MENU
+    if (m_platformDescription->qaction)
+        m_platformDescription->qaction->setEnabled(on);
+#endif
 }
 
 bool ContextMenuItem::enabled() const
 {
-    return true;
+#ifndef QT_NO_MENU
+    if (m_platformDescription->qaction)
+        return m_platformDescription->qaction->isEnabled();
+#endif
+    return false;
 }
 
 }
+// vim: ts=4 sw=4 et
index ebd687e2a5e769f0455b4cab7040e92c91be57da..5695596fcf9f6b385bbaa86aa054138dd0f329b8 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #include "config.h"
 #include "ContextMenu.h"
+#include "MenuEventProxy.h"
 
 #include <wtf/Assertions.h>
 
-#include <QMenu>
 #include <QAction>
 
+#include <qwebframe.h>
+#include <qwebpage.h>
+#include <FrameLoaderClientQt.h>
+#include <Document.h>
+#include <Frame.h>
+#include <FrameLoader.h>
+#include <FrameLoaderClient.h>
+
 namespace WebCore {
 
 ContextMenu::ContextMenu(const HitTestResult& result)
-    : m_hitTestResult(result), m_menu(0)
+    : m_hitTestResult(result)
 {
+#ifndef QT_NO_MENU
+    m_menu = new QMenu;
+    //qDebug("Create menu(%p) %p", this, (QMenu*)m_menu);
+    m_proxy = new MenuEventProxy(this);
+#endif
 }
 
 ContextMenu::~ContextMenu()
 {
+#ifndef QT_NO_MENU
+    //qDebug("Destroy menu(%p) %p", this, (QMenu*)m_menu);
+    delete m_menu;
+    m_menu = 0;
+    delete m_proxy;
+    m_proxy = 0;
+#endif
 }
 
 void ContextMenu::appendItem(ContextMenuItem& item)
 {
-    if (!m_menu)
-        m_menu = new QMenu();
-
-    QAction* action  = m_menu->addAction(item.title());
+    insertItem(999999, item); // yuck!  Fix this API!!
 }
 
 unsigned ContextMenu::itemCount() const
 {
-    // FIXME: This method is silly
-    return 1;
+#ifndef QT_NO_MENU
+    return m_menu->actions().count();
+#else
+    return 0;
+#endif
 }
 
 void ContextMenu::insertItem(unsigned position, ContextMenuItem& item)
 {
-    // FIXME: Another silly method
-    appendItem(item);
+#ifndef QT_NO_MENU
+    int id;
+    QAction *action;
+    QAction *before = 0;
+    int p = position;
+    if (p == 999999)
+        p = -1;
+    if (p >= 0)
+        before = m_menu->actions()[p];
+
+    switch (item.type()) {
+        case ActionType:
+            if (!item.title().isEmpty()) {
+                action = m_menu->addAction((QString)item.title());
+                m_menu->removeAction(action);
+                m_menu->insertAction(before, action);
+                QObject::connect(m_menu, SIGNAL(triggered(QAction *)), m_proxy, SLOT(trigger(QAction *)));
+            }
+            break;
+        case SeparatorType:
+            action = m_menu->insertSeparator(before);
+            break;
+        case SubmenuType:
+            if (!item.title().isEmpty()) {
+                QMenu *m = item.platformSubMenu();
+                if (!m)
+                    return;
+                action = m_menu->insertMenu(before, m);
+                action->setText(item.title());
+            }
+            break;
+        default:
+            return;
+    }
+    if (action) {
+        m_proxy->map(action, item.action());
+        item.releasePlatformDescription()->qaction = action;
+    }
+#endif
 }
 
 void ContextMenu::setPlatformDescription(PlatformMenuDescription menu)
 {
-    delete m_menu;
-    m_menu = static_cast<QMenu*>(menu);
+#ifndef QT_NO_MENU
+    //qDebug("Switch menu(%p) %p to %p", this, (QMenu*)m_menu, menu);
+    if (menu == 0) {
+        FrameLoaderClient *f = m_hitTestResult.innerNode()->document()->frame()->loader()->client();
+        QWidget *page = static_cast<FrameLoaderClientQt*>(f)->webFrame()->page();
+        m_menu->exec(page->mapToGlobal(m_hitTestResult.point()));
+    }
+    if (menu != m_menu) {
+        delete m_menu;
+        m_menu = menu;
+    }
+#endif
 }
 
+PlatformMenuDescription ContextMenu::platformDescription() const
+{
+    return m_menu;
+}
+
+
 }
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/qt/MenuEventProxy.h b/WebCore/platform/qt/MenuEventProxy.h
new file mode 100644 (file)
index 0000000..af8d654
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef MENUEVENTPROXY_H
+#define MENUEVENTPROXY_H
+
+#include "Platform.h"
+#include <qobject.h>
+#include <qmap.h>
+#include "ContextMenu.h"
+#include "ContextMenuItem.h"
+#include "ContextMenuController.h"
+
+namespace WebCore {
+class MenuEventProxy : public QObject {
+    Q_OBJECT
+    public:
+        MenuEventProxy(WebCore::ContextMenu *m) : m_m(m) {}
+        ~MenuEventProxy() {}
+
+        void map(QAction* action, unsigned actionTag) { _map[action] = actionTag; }
+
+    public slots:
+        void trigger(QAction *action) {
+            WebCore::ContextMenuItem item(WebCore::ActionType, static_cast<WebCore::ContextMenuAction>(_map[action]), WebCore::String()); 
+            m_m->controller()->contextMenuItemSelected(&item);
+        }
+
+    private:
+        WebCore::ContextMenu *m_m;
+        QMap<QAction*, unsigned> _map;
+};
+
+}
+
+#endif
+// vim: ts=4 sw=4 et