/******************************************************************************** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).** All rights reserved.** Contact: Nokia Corporation (qt-info@nokia.com)**** This file is part of the QtGui module of the Qt Toolkit.**** $QT_BEGIN_LICENSE:LGPL$** No Commercial Usage** This file contains pre-release code and may not be distributed.** You may use this file in accordance with the terms and conditions** contained in the Technology Preview License Agreement accompanying** this package.**** GNU Lesser General Public License Usage** Alternatively, this file may be used under the terms of the GNU Lesser** General Public License version 2.1 as published by the Free Software** Foundation and appearing in the file LICENSE.LGPL included in the** packaging of this file. Please review the following information to** ensure the GNU Lesser General Public License version 2.1 requirements** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.**** In addition, as a special exception, Nokia gives you certain additional** rights. These rights are described in the Nokia Qt LGPL Exception** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.**** If you have questions regarding the use of this file, please contact** Nokia at qt-info@nokia.com.****************** $QT_END_LICENSE$******************************************************************************/#include "qapplication.h"#include "qevent.h"#include "qbitmap.h"#include "private/qsoftkeymanager_p.h"#include "private/qaction_p.h"#include "private/qsoftkeymanager_common_p.h"#ifdef Q_WS_S60#include "private/qsoftkeymanager_s60_p.h"#endif#ifndef QT_NO_SOFTKEYMANAGERQT_BEGIN_NAMESPACEQSoftKeyManager *QSoftKeyManagerPrivate::self = 0;QString QSoftKeyManager::standardSoftKeyText(StandardSoftKey standardKey){ QString softKeyText; switch (standardKey) { case OkSoftKey: softKeyText = QSoftKeyManager::tr("Ok"); break; case SelectSoftKey: softKeyText = QSoftKeyManager::tr("Select"); break; case DoneSoftKey: softKeyText = QSoftKeyManager::tr("Done"); break; case MenuSoftKey: softKeyText = QSoftKeyManager::tr("Options"); break; case CancelSoftKey: softKeyText = QSoftKeyManager::tr("Cancel"); break; default: break; }; return softKeyText;}QSoftKeyManager *QSoftKeyManager::instance(){ if (!QSoftKeyManagerPrivate::self) QSoftKeyManagerPrivate::self = new QSoftKeyManager; return QSoftKeyManagerPrivate::self;}QSoftKeyManager::QSoftKeyManager() :#ifdef Q_WS_S60 QObject(*(new QSoftKeyManagerPrivateS60), 0)#else QObject(*(new QSoftKeyManagerPrivate), 0)#endif{}QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *actionWidget){ QAction *action = new QAction(standardSoftKeyText(standardKey), actionWidget); QAction::SoftKeyRole softKeyRole = QAction::NoSoftKey; switch (standardKey) { case MenuSoftKey: // FALL-THROUGH QActionPrivate::get(action)->menuActionSoftkeys = true; case OkSoftKey: case SelectSoftKey: case DoneSoftKey: softKeyRole = QAction::PositiveSoftKey; break; case CancelSoftKey: softKeyRole = QAction::NegativeSoftKey; break; } action->setSoftKeyRole(softKeyRole); action->setVisible(false); setForceEnabledInSoftkeys(action); return action;}/*! \internal Creates a QAction and registers the 'triggered' signal to send the given key event to \a actionWidget as a convenience.*/QAction *QSoftKeyManager::createKeyedAction(StandardSoftKey standardKey, Qt::Key key, QWidget *actionWidget){#ifndef QT_NO_ACTION QScopedPointer<QAction> action(createAction(standardKey, actionWidget)); connect(action.data(), SIGNAL(triggered()), QSoftKeyManager::instance(), SLOT(sendKeyEvent())); connect(action.data(), SIGNAL(destroyed(QObject*)), QSoftKeyManager::instance(), SLOT(cleanupHash(QObject*))); QSoftKeyManager::instance()->d_func()->keyedActions.insert(action.data(), key); return action.take();#endif //QT_NO_ACTION}void QSoftKeyManager::cleanupHash(QObject *obj){ Q_D(QSoftKeyManager); QAction *action = qobject_cast<QAction*>(obj); d->keyedActions.remove(action);}void QSoftKeyManager::sendKeyEvent(){ Q_D(QSoftKeyManager); QAction *action = qobject_cast<QAction*>(sender()); if (!action) return; Qt::Key keyToSend = d->keyedActions.value(action, Qt::Key_unknown); if (keyToSend != Qt::Key_unknown) QApplication::postEvent(action->parentWidget(), new QKeyEvent(QEvent::KeyPress, keyToSend, Qt::NoModifier));}void QSoftKeyManager::updateSoftKeys(){ QSoftKeyManager::instance()->d_func()->pendingUpdate = true; QEvent *event = new QEvent(QEvent::UpdateSoftKeys); QApplication::postEvent(QSoftKeyManager::instance(), event);}bool QSoftKeyManager::appendSoftkeys(const QWidget &source, int level){ Q_D(QSoftKeyManager); bool ret = false; foreach(QAction *action, source.actions()) { if (action->softKeyRole() != QAction::NoSoftKey && (action->isVisible() || isForceEnabledInSofkeys(action))) { d->requestedSoftKeyActions.insert(level, action); ret = true; } } return ret;}static bool isChildOf(const QWidget *c, const QWidget *p){ while (c) { if (c == p) return true; c = c->parentWidget(); } return false;}QWidget *QSoftKeyManager::softkeySource(QWidget *previousSource, bool& recursiveMerging){ Q_D(QSoftKeyManager); QWidget *source = NULL; if (!previousSource) { // Initial source is primarily focuswidget and secondarily activeWindow QWidget *focus = QApplication::focusWidget(); QWidget *popup = QApplication::activePopupWidget(); if (popup) { if (isChildOf(focus, popup)) source = focus; else source = popup; } if (!source) { QWidget *modal = QApplication::activeModalWidget(); if (modal) { if (isChildOf(focus, modal)) source = focus; else source = modal; } } if (!source) { source = focus; if (!source) source = QApplication::activeWindow(); } } else { // Softkey merging is based on four criterias // 1. Implicit merging is used whenever focus widget does not specify any softkeys bool implicitMerging = d->requestedSoftKeyActions.isEmpty(); // 2. Explicit merging with parent is used whenever WA_MergeSoftkeys widget attribute is set bool explicitMerging = previousSource->testAttribute(Qt::WA_MergeSoftkeys); // 3. Explicit merging with all parents recursiveMerging |= previousSource->testAttribute(Qt::WA_MergeSoftkeysRecursively); // 4. Implicit and explicit merging always stops at window boundary bool merging = (implicitMerging || explicitMerging || recursiveMerging) && !previousSource->isWindow(); source = merging ? previousSource->parentWidget() : NULL; } return source;}bool QSoftKeyManager::handleUpdateSoftKeys(){ Q_D(QSoftKeyManager); int level = 0; d->requestedSoftKeyActions.clear(); bool recursiveMerging = false; QWidget *source = softkeySource(NULL, recursiveMerging); d->initialSoftKeySource = source; while (source) { if (appendSoftkeys(*source, level)) ++level; source = softkeySource(source, recursiveMerging); } d->updateSoftKeys_sys(); d->pendingUpdate = false; return true;}void QSoftKeyManager::setForceEnabledInSoftkeys(QAction *action){ QActionPrivate::get(action)->forceEnabledInSoftkeys = true;}bool QSoftKeyManager::isForceEnabledInSofkeys(QAction *action){ return QActionPrivate::get(action)->forceEnabledInSoftkeys;}bool QSoftKeyManager::event(QEvent *e){#ifndef QT_NO_ACTION if (e->type() == QEvent::UpdateSoftKeys) return handleUpdateSoftKeys();#endif //QT_NO_ACTION return false;}#ifdef Q_WS_S60bool QSoftKeyManager::handleCommand(int command){ if (QSoftKeyManager::instance()->d_func()->pendingUpdate) (void)QSoftKeyManager::instance()->handleUpdateSoftKeys(); return static_cast<QSoftKeyManagerPrivateS60*>(QSoftKeyManager::instance()->d_func())->handleCommand(command);}#endifQT_END_NAMESPACE#endif //QT_NO_SOFTKEYMANAGER