<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[102573] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/102573">102573</a></dd>
<dt>Author</dt> <dd>caio.oliveira@openbossa.org</dd>
<dt>Date</dt> <dd>2011-12-12 05:53:13 -0800 (Mon, 12 Dec 2011)</dd>
</dl>

<h3>Log Message</h3>
<pre>[Qt] [WK2] Support customizing popup menus with QML
https://bugs.webkit.org/show_bug.cgi?id=73560

Reviewed by Tor Arne Vestbø.

Source/WebKit2:

Add a new property 'itemSelector' to WebView (experimental for now) that contains
the QML component used when it needs to spawn a popup menu. For example, <select>
HTML tag may trigger a popup menu.

When loaded the component will have the 'model' available in its context with two
properties: 'elementRect', describing the position of the element which spawned
the item selector, and 'items', which is a model ready to be used by ListView. The
'model' also have methods to accept/reject the selection.

Option groups are available as a property for each row in the 'items' model. This
can be used together with ListView to create sections, as demonstrated in the
MiniBrowser. QML tests were added as well.

The existing Desktop version is removed since after the Qt5 refactoring isn't
working correctly. Once Qt have its own QML components for popup, we hope to use
it as a default if no other popupMenu is specified.

* Target.pri:
* UIProcess/API/qt/qquickwebview.cpp:
(QQuickWebViewPrivate::QQuickWebViewPrivate):
(QQuickWebViewExperimental::itemSelector):
(QQuickWebViewExperimental::setItemSelector):
* UIProcess/API/qt/qquickwebview_p.h:
* UIProcess/API/qt/qquickwebview_p_p.h:
(QQuickWebViewPrivate::get):
* UIProcess/API/qt/tests/qmltests/WebView/tst_itemSelector.qml: Added.
* UIProcess/API/qt/tests/qmltests/common/select.html: Added.
* UIProcess/API/qt/tests/qmltests/qmltests.pro:
* UIProcess/qt/QtPageClient.cpp:
* UIProcess/qt/QtWebPageProxy.cpp:
(QtWebPageProxy::createPopupMenuProxy):
* UIProcess/qt/WebPopupMenuProxyQt.cpp:
(WebKit::PopupMenuItemModel::rowCount):
(WebKit::PopupMenuItemModel::Item::Item):
(WebKit::ItemSelectorContextObject::elementRect):
(WebKit::ItemSelectorContextObject::items):
(WebKit::ItemSelectorContextObject::reject):
(WebKit::ItemSelectorContextObject::ItemSelectorContextObject):
(WebKit::ItemSelectorContextObject::accept):
(WebKit::createRoleNamesHash):
(WebKit::PopupMenuItemModel::PopupMenuItemModel):
(WebKit::PopupMenuItemModel::data):
(WebKit::PopupMenuItemModel::select):
(WebKit::PopupMenuItemModel::selectedOriginalIndex):
(WebKit::PopupMenuItemModel::buildItems):
(WebKit::WebPopupMenuProxyQt::WebPopupMenuProxyQt):
(WebKit::WebPopupMenuProxyQt::showPopupMenu):
(WebKit::WebPopupMenuProxyQt::hidePopupMenu):
(WebKit::WebPopupMenuProxyQt::selectIndex):
(WebKit::WebPopupMenuProxyQt::createItem):
(WebKit::WebPopupMenuProxyQt::createContext):
(WebKit::WebPopupMenuProxyQt::notifyValueChanged):
* UIProcess/qt/WebPopupMenuProxyQt.h:
(WebKit::WebPopupMenuProxyQt::create):
* UIProcess/qt/WebPopupMenuProxyQtDesktop.cpp: Removed.
* UIProcess/qt/WebPopupMenuProxyQtDesktop.h: Removed.

Tools:

Add an Item Selector to our WebView using the experimental API.

