a51610636071498a33efa0ad4d0543cda5734f78
[WebKit-https.git] / Source / WebKit / qt / WebCoreSupport / QtFallbackWebPopup.cpp
1 /*
2  * Copyright (C) 2010 Girish Ramakrishnan <girish@forwardbias.in>
3  * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  */
21 #include "config.h"
22 #include "QtFallbackWebPopup.h"
23
24 #ifndef QT_NO_COMBOBOX
25
26 #include "ChromeClientQt.h"
27 #include "QWebPageClient.h"
28 #include "qgraphicswebview.h"
29 #include <QAbstractItemView>
30 #include <QApplication>
31 #include <QGraphicsProxyWidget>
32 #include <QGraphicsScene>
33 #include <QGraphicsView>
34 #include <QInputContext>
35 #include <QMouseEvent>
36 #include <QStandardItemModel>
37
38 namespace WebCore {
39
40 QtFallbackWebPopupCombo::QtFallbackWebPopupCombo(QtFallbackWebPopup& ownerPopup)
41     : m_ownerPopup(ownerPopup)
42 {
43     // Install an event filter on the view inside the combo box popup to make sure we know
44     // when the popup got closed. E.g. QComboBox::hidePopup() won't be called when the popup
45     // is closed by a mouse wheel event outside its window.
46     view()->installEventFilter(this);
47 }
48
49 void QtFallbackWebPopupCombo::showPopup()
50 {
51     QComboBox::showPopup();
52     m_ownerPopup.m_popupVisible = true;
53 }
54
55 void QtFallbackWebPopupCombo::hidePopup()
56 {
57 #ifndef QT_NO_IM
58     QWidget* activeFocus = QApplication::focusWidget();
59     if (activeFocus && activeFocus == QComboBox::view()
60         && activeFocus->testAttribute(Qt::WA_InputMethodEnabled)) {
61         QInputContext* qic = activeFocus->inputContext();
62         if (qic) {
63             qic->reset();
64             qic->setFocusWidget(0);
65         }
66     }
67 #endif // QT_NO_IM
68
69     QComboBox::hidePopup();
70
71     if (!m_ownerPopup.m_popupVisible)
72         return;
73
74     m_ownerPopup.m_popupVisible = false;
75     emit m_ownerPopup.didHide();
76     m_ownerPopup.destroyPopup();
77 }
78
79 bool QtFallbackWebPopupCombo::eventFilter(QObject* watched, QEvent* event)
80 {
81     Q_ASSERT(watched == view());
82
83     if (event->type() == QEvent::Show && !m_ownerPopup.m_popupVisible)
84         showPopup();
85     else if (event->type() == QEvent::Hide && m_ownerPopup.m_popupVisible)
86         hidePopup();
87
88     return false;
89 }
90
91 // QtFallbackWebPopup
92
93 QtFallbackWebPopup::QtFallbackWebPopup(const ChromeClientQt* chromeClient)
94     : m_popupVisible(false)
95     , m_combo(0)
96     , m_chromeClient(chromeClient)
97 {
98 }
99
100 QtFallbackWebPopup::~QtFallbackWebPopup()
101 {
102     destroyPopup();
103 }
104
105 void QtFallbackWebPopup::show(const QWebSelectData& data)
106 {
107     if (!pageClient())
108         return;
109
110     destroyPopup();
111     m_combo = new QtFallbackWebPopupCombo(*this);
112     connect(m_combo, SIGNAL(activated(int)),
113             SLOT(activeChanged(int)), Qt::QueuedConnection);
114
115     populate(data);
116
117     QRect rect = geometry();
118     if (QGraphicsWebView *webView = qobject_cast<QGraphicsWebView*>(pageClient()->pluginParent())) {
119         QGraphicsProxyWidget* proxy = new QGraphicsProxyWidget(webView);
120         proxy->setWidget(m_combo);
121         proxy->setGeometry(rect);
122     } else {
123         m_combo->setParent(pageClient()->ownerWidget());
124         m_combo->setGeometry(QRect(rect.left(), rect.top(),
125                                rect.width(), m_combo->sizeHint().height()));
126
127     }
128
129     QMouseEvent event(QEvent::MouseButtonPress, QCursor::pos(), Qt::LeftButton,
130                       Qt::LeftButton, Qt::NoModifier);
131     QCoreApplication::sendEvent(m_combo, &event);
132 }
133
134 void QtFallbackWebPopup::hide()
135 {
136     // Destroying the QComboBox here cause problems if the popup is in the
137     // middle of its show animation. Instead we rely on the fact that the
138     // Qt::Popup window will hide itself on mouse events outside its window.
139 }
140
141 void QtFallbackWebPopup::destroyPopup()
142 {
143     if (m_combo) {
144         m_combo->deleteLater();
145         m_combo = 0;
146     }
147 }
148
149 void QtFallbackWebPopup::populate(const QWebSelectData& data)
150 {
151     QStandardItemModel* model = qobject_cast<QStandardItemModel*>(m_combo->model());
152     Q_ASSERT(model);
153
154 #if !defined(Q_OS_SYMBIAN)
155     m_combo->setFont(font());
156 #endif
157
158     int currentIndex = -1;
159     for (int i = 0; i < data.itemCount(); ++i) {
160         switch (data.itemType(i)) {
161         case QWebSelectData::Separator:
162             m_combo->insertSeparator(i);
163             break;
164         case QWebSelectData::Group:
165             m_combo->insertItem(i, data.itemText(i));
166             model->item(i)->setEnabled(false);
167             break;
168         case QWebSelectData::Option:
169             m_combo->insertItem(i, data.itemText(i));
170             model->item(i)->setEnabled(data.itemIsEnabled(i));
171 #ifndef QT_NO_TOOLTIP
172             model->item(i)->setToolTip(data.itemToolTip(i));
173 #endif
174             model->item(i)->setBackground(data.itemBackgroundColor(i));
175             model->item(i)->setForeground(data.itemForegroundColor(i));
176             if (data.itemIsSelected(i))
177                 currentIndex = i;
178             break;
179         }
180     }
181
182     if (currentIndex >= 0)
183         m_combo->setCurrentIndex(currentIndex);
184 }
185
186 void QtFallbackWebPopup::activeChanged(int index)
187 {
188     if (index < 0)
189         return;
190
191     emit selectItem(index, false, false);
192 }
193
194 QWebPageClient* QtFallbackWebPopup::pageClient() const
195 {
196     return m_chromeClient->platformPageClient();
197 }
198
199 }
200
201 #endif // QT_NO_COMBOBOX