From 7bc18035816a2eac15dfac4d987eb9bf43f90ef6 Mon Sep 17 00:00:00 2001 From: Janne Koskinen Date: Mon, 28 Dec 2009 13:47:46 +0200 Subject: Daylight savings time for Symbian take 2 Second try to make this work for all S60 platforms --- src/corelib/corelib.pro | 2 ++ src/corelib/tools/qdatetime.cpp | 60 +++++++++++++++++++++------------- tests/auto/qdatetime/tst_qdatetime.cpp | 7 ++++ 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index 9a15bf1..7f33791 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -35,4 +35,6 @@ symbian: { # Workaroud for problems with paging this dll MMP_RULES -= PAGED MMP_RULES *= UNPAGED + # Timezone server + LIBS += -ltzclient } diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index db6435e..240f0cf 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -75,6 +75,7 @@ #if defined(Q_OS_SYMBIAN) #include +#include #endif QT_BEGIN_NAMESPACE @@ -3721,23 +3722,32 @@ static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time) #elif defined(Q_OS_SYMBIAN) // months and days are zero index based _LIT(KUnixEpoch, "19700000:000000.000000"); - TTimeIntervalSeconds utcOffset = User::UTCOffset(); TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC); TTime epochTTime; TInt err = epochTTime.Set(KUnixEpoch); tm res; if(err == KErrNone) { TTime utcTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC; - utcTTime = utcTTime + utcOffset; - TDateTime utcDateTime = utcTTime.DateTime(); - res.tm_sec = utcDateTime.Second(); - res.tm_min = utcDateTime.Minute(); - res.tm_hour = utcDateTime.Hour(); - res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct - res.tm_mon = utcDateTime.Month(); - res.tm_year = utcDateTime.Year() - 1900; - res.tm_isdst = 0; - brokenDown = &res; + TRAP(err, + RTz tz; + User::LeaveIfError(tz.Connect()); + CleanupClosePushL(tz); + res.tm_isdst = tz.IsDaylightSavingOnL(*tz.GetTimeZoneIdL(),utcTTime); + User::LeaveIfError(tz.ConvertToLocalTime(utcTTime)); + CleanupStack::PopAndDestroy(&tz)); + if (KErrNone == err) { + TDateTime localDateTime = utcTTime.DateTime(); + res.tm_sec = localDateTime.Second(); + res.tm_min = localDateTime.Minute(); + res.tm_hour = localDateTime.Hour(); + res.tm_mday = localDateTime.Day() + 1; // non-zero based index for tm struct + res.tm_mon = localDateTime.Month(); + res.tm_year = localDateTime.Year() - 1900; + // Symbian's timezone server doesn't know how to handle DST before year 1997 + if (res.tm_year < 97) + res.tm_isdst = -1; + brokenDown = &res; + } } #elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) // use the reentrant version of localtime() where available @@ -3812,23 +3822,27 @@ static void localToUtc(QDate &date, QTime &time, int isdst) #elif defined(Q_OS_SYMBIAN) // months and days are zero index based _LIT(KUnixEpoch, "19700000:000000.000000"); - TTimeIntervalSeconds utcOffset = TTimeIntervalSeconds(0 - User::UTCOffset().Int()); TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC); TTime epochTTime; TInt err = epochTTime.Set(KUnixEpoch); tm res; if(err == KErrNone) { - TTime utcTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC; - utcTTime = utcTTime + utcOffset; - TDateTime utcDateTime = utcTTime.DateTime(); - res.tm_sec = utcDateTime.Second(); - res.tm_min = utcDateTime.Minute(); - res.tm_hour = utcDateTime.Hour(); - res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct - res.tm_mon = utcDateTime.Month(); - res.tm_year = utcDateTime.Year() - 1900; - res.tm_isdst = (int)isdst; - brokenDown = &res; + TTime localTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC; + RTz tz; + if (KErrNone == tz.Connect()) { + if (KErrNone == tz.ConvertToUniversalTime(localTTime)) { + TDateTime utcDateTime = localTTime.DateTime(); + res.tm_sec = utcDateTime.Second(); + res.tm_min = utcDateTime.Minute(); + res.tm_hour = utcDateTime.Hour(); + res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct + res.tm_mon = utcDateTime.Month(); + res.tm_year = utcDateTime.Year() - 1900; + res.tm_isdst = (int)isdst; + brokenDown = &res; + } + tz.Close(); + } } #elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) // use the reentrant version of gmtime() where available diff --git a/tests/auto/qdatetime/tst_qdatetime.cpp b/tests/auto/qdatetime/tst_qdatetime.cpp index 1140402..32fa398 100644 --- a/tests/auto/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/qdatetime/tst_qdatetime.cpp @@ -147,9 +147,16 @@ Q_DECLARE_METATYPE(QTime) tst_QDateTime::tst_QDateTime() { +#ifdef Q_OS_SYMBIAN + // Symbian's timezone server cannot handle DST correctly for dates before year 1997 + uint x1 = QDateTime(QDate(2000, 1, 1), QTime()).toTime_t(); + uint x2 = QDateTime(QDate(2000, 6, 1), QTime()).toTime_t(); + europeanTimeZone = (x1 == 946681200 && x2 == 959810400); +#else uint x1 = QDateTime(QDate(1990, 1, 1), QTime()).toTime_t(); uint x2 = QDateTime(QDate(1990, 6, 1), QTime()).toTime_t(); europeanTimeZone = (x1 == 631148400 && x2 == 644191200); +#endif } tst_QDateTime::~tst_QDateTime() -- cgit v0.12 From 2a8d20453926082062246fc4cc788f88ea3c59ae Mon Sep 17 00:00:00 2001 From: Janne Anttila Date: Wed, 3 Feb 2010 11:37:24 +0200 Subject: S60 softkey refactoring (support for merging, priorities and menus) Implemented features: Softkey Merging: Widget can set only one softkey and set flag that rest of the softkeys shall be taken from parent. Priority Handling: If multiple sokftkeys with same role are set, the highest priority action gets displayed. Custom Softkey Menu: By setting QMenu to QAction and assigning a softkey role for that action, the native menubar will be displayed when sofkey is clicked. Softkey Image: Initial code for implementing sofkey image support, the final implementation is still pending legal acceptance to use eiksoftkeyimage.h header file which is under EPL license. Task-number: QTBUG-7315 Review-By: Sami Merila Review-By: Jason Barron --- src/corelib/global/qnamespace.h | 3 + src/corelib/global/qnamespace.qdoc | 15 +- src/gui/kernel/kernel.pri | 53 +++-- src/gui/kernel/qsoftkeymanager.cpp | 209 ++++++----------- src/gui/kernel/qsoftkeymanager_common_p.h | 82 +++++++ src/gui/kernel/qsoftkeymanager_p.h | 22 +- src/gui/kernel/qsoftkeymanager_s60.cpp | 366 ++++++++++++++++++++++++++++++ src/gui/kernel/qsoftkeymanager_s60_p.h | 109 +++++++++ src/gui/kernel/qt_s60_p.h | 6 + src/gui/widgets/qmainwindow.cpp | 2 - src/gui/widgets/qmenu_p.h | 7 +- src/gui/widgets/qmenu_symbian.cpp | 34 ++- src/gui/widgets/qmenubar.cpp | 2 +- 13 files changed, 727 insertions(+), 183 deletions(-) create mode 100644 src/gui/kernel/qsoftkeymanager_common_p.h create mode 100644 src/gui/kernel/qsoftkeymanager_s60.cpp create mode 100644 src/gui/kernel/qsoftkeymanager_s60_p.h diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 38e1886..177bee4 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -497,6 +497,9 @@ public: WA_WState_AcceptedTouchBeginEvent = 122, WA_TouchPadAcceptSingleTouchEvents = 123, + WA_MergeSoftkeys = 124, + WA_MergeSoftkeysRecursively = 125, + // Add new attributes before this line WA_AttributeCount }; diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 871dd5c..6627c76 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -524,11 +524,11 @@ receiver are in the same thread. Same as QueuedConnection, if the emitter and receiver are in different threads. - \value DirectConnection + \value DirectConnection The slot is invoked immediately, when the signal is emitted. - \value QueuedConnection + \value QueuedConnection The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread. @@ -1243,6 +1243,17 @@ \value WA_TouchPadAcceptSingleTouchEvents Allows touchpad single touch events to be sent to the widget. + \value WA_MergeSoftkeys Allows widget to merge softkeys with parent widget, + i.e. widget can set only one softkeys and request softkey implementation + to take rest of the softkeys from the parent. Note parents are traversed until + WA_MergeSoftkeys is not set. See also Qt::WA_MergeSoftkeysRecursively + This attribute currently has effect only on Symbian platforms + + \value WA_MergeSoftkeysRecursively Allows widget to merge softkeys recursively + with all parents. If this attribute is set, the widget parents are traversed until + window boundary (widget without parent or dialog) is found. + This attribute currently has effect only on Symbian platforms + \omitvalue WA_SetLayoutDirection \omitvalue WA_InputMethodTransparent \omitvalue WA_WState_CompressKeys diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index f2bd288..0993b86 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -7,7 +7,7 @@ PRECOMPILED_HEADER = kernel/qt_gui_pch.h KERNEL_P= kernel HEADERS += \ kernel/qaction.h \ - kernel/qaction_p.h \ + kernel/qaction_p.h \ kernel/qactiongroup.h \ kernel/qapplication.h \ kernel/qapplication_p.h \ @@ -37,8 +37,8 @@ HEADERS += \ kernel/qstackedlayout.h \ kernel/qtooltip.h \ kernel/qwhatsthis.h \ - kernel/qwidget.h \ - kernel/qwidget_p.h \ + kernel/qwidget.h \ + kernel/qwidget_p.h \ kernel/qwidgetaction.h \ kernel/qwidgetaction_p.h \ kernel/qwindowdefs.h \ @@ -49,6 +49,7 @@ HEADERS += \ kernel/qgesturerecognizer.h \ kernel/qgesturemanager_p.h \ kernel/qsoftkeymanager_p.h \ + kernel/qsoftkeymanager_common_p.h \ kernel/qguiplatformplugin_p.h SOURCES += \ @@ -84,14 +85,14 @@ SOURCES += \ kernel/qgesturerecognizer.cpp \ kernel/qgesturemanager.cpp \ kernel/qsoftkeymanager.cpp \ - kernel/qdesktopwidget.cpp \ + kernel/qdesktopwidget.cpp \ kernel/qguiplatformplugin.cpp win32 { DEFINES += QT_NO_DIRECTDRAW - HEADERS += \ - kernel/qwinnativepangesturerecognizer_win_p.h + HEADERS += \ + kernel/qwinnativepangesturerecognizer_win_p.h SOURCES += \ kernel/qapplication_win.cpp \ @@ -103,30 +104,34 @@ win32 { kernel/qsound_win.cpp \ kernel/qwidget_win.cpp \ kernel/qole_win.cpp \ - kernel/qkeymapper_win.cpp \ - kernel/qwinnativepangesturerecognizer_win.cpp + kernel/qkeymapper_win.cpp \ + kernel/qwinnativepangesturerecognizer_win.cpp - !contains(DEFINES, QT_NO_DIRECTDRAW):LIBS += ddraw.lib + !contains(DEFINES, QT_NO_DIRECTDRAW):LIBS += ddraw.lib } symbian { - SOURCES += \ - kernel/qapplication_s60.cpp \ - kernel/qeventdispatcher_s60.cpp \ - kernel/qwidget_s60.cpp \ - kernel/qcursor_s60.cpp \ - kernel/qdesktopwidget_s60.cpp \ - kernel/qkeymapper_s60.cpp\ - kernel/qclipboard_s60.cpp\ - kernel/qdnd_s60.cpp \ - kernel/qsound_s60.cpp + SOURCES += \ + kernel/qapplication_s60.cpp \ + kernel/qeventdispatcher_s60.cpp \ + kernel/qwidget_s60.cpp \ + kernel/qcursor_s60.cpp \ + kernel/qdesktopwidget_s60.cpp \ + kernel/qkeymapper_s60.cpp\ + kernel/qclipboard_s60.cpp\ + kernel/qdnd_s60.cpp \ + kernel/qsound_s60.cpp \ + kernel/qsoftkeymanager_s60.cpp - HEADERS += \ - kernel/qt_s60_p.h \ - kernel/qeventdispatcher_s60_p.h - LIBS += -lbafl -lestor + HEADERS += \ + kernel/qt_s60_p.h \ + kernel/qeventdispatcher_s60_p.h \ + kernel/qsoftkeymanager_s60_p.h + + LIBS += -lbafl -lestor - INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE + INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE + INCLUDEPATH += ../3rdparty/s60 } diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp index 354f90b..6d108b0 100644 --- a/src/gui/kernel/qsoftkeymanager.cpp +++ b/src/gui/kernel/qsoftkeymanager.cpp @@ -41,34 +41,18 @@ #include "qapplication.h" #include "qevent.h" -#ifdef Q_WS_S60 -#include "qstyle.h" -#include "private/qt_s60_p.h" -#endif +#include "qbitmap.h" #include "private/qsoftkeymanager_p.h" #include "private/qobject_p.h" - -#ifndef QT_NO_SOFTKEYMANAGER -QT_BEGIN_NAMESPACE +#include "private/qsoftkeymanager_common_p.h" #ifdef Q_WS_S60 -static const int s60CommandStart = 6000; +#include "private/qsoftkeymanager_s60_p.h" #endif -class QSoftKeyManagerPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QSoftKeyManager) - -public: - static void updateSoftKeys_sys(const QList &softKeys); - -private: - QHash keyedActions; - static QSoftKeyManager *self; - static QWidget *softKeySource; -}; +#ifndef QT_NO_SOFTKEYMANAGER +QT_BEGIN_NAMESPACE -QWidget *QSoftKeyManagerPrivate::softKeySource = 0; QSoftKeyManager *QSoftKeyManagerPrivate::self = 0; const char *QSoftKeyManager::standardSoftKeyText(StandardSoftKey standardKey) @@ -105,7 +89,12 @@ QSoftKeyManager *QSoftKeyManager::instance() return QSoftKeyManagerPrivate::self; } -QSoftKeyManager::QSoftKeyManager() : QObject(*(new QSoftKeyManagerPrivate), 0) +QSoftKeyManager::QSoftKeyManager() : +#ifdef Q_WS_S60 + QObject(*(new QSoftKeyManagerPrivateS60), 0) +#else + QObject(*(new QSoftKeyManagerPrivate), 0) +#endif { } @@ -115,10 +104,11 @@ QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *act QAction *action = new QAction(QSoftKeyManager::tr(text), actionWidget); QAction::SoftKeyRole softKeyRole = QAction::NoSoftKey; switch (standardKey) { + case MenuSoftKey: // FALL-THROUGH + action->setProperty(MENU_ACTION_PROPERTY, QVariant(true)); // TODO: can be refactored away to use _q_action_menubar case OkSoftKey: case SelectSoftKey: case DoneSoftKey: - case MenuSoftKey: softKeyRole = QAction::PositiveSoftKey; break; case CancelSoftKey: @@ -147,7 +137,7 @@ QAction *QSoftKeyManager::createKeyedAction(StandardSoftKey standardKey, Qt::Key #endif //QT_NO_ACTION } -void QSoftKeyManager::cleanupHash(QObject* obj) +void QSoftKeyManager::cleanupHash(QObject *obj) { Q_D(QSoftKeyManager); QAction *action = qobject_cast(obj); @@ -175,137 +165,78 @@ void QSoftKeyManager::updateSoftKeys() QApplication::postEvent(QSoftKeyManager::instance(), event); } -bool QSoftKeyManager::event(QEvent *e) +bool QSoftKeyManager::appendSoftkeys(const QWidget &source, int level) { -#ifndef QT_NO_ACTION - if (e->type() == QEvent::UpdateSoftKeys) { - QList softKeys; - QWidget *source = QApplication::focusWidget(); - do { - if (source) { - QList actions = source->actions(); - for (int i = 0; i < actions.count(); ++i) { - if (actions.at(i)->softKeyRole() != QAction::NoSoftKey) - softKeys.append(actions.at(i)); - } - - QWidget *parent = source->parentWidget(); - if (parent && softKeys.isEmpty() && !source->isWindow()) - source = parent; - else - break; - } else { - source = QApplication::activeWindow(); - } - } while (source); - - QSoftKeyManagerPrivate::softKeySource = source; - QSoftKeyManagerPrivate::updateSoftKeys_sys(softKeys); - return true; + Q_D(QSoftKeyManager); + bool ret = false; + QList actions = source.actions(); + for (int i = 0; i < actions.count(); ++i) { + if (actions.at(i)->softKeyRole() != QAction::NoSoftKey) { + d->requestedSoftKeyActions.insert(level, actions.at(i)); + ret = true; + } } -#endif //QT_NO_ACTION - return false; + return ret; } -#ifdef Q_WS_S60 -void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList &softkeys) +QWidget *QSoftKeyManager::softkeySource(QWidget *previousSource, bool& recursiveMerging) { - // lets not update softkeys if s60 native dialog or menu is shown - if (QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes) - || CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog()) - return; - - CEikButtonGroupContainer* nativeContainer = S60->buttonGroupContainer(); - nativeContainer->DrawableWindow()->SetOrdinalPosition(0); - nativeContainer->DrawableWindow()->SetPointerCapturePriority(1); //keep softkeys available in modal dialog - nativeContainer->DrawableWindow()->SetFaded(EFalse, RWindowTreeNode::EFadeIncludeChildren); - - int position = -1; - bool needsExitButton = true; - QT_TRAP_THROWING( - //Using -1 instead of EAknSoftkeyEmpty to avoid flickering. - nativeContainer->SetCommandL(0, -1, KNullDesC); - nativeContainer->SetCommandL(2, -1, KNullDesC); - ); - - for (int index = 0; index < softkeys.count(); index++) { - const QAction* softKeyAction = softkeys.at(index); - switch (softKeyAction->softKeyRole()) { - // Positive Actions on the LSK - case QAction::PositiveSoftKey: - position = 0; - break; - case QAction::SelectSoftKey: - position = 0; - break; - // Negative Actions on the RSK - case QAction::NegativeSoftKey: - needsExitButton = false; - position = 2; - break; - default: - break; - } - - int command = (softKeyAction->objectName().contains(QLatin1String("_q_menuSoftKeyAction"))) - ? EAknSoftkeyOptions - : s60CommandStart + index; - - // _q_menuSoftKeyAction action is set to "invisible" and all invisible actions are by default - // disabled. However we never want to dim options softkey, even it is set to "invisible" - bool dimmed = (command == EAknSoftkeyOptions) ? false : !softKeyAction->isEnabled(); - - if (position != -1) { - const int underlineShortCut = QApplication::style()->styleHint(QStyle::SH_UnderlineShortcut); - QString iconText = softKeyAction->iconText(); - TPtrC text = qt_QString2TPtrC( underlineShortCut ? softKeyAction->text() : iconText); - QT_TRAP_THROWING( - nativeContainer->SetCommandL(position, command, text); - nativeContainer->DimCommand(command, dimmed); - ); - } + Q_D(QSoftKeyManager); + QWidget *source = NULL; + if (!previousSource) { + // Initial source is primarily focuswidget and secondarily activeWindow + source = QApplication::focusWidget(); + 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; } - - const Qt::WindowType sourceWindowType = QSoftKeyManagerPrivate::softKeySource - ? QSoftKeyManagerPrivate::softKeySource->window()->windowType() - : Qt::Widget; - - if (needsExitButton && sourceWindowType != Qt::Dialog && sourceWindowType != Qt::Popup) - QT_TRAP_THROWING( - nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QSoftKeyManager::tr("Exit")))); - - nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation + return source; } -bool QSoftKeyManager::handleCommand(int command) +bool QSoftKeyManager::handleUpdateSoftKeys() { - if (command >= s60CommandStart && QSoftKeyManagerPrivate::softKeySource) { - int index = command - s60CommandStart; - const QList& softKeys = QSoftKeyManagerPrivate::softKeySource->actions(); - for (int i = 0, j = 0; i < softKeys.count(); ++i) { - QAction *action = softKeys.at(i); - if (action->softKeyRole() != QAction::NoSoftKey) { - if (j == index) { - QWidget *parent = action->parentWidget(); - if (parent && parent->isEnabled()) { - action->activate(QAction::Trigger); - return true; - } - } - j++; - } + Q_D(QSoftKeyManager); + int level = 0; + d->requestedSoftKeyActions.clear(); + bool recursiveMerging = false; + QWidget *source = softkeySource(NULL, recursiveMerging); + do { + if (source) { + bool added = appendSoftkeys(*source, level); + source = softkeySource(source, recursiveMerging); + level = added ? ++level : level; } - } + } while (source); - return false; + d->updateSoftKeys_sys(); + return true; } -#else - -void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList &) +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) +{ + return static_cast(QSoftKeyManager::instance()->d_func())->handleCommand(command); +} #endif QT_END_NAMESPACE diff --git a/src/gui/kernel/qsoftkeymanager_common_p.h b/src/gui/kernel/qsoftkeymanager_common_p.h new file mode 100644 index 0000000..460d0dc --- /dev/null +++ b/src/gui/kernel/qsoftkeymanager_common_p.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QSOFTKEYMANAGER_COMMON_P_H +#define QSOFTKEYMANAGER_COMMON_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_HEADER + +#ifndef QT_NO_SOFTKEYMANAGER + +QT_BEGIN_NAMESPACE + +class QSoftKeyManagerPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QSoftKeyManager) + +public: + virtual void updateSoftKeys_sys() {}; + +protected: + static QSoftKeyManager *self; + QHash keyedActions; + QMultiHash requestedSoftKeyActions; + +}; + +QT_END_NAMESPACE + +#endif //QT_NO_SOFTKEYMANAGER + +QT_END_HEADER + +#endif // QSOFTKEYMANAGER_COMMON_P_H \ No newline at end of file diff --git a/src/gui/kernel/qsoftkeymanager_p.h b/src/gui/kernel/qsoftkeymanager_p.h index c901a29..ce902fe 100644 --- a/src/gui/kernel/qsoftkeymanager_p.h +++ b/src/gui/kernel/qsoftkeymanager_p.h @@ -63,6 +63,8 @@ QT_BEGIN_NAMESPACE class QSoftKeyManagerPrivate; +const char MENU_ACTION_PROPERTY[] = "_q_menuaction"; + class Q_AUTOTEST_EXPORT QSoftKeyManager : public QObject { Q_OBJECT @@ -79,26 +81,30 @@ public: }; static void updateSoftKeys(); - static QAction *createAction(StandardSoftKey standardKey, QWidget *actionWidget); - static QAction *createKeyedAction(StandardSoftKey standardKey, Qt::Key key, QWidget *actionWidget); - #ifdef Q_WS_S60 static bool handleCommand(int); #endif -private: - QSoftKeyManager(); - static QSoftKeyManager *instance(); - static const char *standardSoftKeyText(StandardSoftKey standardKey); + static QAction *createAction(StandardSoftKey standardKey, QWidget *actionWidget); + static QAction *createKeyedAction(StandardSoftKey standardKey, Qt::Key key, QWidget *actionWidget); protected: bool event(QEvent *e); - Q_DISABLE_COPY(QSoftKeyManager) +private: + QSoftKeyManager(); + static QSoftKeyManager *instance(); + static const char *standardSoftKeyText(StandardSoftKey standardKey); + bool appendSoftkeys(const QWidget &source, int level); + QWidget *softkeySource(QWidget *previousSource, bool& recursiveMerging); + bool handleUpdateSoftKeys(); private Q_SLOTS: void cleanupHash(QObject* obj); void sendKeyEvent(); + +private: + Q_DISABLE_COPY(QSoftKeyManager) }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qsoftkeymanager_s60.cpp b/src/gui/kernel/qsoftkeymanager_s60.cpp new file mode 100644 index 0000000..67ed8b0 --- /dev/null +++ b/src/gui/kernel/qsoftkeymanager_s60.cpp @@ -0,0 +1,366 @@ +/**************************************************************************** +** +** 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 "qstyle.h" +#include "qmenubar.h" +#include "private/qt_s60_p.h" +#include "private/qmenu_p.h" +#include "private/qsoftkeymanager_p.h" +#include "private/qsoftkeymanager_s60_p.h" +#include "private/qobject_p.h" +//#include +#include + +#ifndef QT_NO_SOFTKEYMANAGER +QT_BEGIN_NAMESPACE + +const int S60_COMMAND_START = 6000; +const int LSK_POSITION = 0; +const int MSK_POSITION = 3; +const int RSK_POSITION = 2; + +QSoftKeyManagerPrivateS60::QSoftKeyManagerPrivateS60() +{ + cachedCbaIconSize[0] = QSize(0,0); + cachedCbaIconSize[1] = QSize(0,0); + skipNextUpdate = false; +} + +bool QSoftKeyManagerPrivateS60::skipCbaUpdate() +{ + // lets not update softkeys if + // 1. We don't have application panes, i.e. cba + // 2. S60 native dialog or menu is shown + if (QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes) || + CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog() || skipNextUpdate) { + skipNextUpdate = false; + return true; + } + return false; +} + +void QSoftKeyManagerPrivateS60::ensureCbaVisibilityAndResponsiviness(CEikButtonGroupContainer &cba) +{ + RDrawableWindow *cbaWindow = cba.DrawableWindow(); + Q_ASSERT_X(cbaWindow, Q_FUNC_INFO, "Native CBA does not have window!"); + // Make sure CBA is visible, i.e. CBA window is on top + cbaWindow->SetOrdinalPosition(0); + // Qt shares same CBA instance between top-level widgets, + // make sure we are not faded by underlying window. + cbaWindow->SetFaded(EFalse, RWindowTreeNode::EFadeIncludeChildren); + // Modal dialogs capture pointer events, but shared cba instance + // shall stay responsive. Raise pointer capture priority to keep + // softkeys responsive in modal dialogs + cbaWindow->SetPointerCapturePriority(1); +} + +void QSoftKeyManagerPrivateS60::clearSoftkeys(CEikButtonGroupContainer &cba) +{ + QT_TRAP_THROWING( + //Using -1 instead of EAknSoftkeyEmpty to avoid flickering. + cba.SetCommandL(0, -1, KNullDesC); + // TODO: Should we clear also middle SK? + cba.SetCommandL(2, -1, KNullDesC); + ); + realSoftKeyActions.clear(); +} + +QString QSoftKeyManagerPrivateS60::softkeyText(QAction &softkeyAction) +{ + // In S60 softkeys and menu items do not support key accelerators (i.e. + // CTRL+X). Therefore, removing the accelerator characters from both softkey + // and menu item texts. + const int underlineShortCut = QApplication::style()->styleHint(QStyle::SH_UnderlineShortcut); + QString iconText = softkeyAction.iconText(); + return underlineShortCut ? softkeyAction.text() : iconText; +} + +QAction *QSoftKeyManagerPrivateS60::highestPrioritySoftkey(QAction::SoftKeyRole role) +{ + QAction *ret = NULL; + // Priority look up is two level + // 1. First widget with softkeys always has highest priority + for (int level = 0; !ret; level++) { + // 2. Highest priority action within widget + QList actions = requestedSoftKeyActions.values(level); + if (actions.isEmpty()) + break; + qSort(actions.begin(), actions.end(), QSoftKeyManagerPrivateS60::actionPriorityMoreThan); + foreach (QAction *action, actions) { + if (action->softKeyRole() == role) { + ret = action; + break; + } + } + } + return ret; +} + +bool QSoftKeyManagerPrivateS60::actionPriorityMoreThan(const QAction *firstItem, const QAction *secondItem) +{ + return firstItem->priority() > secondItem->priority(); +} + +void QSoftKeyManagerPrivateS60::setNativeSoftkey(CEikButtonGroupContainer &cba, + TInt position, TInt command, const TDesC &text) +{ + // Calling SetCommandL causes CBA redraw + QT_TRAP_THROWING(cba.SetCommandL(position, command, text)); +} + +bool QSoftKeyManagerPrivateS60::isOrientationLandscape() +{ + // Hard to believe that there is no public API in S60 to + // get current orientation. This workaround works with currently supported resolutions + return S60->screenHeightInPixels < S60->screenWidthInPixels; +} + +QSize QSoftKeyManagerPrivateS60::cbaIconSize(CEikButtonGroupContainer *cba, int position) +{ + Q_UNUSED(cba); + Q_UNUSED(position); + + // Will be implemented when EikSoftkeyImage usage license wise is OK +/* + const int index = isOrientationLandscape() ? 0 : 1; + if(cachedCbaIconSize[index].isNull()) { + // Only way I figured out to get CBA icon size without RnD SDK, was + // Only way I figured out to get CBA icon size without RnD SDK, was + // to set some dummy icon to CBA first and then ask CBA button CCoeControl::Size() + // The returned value is cached to avoid unnecessary icon setting every time. + const bool left = (position == LSK_POSITION); + if(position == LSK_POSITION || position == RSK_POSITION) { + CEikImage* tmpImage = NULL; + QT_TRAP_THROWING(tmpImage = new (ELeave) CEikImage); + EikSoftkeyImage::SetImage(cba, *tmpImage, left); // Takes myimage ownership + int command = S60_COMMAND_START + position; + setNativeSoftkey(*cba, position, command, KNullDesC()); + cachedCbaIconSize[index] = qt_TSize2QSize(cba->ControlOrNull(command)->Size()); + EikSoftkeyImage::SetLabel(cba, left); + } + } + + return cachedCbaIconSize[index]; +*/ + return QSize(); +} + +bool QSoftKeyManagerPrivateS60::setSoftkeyImage(CEikButtonGroupContainer *cba, + QAction &action, int position) +{ + bool ret = false; + Q_UNUSED(cba); + Q_UNUSED(action); + Q_UNUSED(position); + + // Will be implemented when EikSoftkeyImage usage license wise is OK + /* + const bool left = (position == LSK_POSITION); + if(position == LSK_POSITION || position == RSK_POSITION) { + QIcon icon = action.icon(); + if (!icon.isNull()) { + QPixmap pm = icon.pixmap(cbaIconSize(cba, position)); + pm = pm.scaled(cbaIconSize(cba, position)); + QBitmap mask = pm.mask(); + if (mask.isNull()) { + mask = QBitmap(pm.size()); + mask.fill(Qt::color1); + } + + CFbsBitmap* nBitmap = pm.toSymbianCFbsBitmap(); + CFbsBitmap* nMask = mask.toSymbianCFbsBitmap(); + + CEikImage* myimage = new (ELeave) CEikImage; + myimage->SetPicture( nBitmap, nMask ); // nBitmap and nMask ownership transfered + + EikSoftkeyImage::SetImage(cba, *myimage, left); // Takes myimage ownership + ret = true; + } else { + // Restore softkey to text based + EikSoftkeyImage::SetLabel(cba, left); + } + } + */ + return ret; +} + +bool QSoftKeyManagerPrivateS60::setSoftkey(CEikButtonGroupContainer &cba, + QAction::SoftKeyRole role, int position) +{ + QAction *action = highestPrioritySoftkey(role); + if (action) { + setSoftkeyImage(&cba, *action, position); + QString text = softkeyText(*action); + TPtrC nativeText = qt_QString2TPtrC(text); + int command = S60_COMMAND_START + position; + setNativeSoftkey(cba, position, command, nativeText); + cba.DimCommand(command, !action->isEnabled()); + realSoftKeyActions.insert(command, action); + return true; + } + return false; +} + +bool QSoftKeyManagerPrivateS60::setLeftSoftkey(CEikButtonGroupContainer &cba) +{ + return setSoftkey(cba, QAction::PositiveSoftKey, LSK_POSITION); +} + +bool QSoftKeyManagerPrivateS60::setMiddleSoftkey(CEikButtonGroupContainer &cba) +{ + // Note: In order to get MSK working, application has to have EAknEnableMSK flag set + // Currently it is not possible very easily) + // For more information see: http://wiki.forum.nokia.com/index.php/Middle_softkey_usage + return setSoftkey(cba, QAction::SelectSoftKey, MSK_POSITION); +} + +bool QSoftKeyManagerPrivateS60::setRightSoftkey(CEikButtonGroupContainer &cba) +{ + if (!setSoftkey(cba, QAction::NegativeSoftKey, RSK_POSITION)) { + Qt::WindowType windowType = Qt::Window; + QAction *action = requestedSoftKeyActions.value(0); + if (action) { + QWidget *actionParent = action->parentWidget(); + Q_ASSERT_X(actionParent, Q_FUNC_INFO, "No parent set for softkey action!"); + + QWidget *actionWindow = actionParent->window(); + Q_ASSERT_X(actionWindow, Q_FUNC_INFO, "Softkey action does not have window!"); + windowType = actionWindow->windowType(); + } + + if (windowType != Qt::Dialog && windowType != Qt::Popup) { + QString text(QSoftKeyManager::tr("Exit")); + TPtrC nativeText = qt_QString2TPtrC(text); + setNativeSoftkey(cba, RSK_POSITION, EAknSoftkeyExit, nativeText); + return true; + } + } + return false; +} + +void QSoftKeyManagerPrivateS60::setSoftkeys(CEikButtonGroupContainer &cba) +{ + int requestedSoftkeyCount = requestedSoftKeyActions.count(); + const int maxSoftkeyCount = 2; // TODO: differs based on orientation ans S60 versions (some have MSK) + if (requestedSoftkeyCount > maxSoftkeyCount) { + // We have more softkeys than available slots + // Put highest priority negative action to RSK and Options menu with rest of softkey actions to LSK + // TODO: Build menu + setLeftSoftkey(cba); + if(AknLayoutUtils::MSKEnabled()) + setMiddleSoftkey(cba); + setRightSoftkey(cba); + } else { + // We have less softkeys than available slots + // Put softkeys to request slots based on role + setLeftSoftkey(cba); + if(AknLayoutUtils::MSKEnabled()) + setMiddleSoftkey(cba); + setRightSoftkey(cba); + } +} + +void QSoftKeyManagerPrivateS60::updateSoftKeys_sys() +{ + //bool status = CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog(); + if (skipCbaUpdate()) + return; + + CEikButtonGroupContainer *nativeContainer = S60->buttonGroupContainer(); + Q_ASSERT_X(nativeContainer, Q_FUNC_INFO, "Native CBA does not exist!"); + ensureCbaVisibilityAndResponsiviness(*nativeContainer); + clearSoftkeys(*nativeContainer); + setSoftkeys(*nativeContainer); + + nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation +} + +bool QSoftKeyManagerPrivateS60::handleCommand(int command) +{ + QAction *action = realSoftKeyActions.value(command); + if (action) { + QVariant property = action->property(MENU_ACTION_PROPERTY); + if (property.isValid() && property.toBool()) { + QT_TRAP_THROWING(S60->menuBar()->TryDisplayMenuBarL()); + } else if (action->menu()) { + // TODO: This is hack, in order to use exising QMenuBar implementation for Symbian + // menubar needs to have widget to which it is associated. Since we want to associate + // menubar to action (which is inherited from QObejct), we create and associate QWidget + // to action and pass that for QMenuBar. This associates the menubar to action, and we + // can have own menubar for each action. + QWidget *actionContainer = action->property("_q_action_widget").value(); + if(!actionContainer) { + actionContainer = new QWidget(action->parentWidget()); + QMenuBar *menuBar = new QMenuBar(actionContainer); + foreach(QAction *menuAction, action->menu()->actions()) { + QMenu *menu = menuAction->menu(); + if(menu) + menuBar->addMenu(action->menu()); + else + menuBar->addAction(menuAction); + } + QVariant v; + v.setValue(actionContainer); + action->setProperty("_q_action_widget", v); + } + qt_symbian_next_menu_from_action(actionContainer); + QT_TRAP_THROWING(S60->menuBar()->TryDisplayMenuBarL()); + // TODO: hack remove, it can happen that IsDisplayingMenuOrDialog return false + // in updateSoftKeys_sys, and we will override menu CBA with our own + skipNextUpdate = true; + } else { + Q_ASSERT(action->softKeyRole() != QAction::NoSoftKey); + QWidget *actionParent = action->parentWidget(); + Q_ASSERT_X(actionParent, Q_FUNC_INFO, "No parent set for softkey action!"); + if (actionParent->isEnabled()) { + action->activate(QAction::Trigger); + return true; + } + } + } + return false; +} + +QT_END_NAMESPACE +#endif //QT_NO_SOFTKEYMANAGER diff --git a/src/gui/kernel/qsoftkeymanager_s60_p.h b/src/gui/kernel/qsoftkeymanager_s60_p.h new file mode 100644 index 0000000..46e3596 --- /dev/null +++ b/src/gui/kernel/qsoftkeymanager_s60_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QSOFTKEYMANAGER_S60_P_H +#define QSOFTKEYMANAGER_S60_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qobject_p.h" +#include "private/qsoftkeymanager_common_p.h" + +QT_BEGIN_HEADER + +#ifndef QT_NO_SOFTKEYMANAGER + +QT_BEGIN_NAMESPACE + +class CEikButtonGroupContainer; +class QAction; + +class QSoftKeyManagerPrivateS60 : public QSoftKeyManagerPrivate +{ + Q_DECLARE_PUBLIC(QSoftKeyManager) + +public: + QSoftKeyManagerPrivateS60(); + +public: + void updateSoftKeys_sys(); + bool handleCommand(int command); + +private: + bool skipCbaUpdate(); + void ensureCbaVisibilityAndResponsiviness(CEikButtonGroupContainer &cba); + void clearSoftkeys(CEikButtonGroupContainer &cba); + QString softkeyText(QAction &softkeyAction); + QAction *highestPrioritySoftkey(QAction::SoftKeyRole role); + static bool actionPriorityMoreThan(const QAction* item1, const QAction* item2); + void setNativeSoftkey(CEikButtonGroupContainer &cba, TInt position, TInt command, const TDesC& text); + bool isOrientationLandscape(); + QSize cbaIconSize(CEikButtonGroupContainer *cba, int position); + bool setSoftkeyImage(CEikButtonGroupContainer *cba, QAction &action, int position); + bool setSoftkey(CEikButtonGroupContainer &cba, QAction::SoftKeyRole role, int position); + bool setLeftSoftkey(CEikButtonGroupContainer &cba); + bool setMiddleSoftkey(CEikButtonGroupContainer &cba); + bool setRightSoftkey(CEikButtonGroupContainer &cba); + void setSoftkeys(CEikButtonGroupContainer &cba); + +private: + QHash realSoftKeyActions; + QSize cachedCbaIconSize[2]; + bool skipNextUpdate; +}; + + +QT_END_NAMESPACE + +#endif //QT_NO_SOFTKEYMANAGER + +QT_END_HEADER + +#endif // QSOFTKEYMANAGER_S60_P_H diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 1163055..735ca7a 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -128,6 +128,7 @@ public: static inline RWindowGroup& windowGroup(); static inline CWsScreenDevice* screenDevice(); static inline CCoeAppUi* appUi(); + static inline CEikMenuBar* menuBar(); #ifdef Q_WS_S60 static inline CEikStatusPane* statusPane(); static inline CCoeControl* statusPaneSubPane(TInt aPaneId); @@ -270,6 +271,11 @@ inline CCoeAppUi* QS60Data::appUi() return CCoeEnv::Static()-> AppUi(); } +inline CEikMenuBar* QS60Data::menuBar() +{ + return CEikonEnv::Static()->AppUiFactory()->MenuBar(); +} + #ifdef Q_WS_S60 inline CEikStatusPane* QS60Data::statusPane() { diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index 1622191..269cd12 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -119,8 +119,6 @@ void QMainWindowPrivate::init() q->setAttribute(Qt::WA_Hover); #ifdef QT_SOFTKEYS_ENABLED menuBarAction = QSoftKeyManager::createAction(QSoftKeyManager::MenuSoftKey, q); - menuBarAction->setObjectName(QLatin1String("_q_menuSoftKeyAction")); - menuBarAction->setVisible(false); #endif } diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h index b7272f7..aaed6b1 100644 --- a/src/gui/widgets/qmenu_p.h +++ b/src/gui/widgets/qmenu_p.h @@ -71,6 +71,7 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_MENU #ifdef Q_WS_S60 +void qt_symbian_next_menu_from_action(QWidget* actionContainer); void qt_symbian_show_toplevel(CEikMenuPane* menuPane); void qt_symbian_show_submenu(CEikMenuPane* menuPane, int id); #endif // Q_WS_S60 @@ -87,7 +88,7 @@ QT_BEGIN_NAMESPACE typedef void NSMenuItem; # endif //__OBJC__ struct QMacMenuAction { - QMacMenuAction() + QMacMenuAction() #ifndef QT_MAC_USE_COCOA : command(0) #else @@ -124,7 +125,7 @@ typedef QList QMenuMergeList; #ifdef Q_WS_WINCE struct QWceMenuAction { - uint command; + uint command; QPointer action; HMENU menuHandle; QWceMenuAction() : menuHandle(0), command(0) {} @@ -340,7 +341,7 @@ public: QList actionItems; HMENU menuHandle; QWceMenuPrivate(); - ~QWceMenuPrivate(); + ~QWceMenuPrivate(); void addAction(QAction *, QWceMenuAction* =0); void addAction(QWceMenuAction *, QWceMenuAction* =0); void syncAction(QWceMenuAction *); diff --git a/src/gui/widgets/qmenu_symbian.cpp b/src/gui/widgets/qmenu_symbian.cpp index 28b27d4..eae97a6 100644 --- a/src/gui/widgets/qmenu_symbian.cpp +++ b/src/gui/widgets/qmenu_symbian.cpp @@ -81,6 +81,7 @@ static QList nativeMenuBars; static uint qt_symbian_menu_static_cmd_id = QT_SYMBIAN_FIRST_MENU_ITEM; static QPointer widgetWithContextMenu; static QList contextMenuActionList; +static QWidget* actionMenu = NULL; static int contexMenuCommand=0; bool menuExists() @@ -224,8 +225,26 @@ static void rebuildMenu() } #ifdef Q_WS_S60 +void qt_symbian_next_menu_from_action(QWidget *actionContainer) +{ + actionMenu = actionContainer; +} + void qt_symbian_show_toplevel( CEikMenuPane* menuPane) { + if (actionMenu) { + QMenuBarPrivate *mb = 0; + mb = menubars()->value(actionMenu); + qt_symbian_menu_static_cmd_id = QT_SYMBIAN_FIRST_MENU_ITEM; + deleteAll( &symbianMenus ); + Q_ASSERT(mb); + mb->symbian_menubar->rebuild(); + for (int i = 0; i < symbianMenus.count(); ++i) + QT_TRAP_THROWING(menuPane->AddMenuItemL(symbianMenus.at(i)->menuItemData)); + actionMenu = NULL; + return; + } + if (!menuExists()) return; rebuildMenu(); @@ -271,10 +290,16 @@ int QMenuBarPrivate::symbianCommands(int command) void QMenuBarPrivate::symbianCreateMenuBar(QWidget *parent) { Q_Q(QMenuBar); - if (parent && parent->isWindow()){ - menubars()->insert(q->window(), this); - symbian_menubar = new QSymbianMenuBarPrivate(this); - nativeMenuBars.append(q); + if (parent) { + if(parent->isWindow()) { + menubars()->insert(q->window(), this); + symbian_menubar = new QSymbianMenuBarPrivate(this); + nativeMenuBars.append(q); + } else { + menubars()->insert(q->parentWidget(), this); + symbian_menubar = new QSymbianMenuBarPrivate(this); + nativeMenuBars.append(q); + } } } @@ -284,6 +309,7 @@ void QMenuBarPrivate::symbianDestroyMenuBar() int index = nativeMenuBars.indexOf(q); nativeMenuBars.removeAt(index); menubars()->remove(q->window(), this); + menubars()->remove(q->parentWidget(), this); rebuildMenu(); if (symbian_menubar) delete symbian_menubar; diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index 0e14385..9caadb7 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -667,7 +667,7 @@ void QMenuBar::initStyleOption(QStyleOptionMenuItem *option, const QAction *acti \i Application Menu | About \i The application name is fetched from the \c {Info.plist} file (see note below). If this entry is not found no About item - will appear in the Application Menu. + will appear in the Application Menu. \row \i config, options, setup, settings or preferences \i Application Menu | Preferences \i If this entry is not found the Settings item will be disabled -- cgit v0.12 From ca57a6e6bb48b468631576c3bd316f6c2b24e0dd Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Wed, 3 Feb 2010 14:07:35 +0100 Subject: Compile fix for non-Symbian compilers Putting the code for "case CT_ComboBox:" into {} --- src/gui/styles/qs60style.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index fc435e8..9025e5b 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -2399,13 +2399,14 @@ QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt, sz.setHeight(sz.height() + 2 * pixelMetric(PM_FocusFrameVMargin)); break; #ifndef QT_NO_COMBOBOX - case CT_ComboBox: - // Fixing Ui design issues with too wide QComboBoxes and greedy SizeHints - // Make sure, that the combobox says within the screen. - const QSize desktopContentSize = QApplication::desktop()->availableGeometry().size() - -QSize(pixelMetric(PM_LayoutLeftMargin) + pixelMetric(PM_LayoutRightMargin), 0); - sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget). - boundedTo(desktopContentSize); + case CT_ComboBox: { + // Fixing Ui design issues with too wide QComboBoxes and greedy SizeHints + // Make sure, that the combobox says within the screen. + const QSize desktopContentSize = QApplication::desktop()->availableGeometry().size() + -QSize(pixelMetric(PM_LayoutLeftMargin) + pixelMetric(PM_LayoutRightMargin), 0); + sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget). + boundedTo(desktopContentSize); + } break; #endif default: -- cgit v0.12 From 14ee2007fd2ada46e5fe30af838f5a7fcb7c6f4d Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 3 Feb 2010 15:39:43 +0000 Subject: Corrected namespace for Phonon::MMF translatable error strings Error strings are now part of the Phonon::MMF namespace. Reviewed-by: trustme --- src/3rdparty/phonon/mmf/utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty/phonon/mmf/utils.h b/src/3rdparty/phonon/mmf/utils.h index 56ccafc..acad55a 100644 --- a/src/3rdparty/phonon/mmf/utils.h +++ b/src/3rdparty/phonon/mmf/utils.h @@ -44,7 +44,7 @@ enum PanicCode { class Utils { - Q_DECLARE_TR_FUNCTIONS(Utils) + Q_DECLARE_TR_FUNCTIONS(Phonon::MMF) public: /** -- cgit v0.12 From 4b059682ddba4a1fb90c656d7d829680779a2e60 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 3 Feb 2010 15:52:14 +0000 Subject: Added descriptions of translatable strings for Phonon MMF reverb effect Reviewed-by: trustme --- src/3rdparty/phonon/mmf/environmentalreverb.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/phonon/mmf/environmentalreverb.cpp b/src/3rdparty/phonon/mmf/environmentalreverb.cpp index 89f8d60..4a6ce29 100644 --- a/src/3rdparty/phonon/mmf/environmentalreverb.cpp +++ b/src/3rdparty/phonon/mmf/environmentalreverb.cpp @@ -140,55 +140,75 @@ bool EnvironmentalReverb::getParameters(CMdaAudioOutputStream *stream, TUint32 umin, umax; // DecayHFRatio + // Ratio of high-frequency decay time to the value specified by + // DecayTime. effect->DecayHFRatioRange(umin, umax); parameters.append(createParameter( DecayHFRatio, tr("Decay HF ratio (%)"), effect->DecayHFRatio(), umin, umax)); // DecayTime + // Time over which reverberation is diminished. effect->DecayTimeRange(umin, umax); parameters.append(createParameter( DecayTime, tr("Decay time (ms)"), effect->DecayTime(), umin, umax)); // Density + // Delay between first and subsequent reflections. + // Note that the S60 platform documentation does not make clear + // the distinction between this value and the Diffusion value. parameters.append(createParameter( Density, tr("Density (%)"), effect->Density(), 0, 100)); // Diffusion + // Delay between first and subsequent reflections. + // Note that the S60 platform documentation does not make clear + // the distinction between this value and the Density value. parameters.append(createParameter( Diffusion, tr("Diffusion (%)"), effect->Diffusion(), 0, 100)); // ReflectionsDelay + // Amount of delay between the arrival the direct path from the + // source and the arrival of the first reflection. parameters.append(createParameter( ReflectionsDelay, tr("Reflections delay (ms)"), effect->ReflectionsDelay(), 0, effect->ReflectionsDelayMax())); // ReflectionsLevel - effect->ReflectionLevelRange(min, max); + // Amplitude of reflections. This value is corrected by the RoomLevel + // to give the final reflection amplitude. + effect->ReflectionLevelRange(min, max); parameters.append(createParameter( ReflectionsLevel, tr("Reflections level (mB)"), effect->ReflectionsLevel(), min, max, EffectParameter::LogarithmicHint)); // ReverbDelay + // Amount of time between arrival of the first reflection and start of + // the late reverberation. parameters.append(createParameter( ReverbDelay, tr("Reverb delay (ms)"), effect->ReverbDelay(), 0, effect->ReverbDelayMax())); // ReverbLevel + // Amplitude of reverberations. This value is corrected by the + // RoomLevel to give the final reverberation amplitude. effect->ReverbLevelRange(min, max); parameters.append(createParameter( ReverbLevel, tr("Reverb level (mB)"), effect->ReverbLevel(), min, max, EffectParameter::LogarithmicHint)); // RoomHFLevel + // Amplitude of low-pass filter used to attenuate the high frequency + // component of reflected sound. effect->RoomHFLevelRange(min, max); parameters.append(createParameter( RoomHFLevel, tr("Room HF level"), effect->RoomHFLevel(), min, max)); // RoomLevel + // Master volume control for all reflected sound. effect->RoomLevelRange(min, max); parameters.append(createParameter( RoomLevel, tr("Room level (mB)"), effect->RoomLevel(), -- cgit v0.12 From afae62256897a8ed14e3156df33838082c6d4b98 Mon Sep 17 00:00:00 2001 From: Iain Date: Thu, 5 Nov 2009 13:16:41 +0100 Subject: Adjust rw base address for gui built with GCCE for Symbian OS fixed during merge to match new style flag setting. Reviewed-by: Janne Koskinen --- src/gui/gui.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 4215f97..8ad3bac 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -54,4 +54,5 @@ DEFINES += Q_INTERNAL_QAPP_SRC symbian:TARGET.UID3=0x2001B2DD # ro-section in gui can exceed default allocated space, so more rw-section little further -symbian-sbsv2: QMAKE_LFLAGS.ARMCC += --rw-base 0x800000" +symbian-sbsv2: QMAKE_LFLAGS.ARMCC += --rw-base 0x800000 +symbian: QMAKE_LFLAGS.GCCE += -Tdata 0xC00000 -- cgit v0.12