* MiniBrowser/qt/MiniBrowser.pro:
* MiniBrowser/qt/MiniBrowser.qrc:
* MiniBrowser/qt/qml/BrowserWindow.qml:
* MiniBrowser/qt/qml/ItemSelector.qml: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2Targetpri">trunk/Source/WebKit2/Target.pri</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIqtqquickwebviewcpp">trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIqtqquickwebview_ph">trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIqtqquickwebview_p_ph">trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIqttestsqmltestsqmltestspro">trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/qmltests.pro</a></li>
<li><a href="#trunkSourceWebKit2UIProcessqtQtPageClientcpp">trunk/Source/WebKit2/UIProcess/qt/QtPageClient.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessqtQtWebPageProxycpp">trunk/Source/WebKit2/UIProcess/qt/QtWebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessqtWebPopupMenuProxyQtcpp">trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessqtWebPopupMenuProxyQth">trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsMiniBrowserqtMiniBrowserpro">trunk/Tools/MiniBrowser/qt/MiniBrowser.pro</a></li>
<li><a href="#trunkToolsMiniBrowserqtMiniBrowserqrc">trunk/Tools/MiniBrowser/qt/MiniBrowser.qrc</a></li>
<li><a href="#trunkToolsMiniBrowserqtqmlBrowserWindowqml">trunk/Tools/MiniBrowser/qt/qml/BrowserWindow.qml</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2UIProcessAPIqttestsqmltestsWebViewtst_itemSelectorqml">trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_itemSelector.qml</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIqttestsqmltestscommonselecthtml">trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/select.html</a></li>
<li><a href="#trunkToolsMiniBrowserqtqmlItemSelectorqml">trunk/Tools/MiniBrowser/qt/qml/ItemSelector.qml</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2UIProcessqtWebPopupMenuProxyQtDesktopcpp">trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQtDesktop.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessqtWebPopupMenuProxyQtDesktoph">trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQtDesktop.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog   2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Source/WebKit2/ChangeLog      2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -1,3 +1,67 @@
</span><ins>+2011-12-12  Caio Marcelo de Oliveira Filho  <caio.oliveira@openbossa.org>
+
+        [Qt] [WK2] Support customizing popup menus with QML
+        https://bugs.webkit.org/show_bug.cgi?id=73560
+
+        Reviewed by Tor Arne Vestbø.
+
+        Add a new property 'itemSelector' to WebView (experimental for now) that contains
+        the QML component used when it needs to spawn a popup menu. For example, <select>
+        HTML tag may trigger a popup menu.
+
+        When loaded the component will have the 'model' available in its context with two
+        properties: 'elementRect', describing the position of the element which spawned
+        the item selector, and 'items', which is a model ready to be used by ListView. The
+        'model' also have methods to accept/reject the selection.
+
+        Option groups are available as a property for each row in the 'items' model. This
+        can be used together with ListView to create sections, as demonstrated in the
+        MiniBrowser. QML tests were added as well.
+
+        The existing Desktop version is removed since after the Qt5 refactoring isn't
+        working correctly. Once Qt have its own QML components for popup, we hope to use
+        it as a default if no other popupMenu is specified.
+
+        * Target.pri:
+        * UIProcess/API/qt/qquickwebview.cpp:
+        (QQuickWebViewPrivate::QQuickWebViewPrivate):
+        (QQuickWebViewExperimental::itemSelector):
+        (QQuickWebViewExperimental::setItemSelector):
+        * UIProcess/API/qt/qquickwebview_p.h:
+        * UIProcess/API/qt/qquickwebview_p_p.h:
+        (QQuickWebViewPrivate::get):
+        * UIProcess/API/qt/tests/qmltests/WebView/tst_itemSelector.qml: Added.
+        * UIProcess/API/qt/tests/qmltests/common/select.html: Added.
+        * UIProcess/API/qt/tests/qmltests/qmltests.pro:
+        * UIProcess/qt/QtPageClient.cpp:
+        * UIProcess/qt/QtWebPageProxy.cpp:
+        (QtWebPageProxy::createPopupMenuProxy):
+        * UIProcess/qt/WebPopupMenuProxyQt.cpp:
+        (WebKit::PopupMenuItemModel::rowCount):
+        (WebKit::PopupMenuItemModel::Item::Item):
+        (WebKit::ItemSelectorContextObject::elementRect):
+        (WebKit::ItemSelectorContextObject::items):
+        (WebKit::ItemSelectorContextObject::reject):
+        (WebKit::ItemSelectorContextObject::ItemSelectorContextObject):
+        (WebKit::ItemSelectorContextObject::accept):
+        (WebKit::createRoleNamesHash):
+        (WebKit::PopupMenuItemModel::PopupMenuItemModel):
+        (WebKit::PopupMenuItemModel::data):
+        (WebKit::PopupMenuItemModel::select):
+        (WebKit::PopupMenuItemModel::selectedOriginalIndex):
+        (WebKit::PopupMenuItemModel::buildItems):
+        (WebKit::WebPopupMenuProxyQt::WebPopupMenuProxyQt):
+        (WebKit::WebPopupMenuProxyQt::showPopupMenu):
+        (WebKit::WebPopupMenuProxyQt::hidePopupMenu):
+        (WebKit::WebPopupMenuProxyQt::selectIndex):
+        (WebKit::WebPopupMenuProxyQt::createItem):
+        (WebKit::WebPopupMenuProxyQt::createContext):
+        (WebKit::WebPopupMenuProxyQt::notifyValueChanged):
+        * UIProcess/qt/WebPopupMenuProxyQt.h:
+        (WebKit::WebPopupMenuProxyQt::create):
+        * UIProcess/qt/WebPopupMenuProxyQtDesktop.cpp: Removed.
+        * UIProcess/qt/WebPopupMenuProxyQtDesktop.h: Removed.
+
</ins><span class="cx"> 2011-12-11  Gopal Raghavan  <gopal.1.raghavan@nokia.com>
</span><span class="cx"> 
</span><span class="cx">         [Qt] QQuickWebView missing titleChanged signal tests
</span></span></pre></div>
<a id="trunkSourceWebKit2Targetpri"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Target.pri (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Target.pri  2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Source/WebKit2/Target.pri     2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -273,7 +273,6 @@
</span><span class="cx">     UIProcess/qt/WebContextMenuProxyQt.h \
</span><span class="cx">     UIProcess/qt/WebGeolocationProviderQt.h \
</span><span class="cx">     UIProcess/qt/WebPopupMenuProxyQt.h \
</span><del>-    UIProcess/qt/WebPopupMenuProxyQtDesktop.h \
</del><span class="cx">     WebProcess/ApplicationCache/WebApplicationCacheManager.h \
</span><span class="cx">     WebProcess/Authentication/AuthenticationManager.h \
</span><span class="cx">     WebProcess/Cookies/WebCookieManager.h \
</span><span class="lines">@@ -600,7 +599,6 @@
</span><span class="cx">     UIProcess/qt/WebInspectorProxyQt.cpp \
</span><span class="cx">     UIProcess/qt/WebPageProxyQt.cpp \
</span><span class="cx">     UIProcess/qt/WebPopupMenuProxyQt.cpp \
</span><del>-    UIProcess/qt/WebPopupMenuProxyQtDesktop.cpp \
</del><span class="cx">     UIProcess/qt/WebPreferencesQt.cpp \
</span><span class="cx">     WebProcess/ApplicationCache/WebApplicationCacheManager.cpp \
</span><span class="cx">     WebProcess/Authentication/AuthenticationManager.cpp \
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIqtqquickwebviewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp  2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp     2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx">     , alertDialog(0)
</span><span class="cx">     , confirmDialog(0)
</span><span class="cx">     , promptDialog(0)
</span><ins>+    , itemSelector(0)
</ins><span class="cx">     , postTransitionState(adoptPtr(new PostTransitionState(this)))
</span><span class="cx">     , isTransitioningToNewPage(false)
</span><span class="cx">     , pageIsSuspended(false)
</span><span class="lines">@@ -494,6 +495,21 @@
</span><span class="cx">     emit promptDialogChanged();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+QDeclarativeComponent* QQuickWebViewExperimental::itemSelector() const
+{
+    Q_D(const QQuickWebView);
+    return d->itemSelector;
+}
+
+void QQuickWebViewExperimental::setItemSelector(QDeclarativeComponent* itemSelector)
+{
+    Q_D(QQuickWebView);
+    if (d->itemSelector == itemSelector)
+        return;
+    d->itemSelector = itemSelector;
+    emit itemSelectorChanged();
+}
+
</ins><span class="cx"> bool QQuickWebViewExperimental::useTraditionalDesktopBehaviour() const
</span><span class="cx"> {
</span><span class="cx">     Q_D(const QQuickWebView);
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIqtqquickwebview_ph"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h  2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h     2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -172,6 +172,7 @@
</span><span class="cx">     Q_PROPERTY(QDeclarativeComponent* alertDialog READ alertDialog WRITE setAlertDialog NOTIFY alertDialogChanged)
</span><span class="cx">     Q_PROPERTY(QDeclarativeComponent* confirmDialog READ confirmDialog WRITE setConfirmDialog NOTIFY confirmDialogChanged)
</span><span class="cx">     Q_PROPERTY(QDeclarativeComponent* promptDialog READ promptDialog WRITE setPromptDialog NOTIFY promptDialogChanged)
</span><ins>+    Q_PROPERTY(QDeclarativeComponent* itemSelector READ itemSelector WRITE setItemSelector NOTIFY itemSelectorChanged)
</ins><span class="cx">     Q_PROPERTY(bool useTraditionalDesktopBehaviour READ useTraditionalDesktopBehaviour WRITE setUseTraditionalDesktopBehaviour)
</span><span class="cx"> 
</span><span class="cx"> public:
</span><span class="lines">@@ -184,6 +185,8 @@
</span><span class="cx">     void setConfirmDialog(QDeclarativeComponent*);
</span><span class="cx">     QDeclarativeComponent* promptDialog() const;
</span><span class="cx">     void setPromptDialog(QDeclarativeComponent*);
</span><ins>+    QDeclarativeComponent* itemSelector() const;
+    void setItemSelector(QDeclarativeComponent*);
</ins><span class="cx"> 
</span><span class="cx">     bool useTraditionalDesktopBehaviour() const;
</span><span class="cx"> 
</span><span class="lines">@@ -194,6 +197,7 @@
</span><span class="cx">     void alertDialogChanged();
</span><span class="cx">     void confirmDialogChanged();
</span><span class="cx">     void promptDialogChanged();
</span><ins>+    void itemSelectorChanged();
</ins><span class="cx">     void downloadRequested(QWebDownloadItem* downloadItem);
</span><span class="cx">     void permissionRequested(QWebPermissionRequest* permission);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIqtqquickwebview_p_ph"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h        2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h   2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -48,6 +48,8 @@
</span><span class="cx">     friend class QQuickWebViewExperimental;
</span><span class="cx"> 
</span><span class="cx"> public:
</span><ins>+    static QQuickWebViewPrivate* get(QQuickWebView* q) { return q->d_ptr.data(); }
+
</ins><span class="cx">     QQuickWebViewPrivate(QQuickWebView* viewport, WKContextRef contextRef = 0, WKPageGroupRef pageGroupRef = 0);
</span><span class="cx">     virtual ~QQuickWebViewPrivate(); 
</span><span class="cx">     void setPageProxy(QtWebPageProxy*);
</span><span class="lines">@@ -81,6 +83,7 @@
</span><span class="cx">     QString runJavaScriptPrompt(const QString&, const QString& defaultValue, bool& ok);
</span><span class="cx"> 
</span><span class="cx">     void setUseTraditionalDesktopBehaviour(bool enable);
</span><ins>+    void setViewInAttachedProperties(QObject*);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     // This class is responsible for collecting and applying all properties
</span><span class="lines">@@ -109,8 +112,6 @@
</span><span class="cx">         QSize contentsSize;
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    void setViewInAttachedProperties(QObject*);
-
</del><span class="cx">     QScopedPointer<QtPageClient> pageClient;
</span><span class="cx">     QScopedPointer<QtWebPageEventHandler> eventHandler;
</span><span class="cx"> 
</span><span class="lines">@@ -127,6 +128,7 @@
</span><span class="cx">     QDeclarativeComponent* alertDialog;
</span><span class="cx">     QDeclarativeComponent* confirmDialog;
</span><span class="cx">     QDeclarativeComponent* promptDialog;
</span><ins>+    QDeclarativeComponent* itemSelector;
</ins><span class="cx"> 
</span><span class="cx">     WebCore::ViewportArguments viewportArguments;
</span><span class="cx">     OwnPtr<PostTransitionState> postTransitionState;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIqttestsqmltestsWebViewtst_itemSelectorqml"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_itemSelector.qml (0 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_itemSelector.qml                                (rev 0)
+++ trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_itemSelector.qml   2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -0,0 +1,119 @@
</span><ins>+import QtQuick 2.0
+import QtTest 1.0
+import QtWebKit 3.0
+import QtWebKit.experimental 3.0
+
+// FIXME: used because we want to have mouseClick() to open the <select> tag. We can remove this
+// when TestCase starts supporting touch events, see https://bugreports.qt.nokia.com/browse/QTBUG-23083.
+import "../DesktopBehavior"
+
+DesktopWebView {
+    id: webView
+
+    width: 400
+    height: 400
+
+    property int initialSelection
+    property int finalSelection
+    property bool useAcceptDirectly
+    property bool selectorLoaded
+
+    experimental.itemSelector: Item {
+        Component.onCompleted: {
+            if (WebView.view.initialSelection != -1)
+                model.items.select(WebView.view.initialSelection)
+
+            if (WebView.view.finalSelection == -1)
+                model.reject()
+            else {
+                if (useAcceptDirectly) {
+                    model.accept(WebView.view.finalSelection)
+                } else {
+                    model.items.select(WebView.view.finalSelection)
+                    model.accept()
+                }
+            }
+
+            WebView.view.selectorLoaded = true
+        }
+    }
+
+    SignalSpy {
+        id: loadSpy
+        target: webView
+        signalName: "loadSucceeded"
+    }
+
+    SignalSpy {
+        id: titleSpy
+        target: webView
+        signalName: "titleChanged"
+    }
+
+    TestCase {
+        id: test
+        name: "WebViewItemSelector"
+        when: windowShown
+
+        function init() {
+            webView.initialSelection = -1
+            webView.finalSelection = -1
+            webView.useAcceptDirectly = false
+            webView.selectorLoaded = false
+            loadSpy.clear()
+            webView.load(Qt.resolvedUrl("../common/select.html"))
+            loadSpy.wait()
+            titleSpy.clear()
+        }
+
+        function openItemSelector() {
+            mouseClick(webView, 15, 15, Qt.LeftButton)
+        }
+
+        function test_accept() {
+            webView.finalSelection = 1
+            openItemSelector()
+            titleSpy.wait()
+            compare(webView.title, "__closed__")
+        }
+
+        function test_acceptDirectly() {
+            webView.finalSelection = 1
+            webView.useAcceptDirectly = true
+            openItemSelector()
+            titleSpy.wait()
+            compare(webView.title, "__closed__")
+        }
+
+        function test_selectFirstThenAccept() {
+            webView.initialSelection = 1
+            webView.finalSelection = 2
+            openItemSelector()
+            titleSpy.wait()
+            compare(webView.title, "__all__")
+        }
+
+        function test_selectFirstThenAcceptDirectly() {
+            webView.initialSelection = 1
+            webView.finalSelection = 2
+            webView.useAcceptDirectly = true
+            openItemSelector()
+            titleSpy.wait()
+            compare(webView.title, "__all__")
+        }
+
+        function test_reject() {
+            openItemSelector()
+            tryCompare(webView, "selectorLoaded", true)
+            compare(webView.title, "No new selection was made")
+        }
+
+        function test_selectFirstThenReject() {
+            webView.initialSelection = 1
+            webView.finalSelection = -1
+            openItemSelector()
+            tryCompare(webView, "selectorLoaded", true)
+            compare(webView.title, "No new selection was made")
+        }
+    }
+}
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIqttestsqmltestscommonselecthtml"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/select.html (0 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/select.html                          (rev 0)
+++ trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/select.html     2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<head>
+<title>No new selection was made</title>
+<script>
+function updateTitle(selectElement) {
+    var index = selectElement.selectedIndex;
+    document.title = selectElement.options[index].value;
+}
+</script>
+</head>
+<body>
+<select onchange="updateTitle(this)">
+<option value="__open__" >Open</option>
+<option value="__closed__" >Closed</option>
+<option value="__all__" >All</option>
+</select>
+</html>
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIqttestsqmltestsqmltestspro"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/qmltests.pro (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/qmltests.pro        2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/qmltests.pro   2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -23,6 +23,7 @@
</span><span class="cx">     DesktopBehavior/tst_navigationRequested.qml \
</span><span class="cx">     WebView/tst_download.qml \
</span><span class="cx">     WebView/tst_geopermission.qml \
</span><ins>+    WebView/tst_itemSelector.qml \
</ins><span class="cx">     WebView/tst_javaScriptDialogs.qml \
</span><span class="cx">     WebView/tst_loadFail.qml \
</span><span class="cx">     WebView/tst_loadHtml.qml \
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessqtQtPageClientcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/qt/QtPageClient.cpp (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/qt/QtPageClient.cpp       2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Source/WebKit2/UIProcess/qt/QtPageClient.cpp  2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -26,7 +26,6 @@
</span><span class="cx"> #include "QtWebUndoCommand.h"
</span><span class="cx"> #include "WebContextMenuProxyQt.h"
</span><span class="cx"> #include "WebEditCommandProxy.h"
</span><del>-#include "WebPopupMenuProxyQtDesktop.h"
</del><span class="cx"> #include <QGuiApplication>
</span><span class="cx"> #include <QUndoStack>
</span><span class="cx"> #include <WebCore/Cursor.h>
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessqtQtWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/qt/QtWebPageProxy.cpp (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/qt/QtWebPageProxy.cpp     2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Source/WebKit2/UIProcess/qt/QtWebPageProxy.cpp        2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx"> #include "WebContext.h"
</span><span class="cx"> #include "WebContextMenuProxyQt.h"
</span><span class="cx"> #include "WebEditCommandProxy.h"
</span><del>-#include "WebPopupMenuProxyQtDesktop.h"
</del><ins>+#include "WebPopupMenuProxyQt.h"
</ins><span class="cx"> #include "WKStringQt.h"
</span><span class="cx"> #include "WKURLQt.h"
</span><span class="cx"> #include <QDrag>
</span><span class="lines">@@ -184,7 +184,7 @@
</span><span class="cx"> 
</span><span class="cx"> PassRefPtr<WebPopupMenuProxy> QtWebPageProxy::createPopupMenuProxy(WebPageProxy*)
</span><span class="cx"> {
</span><del>-    return WebPopupMenuProxyQtDesktop::create(m_webPageProxy.get(), m_qmlWebView);
</del><ins>+    return WebPopupMenuProxyQt::create(m_webPageProxy.get(), m_qmlWebView);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WKPageRef QtWebPageProxy::pageRef() const
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessqtWebPopupMenuProxyQtcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp        2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp   2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -1,5 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2010 Apple Inc. All rights reserved.
</span><ins>+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -28,26 +29,288 @@
</span><span class="cx"> 
</span><span class="cx"> #include "PlatformPopupMenuData.h"
</span><span class="cx"> #include "WebPopupItem.h"
</span><ins>+#include "qquickwebview_p.h"
+#include "qquickwebview_p_p.h"
+#include <QtCore/QAbstractListModel>
+#include <QtDeclarative/QDeclarativeContext>
+#include <QtDeclarative/QDeclarativeEngine>
</ins><span class="cx"> 
</span><span class="cx"> using namespace WebCore;
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><del>-WebPopupMenuProxyQt::WebPopupMenuProxyQt()
-    : WebPopupMenuProxy(0)
</del><ins>+static QHash<int, QByteArray> createRoleNamesHash();
+
+class PopupMenuItemModel : public QAbstractListModel {
+    Q_OBJECT
+
+public:
+    enum Roles {
+        GroupRole = Qt::UserRole,
+        EnabledRole = Qt::UserRole + 1,
+        SelectedRole = Qt::UserRole + 2,
+        IsSeparatorRole = Qt::UserRole + 3
+    };
+
+    PopupMenuItemModel(const Vector<WebPopupItem>&, int selectedOriginalIndex);
+    virtual int rowCount(const QModelIndex& parent = QModelIndex()) const { return m_items.size(); }
+    virtual QVariant data(const QModelIndex&, int role = Qt::DisplayRole) const;
+
+    Q_INVOKABLE void select(int);
+
+    int selectedOriginalIndex() const;
+
+private:
+    struct Item {
+        Item(const WebPopupItem& webPopupItem, const QString& group, int originalIndex, bool selected)
+            : text(webPopupItem.m_text)
+            , toolTip(webPopupItem.m_toolTip)
+            , group(group)
+            , originalIndex(originalIndex)
+            , enabled(webPopupItem.m_isEnabled)
+            , selected(selected)
+            , isSeparator(webPopupItem.m_type == WebPopupItem::Separator)
+        { }
+
+        QString text;
+        QString toolTip;
+        QString group;
+        // Keep track of originalIndex because we don't add the label (group) items to our vector.
+        int originalIndex;
+        bool enabled;
+        bool selected;
+        bool isSeparator;
+    };
+
+    void buildItems(const Vector<WebPopupItem>& webPopupItems, int selectedOriginalIndex);
+
+    Vector<Item> m_items;
+    int m_selectedModelIndex;
+};
+
+class ItemSelectorContextObject : public QObject {
+    Q_OBJECT
+    Q_PROPERTY(QRect elementRect READ elementRect CONSTANT FINAL)
+    Q_PROPERTY(QObject* items READ items CONSTANT FINAL)
+
+public:
+    ItemSelectorContextObject(const IntRect& elementRect, const Vector<WebPopupItem>&, int selectedIndex);
+
+    QRect elementRect() const { return m_elementRect; }
+    PopupMenuItemModel* items() { return &m_items; }
+
+    Q_INVOKABLE void accept(int index = -1);
+    Q_INVOKABLE void reject() { emit rejected(); }
+
+Q_SIGNALS:
+    void acceptedWithOriginalIndex(int);
+    void rejected();
+
+private:
+    QRect m_elementRect;
+    PopupMenuItemModel m_items;
+};
+
+ItemSelectorContextObject::ItemSelectorContextObject(const IntRect& elementRect, const Vector<WebPopupItem>& webPopupItems, int selectedIndex)
+    : m_elementRect(elementRect)
+    , m_items(webPopupItems, selectedIndex)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void ItemSelectorContextObject::accept(int index)
+{
+    if (index != -1)
+        m_items.select(index);
+    int originalIndex = m_items.selectedOriginalIndex();
+    emit acceptedWithOriginalIndex(originalIndex);
+}
+
+static QHash<int, QByteArray> createRoleNamesHash()
+{
+    QHash<int, QByteArray> roles;
+    roles[Qt::DisplayRole] = "text";
+    roles[Qt::ToolTipRole] = "tooltip";
+    roles[PopupMenuItemModel::GroupRole] = "group";
+    roles[PopupMenuItemModel::EnabledRole] = "enabled";
+    roles[PopupMenuItemModel::SelectedRole] = "selected";
+    roles[PopupMenuItemModel::IsSeparatorRole] = "isSeparator";
+    return roles;
+}
+
+PopupMenuItemModel::PopupMenuItemModel(const Vector<WebPopupItem>& webPopupItems, int selectedOriginalIndex)
+    : m_selectedModelIndex(-1)
+{
+    static QHash<int, QByteArray> roles = createRoleNamesHash();
+    setRoleNames(roles);
+    buildItems(webPopupItems, selectedOriginalIndex);
+}
+
+QVariant PopupMenuItemModel::data(const QModelIndex& index, int role) const
+{
+    if (!index.isValid() || index.row() < 0 || index.row() >= m_items.size())
+        return QVariant();
+
+    const Item& item = m_items[index.row()];
+    if (item.isSeparator) {
+        if (role == IsSeparatorRole)
+            return true;
+        return QVariant();
+    }
+
+    switch (role) {
+    case Qt::DisplayRole:
+        return item.text;
+    case Qt::ToolTipRole:
+        return item.toolTip;
+    case GroupRole:
+        return item.group;
+    case EnabledRole:
+        return item.enabled;
+    case SelectedRole:
+        return item.selected;
+    case IsSeparatorRole:
+        return false;
+    }
+
+    return QVariant();
+}
+
+void PopupMenuItemModel::select(int index)
+{
+    int oldIndex = m_selectedModelIndex;
+    if (index == oldIndex)
+        return;
+    if (index < 0 || index >= m_items.size())
+        return;
+    Item& item = m_items[index];
+    if (!item.enabled)
+        return;
+
+    Item& oldItem = m_items[oldIndex];
+    oldItem.selected = false;
+    item.selected = true;
+    m_selectedModelIndex = index;
+
+    emit dataChanged(this->index(oldIndex), this->index(oldIndex));
+    emit dataChanged(this->index(index), this->index(index));
+}
+
+int PopupMenuItemModel::selectedOriginalIndex() const
+{
+    if (m_selectedModelIndex == -1)
+        return -1;
+    return m_items[m_selectedModelIndex].originalIndex;
+}
+
+void PopupMenuItemModel::buildItems(const Vector<WebPopupItem>& webPopupItems, int selectedOriginalIndex)
+{
+    QString currentGroup;
+    m_items.reserveInitialCapacity(webPopupItems.size());
+    for (int i = 0; i < webPopupItems.size(); i++) {
+        const WebPopupItem& webPopupItem = webPopupItems[i];
+        if (webPopupItem.m_isLabel) {
+            currentGroup = webPopupItem.m_text;
+            continue;
+        }
+        const bool selected = i == selectedOriginalIndex;
+        if (selected)
+            m_selectedModelIndex = m_items.size();
+        m_items.append(Item(webPopupItem, currentGroup, i, selected));
+    }
+}
+
+WebPopupMenuProxyQt::WebPopupMenuProxyQt(WebPopupMenuProxy::Client* client, QQuickWebView* webView)
+    : WebPopupMenuProxy(client)
+    , m_webView(webView)
+{
+}
+
</ins><span class="cx"> WebPopupMenuProxyQt::~WebPopupMenuProxyQt()
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPopupMenuProxyQt::showPopupMenu(const IntRect& rect, WebCore::TextDirection, double, const Vector<WebPopupItem>& items, const PlatformPopupMenuData&, int32_t selectedIndex)
</span><span class="cx"> {
</span><ins>+    m_selectedIndex = selectedIndex;
+
+    ItemSelectorContextObject* contextObject = new ItemSelectorContextObject(rect, items, m_selectedIndex);
+    createItem(contextObject);
+    if (!m_itemSelector) {
+        notifyValueChanged();
+        return;
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPopupMenuProxyQt::hidePopupMenu()
</span><span class="cx"> {
</span><ins>+    m_itemSelector.clear();
+    m_context.clear();
+    notifyValueChanged();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPopupMenuProxyQt::selectIndex(int index)
+{
+    m_selectedIndex = index;
+}
+
+void WebPopupMenuProxyQt::createItem(QObject* contextObject)
+{
+    QDeclarativeComponent* component = m_webView->experimental()->itemSelector();
+    if (!component) {
+        delete contextObject;
+        return;
+    }
+
+    createContext(component, contextObject);
+    QObject* object = component->beginCreate(m_context.get());
+    if (!object) {
+        m_context.clear();
+        return;
+    }
+
+    m_itemSelector = adoptPtr(qobject_cast<QQuickItem*>(object));
+    if (!m_itemSelector) {
+        m_context.clear();
+        m_itemSelector.clear();
+        return;
+    }
+
+    connect(contextObject, SIGNAL(acceptedWithOriginalIndex(int)), SLOT(selectIndex(int)));
+
+    // We enqueue these because they are triggered by m_itemSelector and will lead to its destruction.
+    connect(contextObject, SIGNAL(acceptedWithOriginalIndex(int)), SLOT(hidePopupMenu()), Qt::QueuedConnection);
+    connect(contextObject, SIGNAL(rejected()), SLOT(hidePopupMenu()), Qt::QueuedConnection);
+
+    QQuickWebViewPrivate::get(m_webView)->setViewInAttachedProperties(m_itemSelector.get());
+    component->completeCreate();
+
+    m_itemSelector->setParentItem(m_webView);
+}
+
+void WebPopupMenuProxyQt::createContext(QDeclarativeComponent* component, QObject* contextObject)
+{
+    QDeclarativeContext* baseContext = component->creationContext();
+    if (!baseContext)
+        baseContext = QDeclarativeEngine::contextForObject(m_webView);
+    m_context = adoptPtr(new QDeclarativeContext(baseContext));
+
+    contextObject->setParent(m_context.get());
+    m_context->setContextProperty(QLatin1String("model"), contextObject);
+    m_context->setContextObject(contextObject);
+}
+
+void WebPopupMenuProxyQt::notifyValueChanged()
+{
+    if (m_client) {
+        m_client->valueChangedForPopupMenu(this, m_selectedIndex);
+        invalidate();
+    }
+}
+
</ins><span class="cx"> } // namespace WebKit
</span><ins>+
+// Since we define QObjects in WebPopupMenuProxyQt.cpp, this will trigger moc to run on .cpp.
+#include "WebPopupMenuProxyQt.moc"
+
+// And we can't compile the moc for WebPopupMenuProxyQt.h by itself, since it doesn't include "config.h"
+#include "moc_WebPopupMenuProxyQt.cpp"
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessqtWebPopupMenuProxyQth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.h (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.h  2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.h     2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -1,5 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2010 Apple Inc. All rights reserved.
</span><ins>+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -28,21 +29,46 @@
</span><span class="cx"> 
</span><span class="cx"> #include "WebPopupMenuProxy.h"
</span><span class="cx"> 
</span><ins>+#include <QtCore/QObject>
+#include <wtf/OwnPtr.h>
+
+class QDeclarativeComponent;
+class QDeclarativeContext;
+class QQuickWebView;
+class QQuickItem;
+
</ins><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><del>-class WebPopupMenuProxyQt : public WebPopupMenuProxy {
</del><ins>+class WebPopupMenuProxyQt : public QObject, public WebPopupMenuProxy {
+    Q_OBJECT
+
</ins><span class="cx"> public:
</span><del>-    static PassRefPtr<WebPopupMenuProxyQt> create()
</del><ins>+    static PassRefPtr<WebPopupMenuProxyQt> create(WebPopupMenuProxy::Client* client, QQuickWebView* webView)
</ins><span class="cx">     {
</span><del>-        return adoptRef(new WebPopupMenuProxyQt());
</del><ins>+        return adoptRef(new WebPopupMenuProxyQt(client, webView));
</ins><span class="cx">     }
</span><span class="cx">     ~WebPopupMenuProxyQt();
</span><span class="cx"> 
</span><span class="cx">     virtual void showPopupMenu(const WebCore::IntRect&, WebCore::TextDirection, double pageScaleFactor, const Vector<WebPopupItem>&, const PlatformPopupMenuData&, int32_t selectedIndex);
</span><ins>+
+public Q_SLOTS:
</ins><span class="cx">     virtual void hidePopupMenu();
</span><span class="cx"> 
</span><ins>+private Q_SLOTS:
+    void selectIndex(int);
+
</ins><span class="cx"> private:
</span><del>-    WebPopupMenuProxyQt();
</del><ins>+    WebPopupMenuProxyQt(WebPopupMenuProxy::Client*, QQuickWebView*);
+    void createItem(QObject*);
+    void createContext(QDeclarativeComponent*, QObject*);
+
+    void notifyValueChanged();
+
+    OwnPtr<QDeclarativeContext> m_context;
+    OwnPtr<QQuickItem> m_itemSelector;
+
+    QQuickWebView* m_webView;
+    int32_t m_selectedIndex;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessqtWebPopupMenuProxyQtDesktopcpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQtDesktop.cpp (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQtDesktop.cpp 2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQtDesktop.cpp    2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -1,117 +0,0 @@
</span><del>-/*
- * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "WebPopupMenuProxyQtDesktop.h"
-
-#include "PlatformPopupMenuData.h"
-#include <QAbstractItemView>
-#include <QCoreApplication>
-#include <QtQuick/QQuickCanvas>
-#include <QtQuick/QQuickItem>
-#include <QMouseEvent>
-#include <QStandardItemModel>
-#include "WebPopupItem.h"
-#include <wtf/CurrentTime.h>
-
-using namespace WebCore;
-
-namespace WebKit {
-
-WebPopupMenuProxyQtDesktop::WebPopupMenuProxyQtDesktop(WebPopupMenuProxy::Client* client, QQuickItem* webViewItem)
-    : WebPopupMenuProxy(client)
-    , m_webViewItem(webViewItem)
-    , m_selectedIndex(-1)
-{
-    window()->winId(); // Ensure that the combobox has a window
-    Q_ASSERT(window()->windowHandle());
-    window()->windowHandle()->setTransientParent(m_webViewItem->canvas());
-
-    connect(this, SIGNAL(activated(int)), SLOT(setSelectedIndex(int)));
-    // Install an event filter on the view inside the combo box popup to make sure we know
-    // when the popup got closed. E.g. QComboBox::hidePopup() won't be called when the popup
-    // is closed by a mouse wheel event outside its window.
-    view()->installEventFilter(this);
-}
-
-WebPopupMenuProxyQtDesktop::~WebPopupMenuProxyQtDesktop()
-{
-}
-
-void WebPopupMenuProxyQtDesktop::showPopupMenu(const IntRect& rect, WebCore::TextDirection, double, const Vector<WebPopupItem>& items, const PlatformPopupMenuData&, int32_t selectedIndex)
-{
-    m_selectedIndex = selectedIndex;
-    populate(items);
-    setCurrentIndex(selectedIndex);
-    setGeometry(m_webViewItem->mapRectToScene(QRect(rect)).toRect());
-
-    QMouseEvent event(QEvent::MouseButtonPress, QCursor::pos(), Qt::LeftButton,
-                      Qt::LeftButton, Qt::NoModifier);
-    event.setTimestamp(static_cast<qint64>(WTF::currentTimeMS()));
-    QCoreApplication::sendEvent(this, &event);
-}
-
-void WebPopupMenuProxyQtDesktop::hidePopupMenu()
-{
-    hidePopup();
-}
-
-bool WebPopupMenuProxyQtDesktop::eventFilter(QObject *watched, QEvent *event)
-{
-    Q_ASSERT(watched == view());
-    if (event->type() == QEvent::Hide) {
-        if (m_client)
-            m_client->valueChangedForPopupMenu(this, m_selectedIndex);
-    }
-    return false;
-}
-
-void WebPopupMenuProxyQtDesktop::setSelectedIndex(int index)
-{
-    m_selectedIndex = index;
-}
-
-void WebPopupMenuProxyQtDesktop::populate(const Vector<WebPopupItem>& items)
-{
-    clear();
-
-    QStandardItemModel* model = qobject_cast<QStandardItemModel*>(this->model());
-    Q_ASSERT(model);
-
-    for (size_t i = 0; i < items.size(); ++i) {
-        const WebPopupItem& item = items.at(i);
-        if (item.m_type == WebPopupItem::Separator) {
-            insertSeparator(i);
-            continue;
-        }
-        insertItem(i, item.m_text);
-        model->item(i)->setToolTip(item.m_toolTip);
-        model->item(i)->setEnabled(item.m_isEnabled);
-    }
-}
-
-#include "moc_WebPopupMenuProxyQtDesktop.cpp"
-
-} // namespace WebKit
</del></span></pre></div>
<a id="trunkSourceWebKit2UIProcessqtWebPopupMenuProxyQtDesktoph"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQtDesktop.h (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQtDesktop.h   2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQtDesktop.h      2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -1,71 +0,0 @@
</span><del>-/*
- * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef WebPopupMenuProxyQtDesktop_h
-#define WebPopupMenuProxyQtDesktop_h
-
-#include "WebPopupMenuProxy.h"
-#include <QComboBox>
-#include <QObject>
-#include <QWeakPointer>
-
-class QQuickItem;
-
-namespace WebCore {
-class QtWebComboBox;
-}
-
-namespace WebKit {
-
-class WebPopupMenuProxyQtDesktop : public QComboBox, public WebPopupMenuProxy {
-    Q_OBJECT
-
-public:
-    virtual ~WebPopupMenuProxyQtDesktop();
-
-    static PassRefPtr<WebPopupMenuProxyQtDesktop> create(WebPopupMenuProxy::Client* client, QQuickItem* webViewItem)
-    {
-        return adoptRef(new WebPopupMenuProxyQtDesktop(client, webViewItem));
-    }
-
-    virtual void showPopupMenu(const WebCore::IntRect&, WebCore::TextDirection, double pageScaleFactor, const Vector<WebPopupItem>&, const PlatformPopupMenuData&, int32_t selectedIndex);
-    virtual void hidePopupMenu();
-
-    virtual bool eventFilter(QObject* watched, QEvent*);
-
-private Q_SLOTS:
-    void setSelectedIndex(int);
-
-private:
-    WebPopupMenuProxyQtDesktop(WebPopupMenuProxy::Client*, QQuickItem* webViewItem);
-    void populate(const Vector<WebPopupItem>&);
-
-    QQuickItem* m_webViewItem;
-    int32_t m_selectedIndex;
-};
-
-} // namespace WebKit
-
-#endif // WebPopupMenuProxyQtDesktop_h
</del></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog    2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Tools/ChangeLog       2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2011-12-12  Caio Marcelo de Oliveira Filho  <caio.oliveira@openbossa.org>
+
+        [Qt] [WK2] Support customizing popup menus with QML
+        https://bugs.webkit.org/show_bug.cgi?id=73560
+
+        Reviewed by Tor Arne Vestbø.
+
+        Add an Item Selector to our WebView using the experimental API.
+
+        * MiniBrowser/qt/MiniBrowser.pro:
+        * MiniBrowser/qt/MiniBrowser.qrc:
+        * MiniBrowser/qt/qml/BrowserWindow.qml:
+        * MiniBrowser/qt/qml/ItemSelector.qml: Added.
+
</ins><span class="cx"> 2011-12-12  Alexander Færøy  <alexander.faeroy@nokia.com>
</span><span class="cx"> 
</span><span class="cx">         [Qt] MiniBrowser should only visualize mock touch points when in non-desktop mode
</span></span></pre></div>
<a id="trunkToolsMiniBrowserqtMiniBrowserpro"></a>
<div class="modfile"><h4>Modified: trunk/Tools/MiniBrowser/qt/MiniBrowser.pro (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/MiniBrowser/qt/MiniBrowser.pro       2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Tools/MiniBrowser/qt/MiniBrowser.pro  2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -30,4 +30,5 @@
</span><span class="cx"> RESOURCES += MiniBrowser.qrc
</span><span class="cx"> 
</span><span class="cx"> OTHER_FILES += \
</span><del>-    qml/BrowserWindow.qml
</del><ins>+    qml/BrowserWindow.qml \
+    qml/ItemSelector.qml
</ins></span></pre></div>
<a id="trunkToolsMiniBrowserqtMiniBrowserqrc"></a>
<div class="modfile"><h4>Modified: trunk/Tools/MiniBrowser/qt/MiniBrowser.qrc (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/MiniBrowser/qt/MiniBrowser.qrc       2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Tools/MiniBrowser/qt/MiniBrowser.qrc  2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -6,6 +6,7 @@
</span><span class="cx">         <file>icons/stop.png</file>
</span><span class="cx">         <file>icons/touchpoint.png</file>
</span><span class="cx">         <file>qml/BrowserWindow.qml</file>
</span><ins>+        <file>qml/ItemSelector.qml</file>
</ins><span class="cx">         <file>qml/MockTouchPoint.qml</file>
</span><span class="cx">         <file>useragentlist.txt</file>
</span><span class="cx">     </qresource>
</span></span></pre></div>
<a id="trunkToolsMiniBrowserqtqmlBrowserWindowqml"></a>
<div class="modfile"><h4>Modified: trunk/Tools/MiniBrowser/qt/qml/BrowserWindow.qml (102572 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/MiniBrowser/qt/qml/BrowserWindow.qml 2011-12-12 13:41:10 UTC (rev 102572)
+++ trunk/Tools/MiniBrowser/qt/qml/BrowserWindow.qml    2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> import QtQuick 2.0
</span><span class="cx"> import QtWebKit 3.0
</span><ins>+import QtWebKit.experimental 3.0
</ins><span class="cx"> 
</span><span class="cx"> Rectangle {
</span><span class="cx">     // Do not define anchors or an initial size here! This would mess up with QSGView::SizeRootObjectToView.
</span><span class="lines">@@ -230,6 +231,8 @@
</span><span class="cx">                 console.log("Loaded:", webView.url);
</span><span class="cx">             forceActiveFocus();
</span><span class="cx">         }
</span><ins>+
+        experimental.itemSelector: ItemSelector { }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     Keys.onPressed: {
</span></span></pre></div>
<a id="trunkToolsMiniBrowserqtqmlItemSelectorqml"></a>
<div class="addfile"><h4>Added: trunk/Tools/MiniBrowser/qt/qml/ItemSelector.qml (0 => 102573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/MiniBrowser/qt/qml/ItemSelector.qml                          (rev 0)
+++ trunk/Tools/MiniBrowser/qt/qml/ItemSelector.qml     2011-12-12 13:53:13 UTC (rev 102573)
</span><span class="lines">@@ -0,0 +1,83 @@
</span><ins>+/*
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import QtQuick 2.0
+
+MouseArea {
+    // To avoid conflicting with ListView.model when inside ListView context.
+    property QtObject selectorModel: model
+    anchors.fill: parent
+    onClicked: selectorModel.reject()
+
+    Rectangle {
+        clip: true
+        x: selectorModel.elementRect.x
+        y: selectorModel.elementRect.y + selectorModel.elementRect.height
+        height: Math.min(400, parent.height - y)
+        width: 200
+        radius: 5
+        color: "gainsboro"
+        opacity: 0.8
+
+        ListView {
+            anchors.fill: parent
+            anchors.margins: 10
+            spacing: 5
+            model: selectorModel.items
+
+            delegate: Rectangle {
+                color: model.selected ? "gold" : "silver"
+                height: 50
+                width: parent.width
+
+                Text {
+                    anchors.centerIn: parent
+                    text: model.text
+                    color: model.enabled ? "black" : "gainsboro"
+                }
+
+                MouseArea {
+                    anchors.fill: parent
+                    enabled: model.enabled
+                    onClicked: selectorModel.accept(model.index)
+                }
+            }
+
+            section.property: "group"
+            section.delegate: Rectangle {
+                height: 30
+                width: parent.width
+                color: "silver"
+                Text {
+                    anchors.centerIn: parent
+                    text: section
+                    font.bold: true
+                }
+            }
+        }
+    }
+}
</ins></span></pre>
</div>
</div>

</body>
</html>