• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #if ENABLE(SYMBIAN_DIALOG_PROVIDERS)
39 #include <BrCtlDialogsProvider.h>
40 #include <BrowserDialogsProvider.h> // S60 platform private header file
41 #include <e32base.h>
42 #endif
43 
44 namespace WebCore {
45 
QtFallbackWebPopupCombo(QtFallbackWebPopup & ownerPopup)46 QtFallbackWebPopupCombo::QtFallbackWebPopupCombo(QtFallbackWebPopup& ownerPopup)
47     : m_ownerPopup(ownerPopup)
48 {
49     // Install an event filter on the view inside the combo box popup to make sure we know
50     // when the popup got closed. E.g. QComboBox::hidePopup() won't be called when the popup
51     // is closed by a mouse wheel event outside its window.
52     view()->installEventFilter(this);
53 }
54 
showPopup()55 void QtFallbackWebPopupCombo::showPopup()
56 {
57     QComboBox::showPopup();
58     m_ownerPopup.m_popupVisible = true;
59 }
60 
hidePopup()61 void QtFallbackWebPopupCombo::hidePopup()
62 {
63 #ifndef QT_NO_IM
64     QWidget* activeFocus = QApplication::focusWidget();
65     if (activeFocus && activeFocus == QComboBox::view()
66         && activeFocus->testAttribute(Qt::WA_InputMethodEnabled)) {
67         QInputContext* qic = activeFocus->inputContext();
68         if (qic) {
69             qic->reset();
70             qic->setFocusWidget(0);
71         }
72     }
73 #endif // QT_NO_IM
74 
75     QComboBox::hidePopup();
76 
77     if (!m_ownerPopup.m_popupVisible)
78         return;
79 
80     m_ownerPopup.m_popupVisible = false;
81     emit m_ownerPopup.didHide();
82     m_ownerPopup.destroyPopup();
83 }
84 
eventFilter(QObject * watched,QEvent * event)85 bool QtFallbackWebPopupCombo::eventFilter(QObject* watched, QEvent* event)
86 {
87     Q_ASSERT(watched == view());
88 
89     if (event->type() == QEvent::Show && !m_ownerPopup.m_popupVisible)
90         showPopup();
91     else if (event->type() == QEvent::Hide && m_ownerPopup.m_popupVisible)
92         hidePopup();
93 
94     return false;
95 }
96 
97 // QtFallbackWebPopup
98 
QtFallbackWebPopup(const ChromeClientQt * chromeClient)99 QtFallbackWebPopup::QtFallbackWebPopup(const ChromeClientQt* chromeClient)
100     : m_popupVisible(false)
101     , m_combo(0)
102     , m_chromeClient(chromeClient)
103 {
104 }
105 
~QtFallbackWebPopup()106 QtFallbackWebPopup::~QtFallbackWebPopup()
107 {
108     destroyPopup();
109 }
110 
show(const QWebSelectData & data)111 void QtFallbackWebPopup::show(const QWebSelectData& data)
112 {
113     if (!pageClient())
114         return;
115 
116 #if ENABLE(SYMBIAN_DIALOG_PROVIDERS)
117     TRAP_IGNORE(showS60BrowserDialog());
118 #else
119 
120     destroyPopup();
121     m_combo = new QtFallbackWebPopupCombo(*this);
122     connect(m_combo, SIGNAL(activated(int)),
123             SLOT(activeChanged(int)), Qt::QueuedConnection);
124 
125     populate(data);
126 
127     QColor backgroundColor = data.backgroundColor();
128     QColor foregroundColor = data.foregroundColor();
129 
130     QPalette palette = m_combo->palette();
131     if (backgroundColor.isValid())
132         palette.setColor(QPalette::Background, backgroundColor);
133     if (foregroundColor.isValid())
134         palette.setColor(QPalette::Foreground, foregroundColor);
135     m_combo->setPalette(palette);
136 
137 
138     QRect rect = geometry();
139     if (QGraphicsWebView *webView = qobject_cast<QGraphicsWebView*>(pageClient()->pluginParent())) {
140         QGraphicsProxyWidget* proxy = new QGraphicsProxyWidget(webView);
141         proxy->setWidget(m_combo);
142         proxy->setGeometry(rect);
143     } else {
144         m_combo->setParent(pageClient()->ownerWidget());
145         m_combo->setGeometry(QRect(rect.left(), rect.top(),
146                                rect.width(), m_combo->sizeHint().height()));
147 
148     }
149 
150     QMouseEvent event(QEvent::MouseButtonPress, QCursor::pos(), Qt::LeftButton,
151                       Qt::LeftButton, Qt::NoModifier);
152     QCoreApplication::sendEvent(m_combo, &event);
153 #endif
154 }
155 
156 #if ENABLE(SYMBIAN_DIALOG_PROVIDERS)
157 
ResetAndDestroy(TAny * aPtr)158 static void ResetAndDestroy(TAny* aPtr)
159 {
160     RPointerArray<HBufC>* items = reinterpret_cast<RPointerArray<HBufC>* >(aPtr);
161     items->ResetAndDestroy();
162 }
163 
showS60BrowserDialog()164 void QtFallbackWebPopup::showS60BrowserDialog()
165 {
166     static MBrCtlDialogsProvider* dialogs = CBrowserDialogsProvider::NewL(0);
167     if (!dialogs)
168         return;
169 
170     int size = itemCount();
171     CArrayFix<TBrCtlSelectOptionData>* options = new CArrayFixFlat<TBrCtlSelectOptionData>(qMax(1, size));
172     RPointerArray<HBufC> items(qMax(1, size));
173     CleanupStack::PushL(TCleanupItem(&ResetAndDestroy, &items));
174 
175     for (int i = 0; i < size; i++) {
176         if (itemType(i) == Separator) {
177             TBrCtlSelectOptionData data(_L("----------"), false, false, false);
178             options->AppendL(data);
179         } else {
180             HBufC16* itemStr = HBufC16::NewL(itemText(i).length());
181             itemStr->Des().Copy((const TUint16*)itemText(i).utf16(), itemText(i).length());
182             CleanupStack::PushL(itemStr);
183             TBrCtlSelectOptionData data(*itemStr, i == currentIndex(), false, itemIsEnabled(i));
184             options->AppendL(data);
185             items.AppendL(itemStr);
186             CleanupStack::Pop();
187         }
188     }
189 
190     dialogs->DialogSelectOptionL(KNullDesC(), (TBrCtlSelectOptionType)(ESelectTypeSingle | ESelectTypeWithFindPane), *options);
191 
192     CleanupStack::PopAndDestroy(&items);
193 
194     int newIndex;
195     for (newIndex = 0; newIndex < options->Count() && !options->At(newIndex).IsSelected(); newIndex++) {}
196     if (newIndex == options->Count())
197         newIndex = currentIndex();
198 
199     m_popupVisible = false;
200     popupDidHide();
201 
202     if (currentIndex() != newIndex && newIndex >= 0)
203         valueChanged(newIndex);
204 
205     delete options;
206 }
207 #endif
208 
hide()209 void QtFallbackWebPopup::hide()
210 {
211     // Destroying the QComboBox here cause problems if the popup is in the
212     // middle of its show animation. Instead we rely on the fact that the
213     // Qt::Popup window will hide itself on mouse events outside its window.
214 }
215 
destroyPopup()216 void QtFallbackWebPopup::destroyPopup()
217 {
218     if (m_combo) {
219         m_combo->deleteLater();
220         m_combo = 0;
221     }
222 }
223 
populate(const QWebSelectData & data)224 void QtFallbackWebPopup::populate(const QWebSelectData& data)
225 {
226     QStandardItemModel* model = qobject_cast<QStandardItemModel*>(m_combo->model());
227     Q_ASSERT(model);
228 
229 #if !defined(Q_OS_SYMBIAN)
230     m_combo->setFont(font());
231 #endif
232 
233     int currentIndex = -1;
234     for (int i = 0; i < data.itemCount(); ++i) {
235         switch (data.itemType(i)) {
236         case QWebSelectData::Separator:
237             m_combo->insertSeparator(i);
238             break;
239         case QWebSelectData::Group:
240             m_combo->insertItem(i, data.itemText(i));
241             model->item(i)->setEnabled(false);
242             break;
243         case QWebSelectData::Option:
244             m_combo->insertItem(i, data.itemText(i));
245             model->item(i)->setEnabled(data.itemIsEnabled(i));
246 #ifndef QT_NO_TOOLTIP
247             model->item(i)->setToolTip(data.itemToolTip(i));
248 #endif
249             model->item(i)->setBackground(data.itemBackgroundColor(i));
250             model->item(i)->setForeground(data.itemForegroundColor(i));
251             if (data.itemIsSelected(i))
252                 currentIndex = i;
253             break;
254         }
255     }
256 
257     if (currentIndex >= 0)
258         m_combo->setCurrentIndex(currentIndex);
259 }
260 
activeChanged(int index)261 void QtFallbackWebPopup::activeChanged(int index)
262 {
263     if (index < 0)
264         return;
265 
266     emit selectItem(index, false, false);
267 }
268 
pageClient() const269 QWebPageClient* QtFallbackWebPopup::pageClient() const
270 {
271     return m_chromeClient->platformPageClient();
272 }
273 
274 }
275 
276 #endif // QT_NO_COMBOBOX
277