From f67b8df3ebdba2d398b9cce686b7c644adffff08 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 7 May 2011 00:02:01 +0200 Subject: library split --- src/widgets/kernel/qsoftkeymanager.cpp | 319 +++++++++++++++++++++++++++++++++ 1 file changed, 319 insertions(+) create mode 100644 src/widgets/kernel/qsoftkeymanager.cpp (limited to 'src/widgets/kernel/qsoftkeymanager.cpp') diff --git a/src/widgets/kernel/qsoftkeymanager.cpp b/src/widgets/kernel/qsoftkeymanager.cpp new file mode 100644 index 0000000000..204efe9ee9 --- /dev/null +++ b/src/widgets/kernel/qsoftkeymanager.cpp @@ -0,0 +1,319 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 + +#ifdef SYMBIAN_VERSION_SYMBIAN3 +#include "private/qt_s60_p.h" +#endif + +#ifndef QT_NO_SOFTKEYMANAGER +QT_BEGIN_NAMESPACE + +QSoftKeyManager *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); +#ifdef SYMBIAN_VERSION_SYMBIAN3 + int key = 0; + switch (standardKey) { + case OkSoftKey: + key = EAknSoftkeyOk; + break; + case SelectSoftKey: + key = EAknSoftkeySelect; + break; + case DoneSoftKey: + key = EAknSoftkeyDone; + break; + case MenuSoftKey: + key = EAknSoftkeyOptions; + break; + case CancelSoftKey: + key = EAknSoftkeyCancel; + break; + default: + break; + }; + if (key != 0) + QSoftKeyManager::instance()->d_func()->softKeyCommandActions.insert(action, key); +#endif + 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 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(obj); + d->keyedActions.remove(action); +#ifdef SYMBIAN_VERSION_SYMBIAN3 + d->softKeyCommandActions.remove(action); +#endif +} + +void QSoftKeyManager::sendKeyEvent() +{ + Q_D(QSoftKeyManager); + QAction *action = qobject_cast(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_S60 +bool QSoftKeyManager::handleCommand(int command) +{ + if (QSoftKeyManager::instance()->d_func()->pendingUpdate) + (void)QSoftKeyManager::instance()->handleUpdateSoftKeys(); + + return static_cast(QSoftKeyManager::instance()->d_func())->handleCommand(command); +} +#endif + +QT_END_NAMESPACE +#endif //QT_NO_SOFTKEYMANAGER -- cgit v1.2.3