1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "WebContextMenuProxyQt.h"
29
30#include <IntPoint.h>
31#include <OwnPtr.h>
32#include <WebContextMenuItemData.h>
33#include <qmenu.h>
34#include <qwkpage.h>
35
36using namespace WebCore;
37
38namespace WebKit {
39
40static QWKPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action)
41{
42    switch (action) {
43    case WebCore::ContextMenuItemTagOpenLink:
44        return QWKPage::OpenLink;
45    case WebCore::ContextMenuItemTagOpenLinkInNewWindow:
46        return QWKPage::OpenLinkInNewWindow;
47    case WebCore::ContextMenuItemTagCopyLinkToClipboard:
48        return QWKPage::CopyLinkToClipboard;
49    case WebCore::ContextMenuItemTagOpenImageInNewWindow:
50        return QWKPage::OpenImageInNewWindow;
51    case WebCore::ContextMenuItemTagGoBack:
52        return QWKPage::Back;
53    case WebCore::ContextMenuItemTagGoForward:
54        return QWKPage::Forward;
55    case WebCore::ContextMenuItemTagStop:
56        return QWKPage::Stop;
57    case WebCore::ContextMenuItemTagReload:
58        return QWKPage::Reload;
59    case WebCore::ContextMenuItemTagCut:
60        return QWKPage::Cut;
61    case WebCore::ContextMenuItemTagCopy:
62        return QWKPage::Copy;
63    case WebCore::ContextMenuItemTagPaste:
64        return QWKPage::Paste;
65    case WebCore::ContextMenuItemTagSelectAll:
66        return QWKPage::SelectAll;
67    default:
68        break;
69    }
70    return QWKPage::NoWebAction;
71}
72
73WebContextMenuProxyQt::WebContextMenuProxyQt(QWKPage* page)
74    : m_page(page)
75{
76}
77
78PassRefPtr<WebContextMenuProxyQt> WebContextMenuProxyQt::create(QWKPage* page)
79{
80    return adoptRef(new WebContextMenuProxyQt(page));
81}
82
83void WebContextMenuProxyQt::showContextMenu(const IntPoint& position, const Vector<WebContextMenuItemData>& items)
84{
85    if (items.isEmpty())
86        return;
87
88    OwnPtr<QMenu> menu = createContextMenu(items);
89
90    // We send the signal, even with no items, because the client should be able to show custom items
91    // even if WebKit has nothing to show.
92    if (!menu)
93        menu = adoptPtr(new QMenu);
94
95    menu->move(position);
96    emit m_page->showContextMenu(QSharedPointer<QMenu>(menu.leakPtr()));
97}
98
99void WebContextMenuProxyQt::hideContextMenu()
100{
101}
102
103PassOwnPtr<QMenu> WebContextMenuProxyQt::createContextMenu(const Vector<WebContextMenuItemData>& items) const
104{
105    OwnPtr<QMenu> menu = adoptPtr(new QMenu);
106    for (int i = 0; i < items.size(); ++i) {
107        const WebContextMenuItemData& item = items.at(i);
108        switch (item.type()) {
109        case WebCore::CheckableActionType: /* fall through */
110        case WebCore::ActionType: {
111            QWKPage::WebAction action = webActionForContextMenuAction(item.action());
112            QAction* qtAction = m_page->action(action);
113            if (qtAction) {
114                qtAction->setEnabled(item.enabled());
115                qtAction->setChecked(item.checked());
116                qtAction->setCheckable(item.type() == WebCore::CheckableActionType);
117
118                menu->addAction(qtAction);
119            }
120            break;
121        }
122        case WebCore::SeparatorType:
123            menu->addSeparator();
124            break;
125        case WebCore::SubmenuType:
126            if (OwnPtr<QMenu> subMenu = createContextMenu(item.submenu())) {
127                subMenu->setParent(menu.get());
128                QMenu* const subMenuPtr = subMenu.leakPtr();
129                subMenu->setTitle(item.title());
130                menu->addMenu(subMenuPtr);
131            }
132
133            break;
134        }
135    }
136
137    // Do not show sub-menus with just disabled actions.
138    if (menu->isEmpty())
139        return PassOwnPtr<QMenu>();
140
141    bool isAnyActionEnabled = false;
142    QList<QAction *> actions = menu->actions();
143    for (int i = 0; i < actions.count(); ++i) {
144        if (actions.at(i)->isVisible())
145            isAnyActionEnabled |= actions.at(i)->isEnabled();
146    }
147    if (!isAnyActionEnabled)
148        return PassOwnPtr<QMenu>();
149
150    return menu.release();
151}
152
153} // namespace WebKit
154