diff options
author | Markku Luukkainen <markku.luukkainen@digia.com> | 2009-06-10 10:57:54 (GMT) |
---|---|---|
committer | Markku Luukkainen <markku.luukkainen@digia.com> | 2009-06-10 10:57:54 (GMT) |
commit | 1c97ec260bd398912d64b0328299d50207962ad4 (patch) | |
tree | 138228023b086a943828b0ef6b16a1c1cde8d8fb | |
parent | 47746f46920e4d09d4524fc2466b25626b2454bf (diff) | |
parent | 9009dce133b015cd2c7060d1f4747f3733dcf546 (diff) | |
download | Qt-1c97ec260bd398912d64b0328299d50207962ad4.zip Qt-1c97ec260bd398912d64b0328299d50207962ad4.tar.gz Qt-1c97ec260bd398912d64b0328299d50207962ad4.tar.bz2 |
Merge branch 'softkeys_without_stack'
-rw-r--r-- | examples/widgets/softkeys/main.cpp | 21 | ||||
-rw-r--r-- | examples/widgets/softkeys/softkeys.cpp | 61 | ||||
-rw-r--r-- | examples/widgets/softkeys/softkeys.h | 79 | ||||
-rw-r--r-- | examples/widgets/softkeys/softkeys.pro | 4 | ||||
-rw-r--r-- | src/gui/itemviews/qabstractitemview.cpp | 9 | ||||
-rw-r--r-- | src/gui/kernel/qaction.cpp | 26 | ||||
-rw-r--r-- | src/gui/kernel/qaction.h | 10 | ||||
-rw-r--r-- | src/gui/kernel/qaction_p.h | 1 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 14 | ||||
-rw-r--r-- | src/gui/kernel/qwidget.cpp | 66 | ||||
-rw-r--r-- | src/gui/kernel/qwidget.h | 3 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_p.h | 5 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_s60.cpp | 53 | ||||
-rw-r--r-- | src/gui/widgets/qactiontokeyeventmapper.cpp | 103 | ||||
-rw-r--r-- | src/gui/widgets/qactiontokeyeventmapper_p.h | 70 | ||||
-rw-r--r-- | src/gui/widgets/qcombobox.cpp | 8 | ||||
-rw-r--r-- | src/gui/widgets/qmainwindow.cpp | 5 | ||||
-rw-r--r-- | src/gui/widgets/qmenu.cpp | 14 | ||||
-rw-r--r-- | src/gui/widgets/qmenu_symbian.cpp | 79 | ||||
-rw-r--r-- | src/gui/widgets/qmenubar_p.h | 1 | ||||
-rw-r--r-- | src/gui/widgets/widgets.pri | 8 | ||||
-rw-r--r-- | src/s60main/qts60mainappui.cpp | 3 |
22 files changed, 598 insertions, 45 deletions
diff --git a/examples/widgets/softkeys/main.cpp b/examples/widgets/softkeys/main.cpp new file mode 100644 index 0000000..a355f93 --- /dev/null +++ b/examples/widgets/softkeys/main.cpp @@ -0,0 +1,21 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> +#include "softkeys.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + MainWindow mw; + mw.showMaximized(); + return app.exec(); +} diff --git a/examples/widgets/softkeys/softkeys.cpp b/examples/widgets/softkeys/softkeys.cpp new file mode 100644 index 0000000..edf38b9 --- /dev/null +++ b/examples/widgets/softkeys/softkeys.cpp @@ -0,0 +1,61 @@ +#include "softkeys.h" + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) +{ + fileMenu = menuBar()->addMenu(tr("&File")); + openDialogAct = new QAction(tr("&Open Dialog"), this); + addSoftKeysAct = new QAction(tr("&Add Softkeys"), this); + clearSoftKeysAct = new QAction(tr("&Clear Softkeys"), this); + fileMenu->addAction(openDialogAct); + fileMenu->addAction(addSoftKeysAct); + fileMenu->addAction(clearSoftKeysAct); + connect(openDialogAct, SIGNAL(triggered()), this, SLOT(openDialog())); + connect(addSoftKeysAct, SIGNAL(triggered()), this, SLOT(addSoftKeys())); + connect(clearSoftKeysAct, SIGNAL(triggered()), this, SLOT(clearSoftKeys())); + QWidget *central = new QWidget(this); + central->setLayout(new QVBoxLayout); +// central->setFocus(); + setCentralWidget(central); + QPushButton button1; +// QAction* menuAction = +} + +MainWindow::~MainWindow() +{ +} + +void MainWindow::openDialog() +{ + QFileDialog::getOpenFileName(this); +} + +void MainWindow::addSoftKeys() +{ + ok = new QAction(tr("Ok"), this); + ok->setSoftKeyRole(QAction::OkSoftKey); + connect(ok, SIGNAL(triggered()), this, SLOT(okPressed())); + + cancel = new QAction(tr("Cancel"), this); + cancel->setSoftKeyRole(QAction::OkSoftKey); + connect(cancel, SIGNAL(triggered()), this, SLOT(cancelPressed())); + + QList<QAction*> softkeys; + softkeys.append(ok); + softkeys.append(cancel); + setSoftKeys(softkeys); + +} + +void MainWindow::clearSoftKeys() +{ + setSoftKey(0); +} + +void MainWindow::okPressed() +{ +} + +void MainWindow::cancelPressed() +{ +} diff --git a/examples/widgets/softkeys/softkeys.h b/examples/widgets/softkeys/softkeys.h new file mode 100644 index 0000000..2bc74ba --- /dev/null +++ b/examples/widgets/softkeys/softkeys.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SOFTKEYS_H +#define SOFTKEYS_H + +#include <QtGui> + +class MainWindow : public QMainWindow +{ + Q_OBJECT +public: + +private slots: + void openDialog(); + void addSoftKeys(); + void clearSoftKeys(); + void okPressed(); + void cancelPressed(); +public: + MainWindow(QWidget *parent = 0); + ~MainWindow(); +private: + QMenu* fileMenu; + QAction* openDialogAct; + QAction* addSoftKeysAct; + QAction* clearSoftKeysAct; + QAction* ok; + QAction* cancel; +}; + +//! [0] +class SoftKey : public QWidget +{ + Q_OBJECT +public: + SoftKey(QWidget *parent = 0); +}; +//! [0] + +#endif diff --git a/examples/widgets/softkeys/softkeys.pro b/examples/widgets/softkeys/softkeys.pro new file mode 100644 index 0000000..4cb8672 --- /dev/null +++ b/examples/widgets/softkeys/softkeys.pro @@ -0,0 +1,4 @@ +HEADERS = softkeys.h +SOURCES += \ + main.cpp \ + softkeys.cpp
\ No newline at end of file diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 159a997..af84ea6 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -61,6 +61,7 @@ #ifndef QT_NO_ACCESSIBILITY #include <qaccessible.h> #endif +#include <qactiontokeyeventmapper_p.h> QT_BEGIN_NAMESPACE @@ -2003,16 +2004,18 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) if (QApplication::keypadNavigationEnabled()) { if (!hasEditFocus()) { setEditFocus(true); + QActionToKeyEventMapper::addSoftKey(QAction::BackSoftKey, Qt::Key_Back, this); return; } } break; case Qt::Key_Back: - case Qt::Key_Context2: // TODO: aportale, remove KEYPAD_NAVIGATION_HACK when softkey support is there - if (QApplication::keypadNavigationEnabled() && hasEditFocus()) + if (QApplication::keypadNavigationEnabled() && hasEditFocus()) { + QActionToKeyEventMapper::removeSoftkey(this); setEditFocus(false); - else + } else { event->ignore(); + } return; default: if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp index abb17d7..8263cbc 100644 --- a/src/gui/kernel/qaction.cpp +++ b/src/gui/kernel/qaction.cpp @@ -1348,6 +1348,32 @@ QAction::MenuRole QAction::menuRole() const } /*! + \property QAction::softKeyRole + \brief the action's softkey role + \since 4.6 + + This indicates what softkey action this action is. Usually used on mobile + platforms to map QActions to hardware keys. + + The softkey role can be changed any time. +*/ +void QAction::setSoftKeyRole(SoftKeyRole softKeyRole) +{ + Q_D(QAction); + if (d->softKeyRole == softKeyRole) + return; + + d->softKeyRole = softKeyRole; + d->sendDataChanged(); +} + +QAction::SoftKeyRole QAction::softKeyRole() const +{ + Q_D(const QAction); + return d->softKeyRole; +} + +/*! \property QAction::iconVisibleInMenu \brief Whether or not an action should show an icon in a menu \since 4.4 diff --git a/src/gui/kernel/qaction.h b/src/gui/kernel/qaction.h index d7bf8c3..8791a5c 100644 --- a/src/gui/kernel/qaction.h +++ b/src/gui/kernel/qaction.h @@ -67,6 +67,7 @@ class Q_GUI_EXPORT QAction : public QObject Q_DECLARE_PRIVATE(QAction) Q_ENUMS(MenuRole) + Q_ENUMS(SoftKeyRole) Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable) Q_PROPERTY(bool checked READ isChecked WRITE setChecked DESIGNABLE isCheckable NOTIFY toggled) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) @@ -84,11 +85,17 @@ class Q_GUI_EXPORT QAction : public QObject #endif Q_PROPERTY(bool visible READ isVisible WRITE setVisible) Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole) + Q_PROPERTY(SoftKeyRole softKeyRole READ softKeyRole WRITE setSoftKeyRole) Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu) public: enum MenuRole { NoRole, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole, AboutRole, PreferencesRole, QuitRole }; + enum SoftKeyRole { OptionsSoftKey, SelectSoftKey, BackSoftKey, NextSoftKey, PreviousSoftKey, + OkSoftKey, CancelSoftKey, EditSoftKey, ViewSoftKey, BackSpaceSoftKey, + EndEditSoftKey, RevertEditSoftKey, DeselectSoftKey, FinishSoftKey, + MenuSoftKey, ContextMenuSoftKey, Key1SoftKey, Key2SoftKey, + Key3SoftKey, Key4SoftKey, CustomSoftKey }; explicit QAction(QObject* parent); QAction(const QString &text, QObject* parent); QAction(const QIcon &icon, const QString &text, QObject* parent); @@ -168,6 +175,9 @@ public: void setMenuRole(MenuRole menuRole); MenuRole menuRole() const; + void setSoftKeyRole(SoftKeyRole softKeyRole); + SoftKeyRole softKeyRole() const; + void setIconVisibleInMenu(bool visible); bool isIconVisibleInMenu() const; diff --git a/src/gui/kernel/qaction_p.h b/src/gui/kernel/qaction_p.h index 0617ef5..6051d9a 100644 --- a/src/gui/kernel/qaction_p.h +++ b/src/gui/kernel/qaction_p.h @@ -102,6 +102,7 @@ public: uint separator : 1; uint fontSet : 1; QAction::MenuRole menuRole; + QAction::SoftKeyRole softKeyRole; int iconVisibleInMenu : 3; // Only has values -1, 0, and 1 QList<QWidget *> widgets; #ifndef QT_NO_GRAPHICSVIEW diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 2f7bdcf..0ae4c00 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1059,13 +1059,19 @@ void QApplication::symbianHandleCommand(int command) { switch (command) { case EEikCmdExit: - case EAknSoftkeyBack: case EAknSoftkeyExit: - qApp->exit(); + exit(); break; default: - // For now assume all unknown menu items are Qt menu items - QMenuBarPrivate::symbianCommands(command); + if (command >= SOFTKEYSTART && command <= SOFTKEYEND) { + int index= command-SOFTKEYSTART; + QWidget* focused = QApplication::focusWidget(); + const QList<QAction*>& softKeys = focused->softKeys(); + Q_ASSERT(index<softKeys.count()); + softKeys.at(index)->activate(QAction::Trigger); + } + else + QMenuBarPrivate::symbianCommands(command); break; } } diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index b376f20..eaa9491 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -4880,6 +4880,13 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset, d->extra->inRenderWithPainter = false; } +#if !defined(Q_WS_S60) +void QWidgetPrivate::setSoftKeys_sys(const QList<QAction*> &softkeys) +{ + Q_UNUSED(softkeys) +} +#endif // !defined(Q_WS_S60) + bool QWidgetPrivate::isAboutToShow() const { if (data.in_show) @@ -5715,9 +5722,12 @@ bool QWidget::hasFocus() const void QWidget::setFocus(Qt::FocusReason reason) { + Q_D(QWidget); + d->setSoftKeys_sys(softKeys()); + if (!isEnabled()) return; - + QWidget *f = this; while (f->d_func()->extra && f->d_func()->extra->focus_proxy) f = f->d_func()->extra->focus_proxy; @@ -11510,6 +11520,60 @@ void QWidget::clearMask() setMask(QRegion()); } +/*! + Returns the (possibly empty) list of this widget's softkeys. + Returned list cannot be changed. Softkeys should be added + and removed via method called setSoftKeys + + \sa setSoftKey(), setSoftKeys() +*/ +const QList<QAction*>& QWidget::softKeys() const +{ + Q_D(const QWidget); + if( d->softKeys.count() > 0) + return d->softKeys; + if (isWindow() || !parentWidget()) + return d->softKeys; + + return parentWidget()->softKeys(); +} + +/*! + Sets the softkey \a softkey to this widget's list of softkeys, + Setting 0 as softkey will clear all the existing softkeys set + to the widget + A QWidget can have 0 or more softkeys + + \sa softKeys(), setSoftKeys() +*/ +void QWidget::setSoftKey(QAction *softKey) +{ + Q_D(QWidget); + qDeleteAll(d->softKeys); + d->softKeys.clear(); + if (softKey) + d->softKeys.append(softKey); + if (QApplication::focusWidget() == this) + d->setSoftKeys_sys(this->softKeys()); +} + +/*! + Sets the list of softkeys \a softkeys to this widget's list of softkeys, + A QWidget can have 0 or more softkeys + + \sa softKeys(), setSoftKey() +*/ +void QWidget::setSoftKeys(const QList<QAction*> &softKeys) +{ + Q_D(QWidget); + qDeleteAll(d->softKeys); + d->softKeys.clear(); + d->softKeys = softKeys; + + if ((QApplication::focusWidget() == this) || (QApplication::focusWidget()==0)) + d->setSoftKeys_sys(this->softKeys()); +} + /*! \fn const QX11Info &QWidget::x11Info() const Returns information about the configuration of the X display used to display the widget. diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 0dd470d..3f9caee 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -554,6 +554,9 @@ public: void removeAction(QAction *action); QList<QAction*> actions() const; #endif + const QList<QAction*>& softKeys() const; + void setSoftKey(QAction *softKey); + void setSoftKeys(const QList<QAction*> &softKeys); QWidget *parentWidget() const; diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index d5f1b98..084439c 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -84,6 +84,9 @@ class RDrawableWindow; class CCoeControl; class CAknTitlePane; class CAknContextPane; +// The following 2 defines may only be needed for s60. To be seen. +const int SOFTKEYSTART=5000; +const int SOFTKEYEND=5004; #endif QT_BEGIN_NAMESPACE @@ -224,6 +227,7 @@ public: explicit QWidgetPrivate(int version = QObjectPrivateVersion); ~QWidgetPrivate(); + void setSoftKeys_sys(const QList<QAction*> &softkeys); QWExtra *extraData() const; QTLWExtra *topData() const; QTLWExtra *maybeTopData() const; @@ -511,6 +515,7 @@ public: #ifndef QT_NO_ACTION QList<QAction*> actions; #endif + QList<QAction*> softKeys; QLayout *layout; QWidgetItemV2 *widgetItem; #if !defined(QT_NO_IM) diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index e32e272..eb3180f 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -52,6 +52,8 @@ #include <qinputcontext.h> +#include <aknappui.h> + QT_BEGIN_NAMESPACE extern bool qt_nograb(); @@ -59,6 +61,56 @@ extern bool qt_nograb(); QWidget *QWidgetPrivate::mouseGrabber = 0; QWidget *QWidgetPrivate::keyboardGrabber = 0; +static bool isEqual(const QList<QAction*>& a, const QList<QAction*>& b) +{ + if ( a.count() != b.count()) + return false; + int index=0; + while (index<a.count()) { + if (a.at(index)->softKeyRole() != b.at(index)->softKeyRole()) + return false; + if (a.at(index)->text().compare(b.at(index)->text())!=0) + return false; + index++; + } + return true; +} + + +void QWidgetPrivate::setSoftKeys_sys(const QList<QAction*> &softkeys) +{ + Q_Q(QWidget); + if (QApplication::focusWidget() && q!=QApplication::focusWidget()) { + QList<QAction *> old = QApplication::focusWidget()->softKeys(); + if (isEqual(old, softkeys )) + return; + } + CCoeAppUi* appui = CEikonEnv::Static()->AppUi(); + CAknAppUi* aknAppUi = static_cast <CAknAppUi*>(appui); + CEikButtonGroupContainer* nativeContainer = aknAppUi->Cba(); + nativeContainer->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS); + + int placeInScreen=0; + for (int index = 0; index < softkeys.count(); index++) { + const QAction* softKeyAction = softkeys.at(index); + if (softKeyAction->softKeyRole() != QAction::ContextMenuSoftKey) { + + HBufC* text = qt_QString2HBufCNewL(softKeyAction->text()); + CleanupStack::PushL(text); + if (softKeyAction->softKeyRole() == QAction::MenuSoftKey) { + nativeContainer->SetCommandL(placeInScreen, EAknSoftkeyOptions, *text); + } else { + nativeContainer->SetCommandL(placeInScreen, SOFTKEYSTART + index, *text); + } + CleanupStack::PopAndDestroy(); + placeInScreen++; + } + if (placeInScreen==1) + placeInScreen=2; + } + nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation +} + void QWidgetPrivate::setWSGeometry(bool dontShow) { @@ -1006,5 +1058,4 @@ void QWidget::activateWindow() rw->SetOrdinalPosition(0); } } - QT_END_NAMESPACE diff --git a/src/gui/widgets/qactiontokeyeventmapper.cpp b/src/gui/widgets/qactiontokeyeventmapper.cpp new file mode 100644 index 0000000..5cce415 --- /dev/null +++ b/src/gui/widgets/qactiontokeyeventmapper.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qapplication.h" +#include "qevent.h" +#include "QActionToKeyEventMapper_p.h" + +QT_BEGIN_NAMESPACE + +QActionToKeyEventMapper::QActionToKeyEventMapper(QAction *softKeyAction, Qt::Key key, QObject *parent) + : QObject(parent) + , m_softKeyAction(softKeyAction) + , m_key(key) +{ + +} + +QString QActionToKeyEventMapper::roleText(QAction::SoftKeyRole role) +{ + switch (role) { + case QAction::OptionsSoftKey: + return QAction::tr("Options"); + case QAction::SelectSoftKey: + return QAction::tr("Select"); + case QAction::BackSoftKey: + return QAction::tr("Back"); + case QAction::NextSoftKey: + return QAction::tr("Next"); + case QAction::PreviousSoftKey: + return QAction::tr("Previous"); + case QAction::OkSoftKey: + return QAction::tr("Ok"); + case QAction::CancelSoftKey: + return QAction::tr("Cancel"); + case QAction::EditSoftKey: + return QAction::tr("Edit"); + case QAction::ViewSoftKey: + return QAction::tr("View"); + default: + return QString(); + }; +} +void QActionToKeyEventMapper::addSoftKey(QAction::SoftKeyRole standardRole, Qt::Key key, QWidget *actionWidget) +{ + QAction *action = new QAction(actionWidget); + action->setSoftKeyRole(standardRole); + action->setText(roleText(standardRole)); + QActionToKeyEventMapper *softKey = new QActionToKeyEventMapper(action, key, actionWidget); + connect(action, SIGNAL(triggered()), softKey, SLOT(sendKeyEvent())); + connect(action, SIGNAL(destroyed()), softKey, SLOT(deleteLater())); + actionWidget->setSoftKey(action); +} + +void QActionToKeyEventMapper::removeSoftkey(QWidget *focussedWidget) +{ + focussedWidget->setSoftKey(0); +} + +void QActionToKeyEventMapper::sendKeyEvent() +{ + QApplication::postEvent(parent(), new QKeyEvent(QEvent::KeyPress, m_key, Qt::NoModifier)); +} + +QT_END_NAMESPACE + diff --git a/src/gui/widgets/qactiontokeyeventmapper_p.h b/src/gui/widgets/qactiontokeyeventmapper_p.h new file mode 100644 index 0000000..da336e8 --- /dev/null +++ b/src/gui/widgets/qactiontokeyeventmapper_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QACTIONTOKEYEVENTMAPPER_P_H +#define QACTIONTOKEYEVENTMAPPER_P_H + +#include <QtCore/qobject.h> +#include "QtGui/qaction.h" +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QActionToKeyEventMapper : public QObject +{ + Q_OBJECT +public: + QActionToKeyEventMapper(QAction *softKeyAction, Qt::Key key, QObject *parent); + static QString roleText(QAction::SoftKeyRole role); + static void addSoftKey(QAction::SoftKeyRole standardRole, Qt::Key key, QWidget *actionWidget); + static void removeSoftkey(QWidget *focussedWidget); +private: + QAction *m_softKeyAction; + Qt::Key m_key; +private Q_SLOTS: + void sendKeyEvent(); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif //QACTIONTOKEYEVENTMAPPER_H diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index 16e2f39..2da5cd0 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -63,7 +63,7 @@ #include <private/qabstractitemmodel_p.h> #include <private/qabstractscrollarea_p.h> #include <qdebug.h> - +#include <qactiontokeyeventmapper_p.h> #ifdef Q_WS_X11 #include <private/qt_x11_p.h> #endif @@ -628,6 +628,9 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e) case Qt::Key_Select: #endif if (view->currentIndex().isValid() && (view->currentIndex().flags() & Qt::ItemIsEnabled) ) { +#ifdef QT_KEYPAD_NAVIGATION + QActionToKeyEventMapper::removeSoftkey(this); +#endif combo->hidePopup(); emit itemSelected(view->currentIndex()); } @@ -640,7 +643,7 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e) case Qt::Key_Escape: #ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Back: - case Qt::Key_Context2: // TODO: aportale, KEYPAD_NAVIGATION_HACK when softkey support is there + QActionToKeyEventMapper::removeSoftkey(this); #endif combo->hidePopup(); return true; @@ -2435,6 +2438,7 @@ void QComboBox::showPopup() #ifdef QT_KEYPAD_NAVIGATION if (QApplication::keypadNavigationEnabled()) view()->setEditFocus(true); + QActionToKeyEventMapper::addSoftKey(QAction::CancelSoftKey, Qt::Key_Back, view()); #endif } diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index 558ba42..2f3b412 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -481,6 +481,11 @@ void QMainWindow::setMenuBar(QMenuBar *menuBar) oldMenuBar->deleteLater(); } d->layout->setMenuBar(menuBar); + if (menuBar) { + QAction* menu = new QAction(QString::fromLatin1("Menu"), this); + menu->setSoftKeyRole(QAction::MenuSoftKey); + setSoftKey(menu); + } } /*! diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 6be0f19..3486574 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -60,6 +60,7 @@ #ifndef QT_NO_WHATSTHIS # include <qwhatsthis.h> #endif +#include <qactiontokeyeventmapper_p.h> #include "qmenu_p.h" #include "qmenubar_p.h" @@ -578,8 +579,14 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason //when the action has no QWidget, the QMenu itself should // get the focus // Since the menu is a pop-up, it uses the popup reason. - if (!q->hasFocus()) + if (!q->hasFocus()) { q->setFocus(Qt::PopupFocusReason); +#ifdef QT_KEYPAD_NAVIGATION + // TODO: aportale, remove KEYPAD_NAVIGATION_HACK when softkey stack + // handles focus related and user related actions separately... + QActionToKeyEventMapper::addSoftKey(QAction::CancelSoftKey, Qt::Key_Back, q); +#endif + } } } } else { //action is a separator @@ -1937,6 +1944,9 @@ void QMenu::popup(const QPoint &p, QAction *atAction) #ifndef QT_NO_ACCESSIBILITY QAccessible::updateAccessibility(this, 0, QAccessible::PopupMenuStart); #endif +#ifdef QT_KEYPAD_NAVIGATION + QActionToKeyEventMapper::addSoftKey(QAction::CancelSoftKey, Qt::Key_Back, this); +#endif } /*! @@ -2587,7 +2597,7 @@ void QMenu::keyPressEvent(QKeyEvent *e) case Qt::Key_Escape: #ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Back: - case Qt::Key_Context2: // TODO: aportale, remove KEYPAD_NAVIGATION_HACK when softkey support is there + QActionToKeyEventMapper::removeSoftkey(this); #endif key_consumed = true; if (d->tornoff) { diff --git a/src/gui/widgets/qmenu_symbian.cpp b/src/gui/widgets/qmenu_symbian.cpp index 48c2cf6..49bcc21 100644 --- a/src/gui/widgets/qmenu_symbian.cpp +++ b/src/gui/widgets/qmenu_symbian.cpp @@ -40,8 +40,6 @@ #include "qmenu.h" #include "qapplication.h" -#include "qmainwindow.h" -#include "qtoolbar.h" #include "qevent.h" #include "qstyle.h" #include "qdebug.h" @@ -56,12 +54,10 @@ #include <eikbtgpc.h> #include <QtCore/qlibrary.h> #include <avkon.rsg> - #ifndef QT_NO_MENUBAR QT_BEGIN_NAMESPACE -// ### FIX/Document this, we need some safe range of menu id's for Qt that don't clash with AIW ones typedef QMultiHash<QWidget *, QMenuBarPrivate *> MenuBarHash; Q_GLOBAL_STATIC(MenuBarHash, menubars) @@ -78,6 +74,10 @@ struct SymbianMenuItem static QList<SymbianMenuItem*> symbianMenus; static QList<QMenuBar*> nativeMenuBars; static uint qt_symbian_menu_static_cmd_id = QT_FIRST_MENU_ITEM; +static QWidget* widgetWithContextMenu=0; +static QList<QAction*> contextMenuActionList; +static QAction contextAction(0); +static int contexMenuCommand=0; bool menuExists() { @@ -88,6 +88,16 @@ bool menuExists() return true; } +static bool hasContextMenu(QWidget* widget) +{ + if (!widget) + return false; + const Qt::ContextMenuPolicy policy = widget->contextMenuPolicy(); + if (policy != Qt::NoContextMenu && policy != Qt::PreventContextMenu ) { + return true; + } + return false; +} // ### FIX THIS, copy/paste of original (faulty) stripped text implementation. // Implementation should be removed from QAction implementation to some generic place static QString qt_strippedText_copy_from_qaction(QString s) @@ -204,24 +214,18 @@ void deleteAll(QList<SymbianMenuItem*> *items) } } -static void setSoftkeys() -{ - CEikButtonGroupContainer* cba = CEikonEnv::Static()->AppUiFactory()->Cba(); - if (cba){ - if (menuExists()) - cba->SetCommandSetL(R_AVKON_SOFTKEYS_OPTIONS_EXIT); - else - cba->SetCommandSetL(R_AVKON_SOFTKEYS_EXIT); - } -} - static void rebuildMenu() { + widgetWithContextMenu = 0; QMenuBarPrivate *mb = 0; - setSoftkeys(); QWidget *w = qApp->activeWindow(); - if (w) - { + QWidget* focusWidget = QApplication::focusWidget(); + if (focusWidget) { + if (hasContextMenu(focusWidget)) + widgetWithContextMenu = focusWidget; + } + + if (w) { mb = menubars()->value(w); qt_symbian_menu_static_cmd_id = QT_FIRST_MENU_ITEM; deleteAll( &symbianMenus ); @@ -229,7 +233,7 @@ static void rebuildMenu() return; mb->symbian_menubar->rebuild(); } - } +} Q_GUI_EXPORT void qt_symbian_show_toplevel( CEikMenuPane* menuPane) { @@ -251,6 +255,11 @@ Q_GUI_EXPORT void qt_symbian_show_submenu( CEikMenuPane* menuPane, int id) void QMenuBarPrivate::symbianCommands(int command) { + if (command == contexMenuCommand) { + QContextMenuEvent* event = new QContextMenuEvent(QContextMenuEvent::Keyboard, QPoint(0,0)); + QCoreApplication::postEvent(widgetWithContextMenu, event); + } + int size = nativeMenuBars.size(); for (int i = 0; i < nativeMenuBars.size(); ++i) { SymbianMenuItem* menu = qt_symbian_find_menu_item(command, symbianMenus); @@ -377,22 +386,36 @@ void QMenuBarPrivate::QSymbianMenuBarPrivate::removeAction(QSymbianMenuAction *a rebuild(); } -void QMenuBarPrivate::QSymbianMenuBarPrivate::rebuild() +void QMenuBarPrivate::QSymbianMenuBarPrivate::insertNativeMenuItems(const QList<QAction*> &actions) { - setSoftkeys(); - qt_symbian_menu_static_cmd_id = QT_FIRST_MENU_ITEM; - deleteAll( &symbianMenus ); - if (!d) - return; - for (int i = 0; i < d->actions.size(); ++i) { + for (int i = 0; i <actions.size(); ++i) { QSymbianMenuAction *symbianActionTopLevel = new QSymbianMenuAction; - symbianActionTopLevel->action = d->actions.at(i); + symbianActionTopLevel->action = actions.at(i); symbianActionTopLevel->parent = 0; symbianActionTopLevel->command = qt_symbian_menu_static_cmd_id++; qt_symbian_insert_action(symbianActionTopLevel, &symbianMenus); - } + } } + + +void QMenuBarPrivate::QSymbianMenuBarPrivate::rebuild() +{ + contexMenuCommand = 0; + qt_symbian_menu_static_cmd_id = QT_FIRST_MENU_ITEM; + deleteAll( &symbianMenus ); + if (d) + insertNativeMenuItems(d->actions); + + contextMenuActionList.clear(); + if (widgetWithContextMenu) { + contexMenuCommand = qt_symbian_menu_static_cmd_id; + contextAction.setText(QString("Actions")); + contextMenuActionList.append(&contextAction); + insertNativeMenuItems(contextMenuActionList); + } + +} QT_END_NAMESPACE #endif //QT_NO_MENUBAR diff --git a/src/gui/widgets/qmenubar_p.h b/src/gui/widgets/qmenubar_p.h index 7993acd..9e7d511 100644 --- a/src/gui/widgets/qmenubar_p.h +++ b/src/gui/widgets/qmenubar_p.h @@ -257,6 +257,7 @@ public: } return 0; } + void insertNativeMenuItems(const QList<QAction*> &actions); } *symbian_menubar; static void symbianCommands(int command); diff --git a/src/gui/widgets/widgets.pri b/src/gui/widgets/widgets.pri index fc57944..9e226e2 100644 --- a/src/gui/widgets/widgets.pri +++ b/src/gui/widgets/widgets.pri @@ -78,8 +78,8 @@ HEADERS += \ widgets/qtoolbararealayout_p.h \ widgets/qplaintextedit.h \ widgets/qplaintextedit_p.h \ - widgets/qprintpreviewwidget.h - + widgets/qprintpreviewwidget.h \ + widgets/qactiontokeyeventmapper_p.h SOURCES += \ widgets/qabstractbutton.cpp \ widgets/qabstractslider.cpp \ @@ -138,8 +138,8 @@ SOURCES += \ widgets/qwidgetanimator.cpp \ widgets/qtoolbararealayout.cpp \ widgets/qplaintextedit.cpp \ - widgets/qprintpreviewwidget.cpp - + widgets/qprintpreviewwidget.cpp \ + widgets/qactiontokeyeventmapper.cpp !embedded:mac { HEADERS += widgets/qmacnativewidget_mac.h \ diff --git a/src/s60main/qts60mainappui.cpp b/src/s60main/qts60mainappui.cpp index 47312af..7d38f33 100644 --- a/src/s60main/qts60mainappui.cpp +++ b/src/s60main/qts60mainappui.cpp @@ -68,6 +68,9 @@ void CQtS60MainAppUi::ConstructL() // even these flags are defined BaseConstructL(CAknAppUi::EAknEnableSkin); + CEikButtonGroupContainer* nativeContainer = Cba(); + nativeContainer->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS); + // Create async callback to call Qt main, // this is required to give S60 app FW to finish starting correctly TCallBack callBack( OpenCMainStaticCallBack, this ); |