source: trunk/src/gui/kernel/qsoftkeymanager.cpp@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 10.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qapplication.h"
43#include "qevent.h"
44#ifdef Q_WS_S60
45#include "qstyle.h"
46#include "private/qt_s60_p.h"
47#endif
48#include "private/qsoftkeymanager_p.h"
49#include "private/qobject_p.h"
50
51#ifndef QT_NO_SOFTKEYMANAGER
52QT_BEGIN_NAMESPACE
53
54#ifdef Q_WS_S60
55static const int s60CommandStart = 6000;
56#endif
57
58class QSoftKeyManagerPrivate : public QObjectPrivate
59{
60 Q_DECLARE_PUBLIC(QSoftKeyManager)
61
62public:
63 static void updateSoftKeys_sys(const QList<QAction*> &softKeys);
64
65private:
66 QHash<QAction*, Qt::Key> keyedActions;
67 static QSoftKeyManager *self;
68 static QWidget *softKeySource;
69};
70
71QWidget *QSoftKeyManagerPrivate::softKeySource = 0;
72QSoftKeyManager *QSoftKeyManagerPrivate::self = 0;
73
74const char *QSoftKeyManager::standardSoftKeyText(StandardSoftKey standardKey)
75{
76 const char *softKeyText = 0;
77 switch (standardKey) {
78 case OkSoftKey:
79 softKeyText = QT_TRANSLATE_NOOP("QSoftKeyManager", "Ok");
80 break;
81 case SelectSoftKey:
82 softKeyText = QT_TRANSLATE_NOOP("QSoftKeyManager", "Select");
83 break;
84 case DoneSoftKey:
85 softKeyText = QT_TRANSLATE_NOOP("QSoftKeyManager", "Done");
86 break;
87 case MenuSoftKey:
88 softKeyText = QT_TRANSLATE_NOOP("QSoftKeyManager", "Options");
89 break;
90 case CancelSoftKey:
91 softKeyText = QT_TRANSLATE_NOOP("QSoftKeyManager", "Cancel");
92 break;
93 default:
94 break;
95 };
96
97 return softKeyText;
98}
99
100QSoftKeyManager *QSoftKeyManager::instance()
101{
102 if (!QSoftKeyManagerPrivate::self)
103 QSoftKeyManagerPrivate::self = new QSoftKeyManager;
104
105 return QSoftKeyManagerPrivate::self;
106}
107
108QSoftKeyManager::QSoftKeyManager() : QObject(*(new QSoftKeyManagerPrivate), 0)
109{
110}
111
112QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *actionWidget)
113{
114 const char* text = standardSoftKeyText(standardKey);
115 QAction *action = new QAction(QSoftKeyManager::tr(text), actionWidget);
116 QAction::SoftKeyRole softKeyRole = QAction::NoSoftKey;
117 switch (standardKey) {
118 case OkSoftKey:
119 case SelectSoftKey:
120 case DoneSoftKey:
121 case MenuSoftKey:
122 softKeyRole = QAction::PositiveSoftKey;
123 break;
124 case CancelSoftKey:
125 softKeyRole = QAction::NegativeSoftKey;
126 break;
127 }
128 action->setSoftKeyRole(softKeyRole);
129 return action;
130}
131
132/*! \internal
133
134 Creates a QAction and registers the 'triggered' signal to send the given key event to
135 \a actionWidget as a convenience.
136
137*/
138QAction *QSoftKeyManager::createKeyedAction(StandardSoftKey standardKey, Qt::Key key, QWidget *actionWidget)
139{
140#ifndef QT_NO_ACTION
141 QScopedPointer<QAction> action(createAction(standardKey, actionWidget));
142
143 connect(action.data(), SIGNAL(triggered()), QSoftKeyManager::instance(), SLOT(sendKeyEvent()));
144 connect(action.data(), SIGNAL(destroyed(QObject*)), QSoftKeyManager::instance(), SLOT(cleanupHash(QObject*)));
145 QSoftKeyManager::instance()->d_func()->keyedActions.insert(action.data(), key);
146 return action.take();
147#endif //QT_NO_ACTION
148}
149
150void QSoftKeyManager::cleanupHash(QObject* obj)
151{
152 Q_D(QSoftKeyManager);
153 QAction *action = qobject_cast<QAction*>(obj);
154 d->keyedActions.remove(action);
155}
156
157void QSoftKeyManager::sendKeyEvent()
158{
159 Q_D(QSoftKeyManager);
160 QAction *action = qobject_cast<QAction*>(sender());
161
162 if (!action)
163 return;
164
165 Qt::Key keyToSend = d->keyedActions.value(action, Qt::Key_unknown);
166
167 if (keyToSend != Qt::Key_unknown)
168 QApplication::postEvent(action->parentWidget(),
169 new QKeyEvent(QEvent::KeyPress, keyToSend, Qt::NoModifier));
170}
171
172void QSoftKeyManager::updateSoftKeys()
173{
174 QEvent *event = new QEvent(QEvent::UpdateSoftKeys);
175 QApplication::postEvent(QSoftKeyManager::instance(), event);
176}
177
178bool QSoftKeyManager::event(QEvent *e)
179{
180#ifndef QT_NO_ACTION
181 if (e->type() == QEvent::UpdateSoftKeys) {
182 QList<QAction*> softKeys;
183 QWidget *source = QApplication::focusWidget();
184 do {
185 if (source) {
186 QList<QAction*> actions = source->actions();
187 for (int i = 0; i < actions.count(); ++i) {
188 if (actions.at(i)->softKeyRole() != QAction::NoSoftKey)
189 softKeys.append(actions.at(i));
190 }
191
192 QWidget *parent = source->parentWidget();
193 if (parent && softKeys.isEmpty() && !source->isWindow())
194 source = parent;
195 else
196 break;
197 } else {
198 source = QApplication::activeWindow();
199 }
200 } while (source);
201
202 QSoftKeyManagerPrivate::softKeySource = source;
203 QSoftKeyManagerPrivate::updateSoftKeys_sys(softKeys);
204 return true;
205 }
206#endif //QT_NO_ACTION
207 return false;
208}
209
210#ifdef Q_WS_S60
211void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys)
212{
213 // lets not update softkeys if s60 native dialog or menu is shown
214 if (QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes)
215 || CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog())
216 return;
217
218 CEikButtonGroupContainer* nativeContainer = S60->buttonGroupContainer();
219 nativeContainer->DrawableWindow()->SetOrdinalPosition(0);
220 nativeContainer->DrawableWindow()->SetPointerCapturePriority(1); //keep softkeys available in modal dialog
221 nativeContainer->DrawableWindow()->SetFaded(EFalse, RWindowTreeNode::EFadeIncludeChildren);
222
223 int position = -1;
224 bool needsExitButton = true;
225 QT_TRAP_THROWING(
226 //Using -1 instead of EAknSoftkeyEmpty to avoid flickering.
227 nativeContainer->SetCommandL(0, -1, KNullDesC);
228 nativeContainer->SetCommandL(2, -1, KNullDesC);
229 );
230
231 for (int index = 0; index < softkeys.count(); index++) {
232 const QAction* softKeyAction = softkeys.at(index);
233 switch (softKeyAction->softKeyRole()) {
234 // Positive Actions on the LSK
235 case QAction::PositiveSoftKey:
236 position = 0;
237 break;
238 case QAction::SelectSoftKey:
239 position = 0;
240 break;
241 // Negative Actions on the RSK
242 case QAction::NegativeSoftKey:
243 needsExitButton = false;
244 position = 2;
245 break;
246 default:
247 break;
248 }
249
250 int command = (softKeyAction->objectName().contains(QLatin1String("_q_menuSoftKeyAction")))
251 ? EAknSoftkeyOptions
252 : s60CommandStart + index;
253
254 // _q_menuSoftKeyAction action is set to "invisible" and all invisible actions are by default
255 // disabled. However we never want to dim options softkey, even it is set to "invisible"
256 bool dimmed = (command == EAknSoftkeyOptions) ? false : !softKeyAction->isEnabled();
257
258 if (position != -1) {
259 const int underlineShortCut = QApplication::style()->styleHint(QStyle::SH_UnderlineShortcut);
260 QString iconText = softKeyAction->iconText();
261 TPtrC text = qt_QString2TPtrC( underlineShortCut ? softKeyAction->text() : iconText);
262 QT_TRAP_THROWING(
263 nativeContainer->SetCommandL(position, command, text);
264 nativeContainer->DimCommand(command, dimmed);
265 );
266 }
267 }
268
269 const Qt::WindowType sourceWindowType = QSoftKeyManagerPrivate::softKeySource
270 ? QSoftKeyManagerPrivate::softKeySource->window()->windowType()
271 : Qt::Widget;
272
273 if (needsExitButton && sourceWindowType != Qt::Dialog && sourceWindowType != Qt::Popup)
274 QT_TRAP_THROWING(
275 nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QSoftKeyManager::tr("Exit"))));
276
277 nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation
278}
279
280bool QSoftKeyManager::handleCommand(int command)
281{
282 if (command >= s60CommandStart && QSoftKeyManagerPrivate::softKeySource) {
283 int index = command - s60CommandStart;
284 const QList<QAction*>& softKeys = QSoftKeyManagerPrivate::softKeySource->actions();
285 for (int i = 0, j = 0; i < softKeys.count(); ++i) {
286 QAction *action = softKeys.at(i);
287 if (action->softKeyRole() != QAction::NoSoftKey) {
288 if (j == index) {
289 QWidget *parent = action->parentWidget();
290 if (parent && parent->isEnabled()) {
291 action->activate(QAction::Trigger);
292 return true;
293 }
294 }
295 j++;
296 }
297 }
298 }
299
300 return false;
301}
302
303#else
304
305void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &)
306{
307}
308
309#endif
310
311QT_END_NAMESPACE
312#endif //QT_NO_SOFTKEYMANAGER
Note: See TracBrowser for help on using the repository browser.