diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2011-05-07 00:02:01 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@nokia.com> | 2011-05-07 00:02:01 +0200 |
commit | f67b8df3ebdba2d398b9cce686b7c644adffff08 (patch) | |
tree | 062dd469f7cf8daa01a32d3e7b767b8fbdb7573a /src/gui/platforms/s60/qsoftkeymanager_s60.cpp | |
parent | 32ce4fe9e6a94e77828e976776cf08da85254ff2 (diff) |
library split
Diffstat (limited to 'src/gui/platforms/s60/qsoftkeymanager_s60.cpp')
-rw-r--r-- | src/gui/platforms/s60/qsoftkeymanager_s60.cpp | 440 |
1 files changed, 0 insertions, 440 deletions
diff --git a/src/gui/platforms/s60/qsoftkeymanager_s60.cpp b/src/gui/platforms/s60/qsoftkeymanager_s60.cpp deleted file mode 100644 index 79ed91af5b..0000000000 --- a/src/gui/platforms/s60/qsoftkeymanager_s60.cpp +++ /dev/null @@ -1,440 +0,0 @@ -/**************************************************************************** -** -** 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 "qstyle.h" -#include "qmenubar.h" -#include "private/qt_s60_p.h" -#include "private/qmenu_p.h" -#include "private/qaction_p.h" -#include "private/qsoftkeymanager_p.h" -#include "private/qsoftkeymanager_s60_p.h" -#include "private/qobject_p.h" -#include <eiksoftkeyimage.h> -#include <eikcmbut.h> - -#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() : cbaHasImage(4) // 4 since MSK position index is 3 -{ - cachedCbaIconSize[0] = QSize(0,0); - cachedCbaIconSize[1] = QSize(0,0); - cachedCbaIconSize[2] = QSize(0,0); - cachedCbaIconSize[3] = QSize(0,0); -} - -bool QSoftKeyManagerPrivateS60::skipCbaUpdate() -{ - // Lets not update softkeys if - // 1. We don't have application panes, i.e. cba - // 2. Our CBA is not active, i.e. S60 native dialog or menu with custom CBA is shown - // 2.1. Except if thre is no current CBA at all and WindowSoftkeysRespondHint is set - - // Note: Cannot use IsDisplayingMenuOrDialog since CBA update can be triggered before - // menu/dialog CBA is actually displayed i.e. it is being costructed. - CEikButtonGroupContainer *appUiCba = S60->buttonGroupContainer(); - if (!appUiCba) - return true; - // CEikButtonGroupContainer::Current returns 0 if CBA is not visible at all - CEikButtonGroupContainer *currentCba = CEikButtonGroupContainer::Current(); - // Check if softkey need to be update even they are not visible - bool cbaRespondsWhenInvisible = false; - QWidget *window = QApplication::activeWindow(); - if (window && (window->windowFlags() & Qt::WindowSoftkeysRespondHint)) - cbaRespondsWhenInvisible = true; - - if (QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes) - || (appUiCba != currentCba && !cbaRespondsWhenInvisible)) { - 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) -{ -#ifdef SYMBIAN_VERSION_SYMBIAN3 - QT_TRAP_THROWING( - //EAknSoftkeyEmpty is used, because using -1 adds softkeys without actions on Symbian3 - cba.SetCommandL(0, EAknSoftkeyEmpty, KNullDesC); - cba.SetCommandL(2, EAknSoftkeyEmpty, KNullDesC); - ); -#else - 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); - ); -#endif - 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<QAction*> 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)); -} - -QPoint QSoftKeyManagerPrivateS60::softkeyIconPosition(int position, QSize sourceSize, QSize targetSize) -{ - QPoint iconPosition(0,0); - switch( AknLayoutUtils::CbaLocation() ) - { - case AknLayoutUtils::EAknCbaLocationBottom: - // RSK must be moved to right, LSK in on correct position by default - if (position == RSK_POSITION) - iconPosition.setX(targetSize.width() - sourceSize.width()); - break; - case AknLayoutUtils::EAknCbaLocationRight: - case AknLayoutUtils::EAknCbaLocationLeft: - // Already in correct position - default: - break; - } - - // Align horizontally to center - iconPosition.setY((targetSize.height() - sourceSize.height()) >> 1); - return iconPosition; -} - -QPixmap QSoftKeyManagerPrivateS60::prepareSoftkeyPixmap(QPixmap src, int position, QSize targetSize) -{ - QPixmap target(targetSize); - target.fill(Qt::transparent); - QPainter p; - p.begin(&target); - p.drawPixmap(softkeyIconPosition(position, src.size(), targetSize), src); - p.end(); - return target; -} - -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) -{ - - int index = position; - index += isOrientationLandscape() ? 0 : 1; - if(cachedCbaIconSize[index].isNull()) { - // 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); - - if(cachedCbaIconSize[index] == QSize(138,72)) { - // Hack for S60 5.0 (5800) landscape orientation, which return wrong icon size - cachedCbaIconSize[index] = QSize(60,60); - } - } - } - - return cachedCbaIconSize[index]; -} - -bool QSoftKeyManagerPrivateS60::setSoftkeyImage(CEikButtonGroupContainer *cba, - QAction &action, int position) -{ - bool ret = false; - - const bool left = (position == LSK_POSITION); - if(position == LSK_POSITION || position == RSK_POSITION) { - QIcon icon = action.icon(); - if (!icon.isNull()) { - // Get size of CBA icon area based on button position and orientation - QSize requiredIconSize = cbaIconSize(cba, position); - // Get pixmap out of icon based on preferred size, the aspect ratio is kept - QPixmap pmWihtAspectRatio = icon.pixmap(requiredIconSize); - // Native softkeys require that pixmap size is exactly the same as requiredIconSize - // prepareSoftkeyPixmap creates a new pixmap with requiredIconSize and blits the 'pmWihtAspectRatio' - // to correct location of it - QPixmap softkeyPixmap = prepareSoftkeyPixmap(pmWihtAspectRatio, position, requiredIconSize); - - QPixmap softkeyAlpha = softkeyPixmap.alphaChannel(); - // Alpha channel in 5.1 and older devices need to be inverted - // TODO: Switch to use toSymbianCFbsBitmap with invert when available - if(QSysInfo::s60Version() <= QSysInfo::SV_S60_5_1) { - QImage alphaImage = softkeyAlpha.toImage(); - alphaImage.invertPixels(); - softkeyAlpha = QPixmap::fromImage(alphaImage); - } - - CFbsBitmap* nBitmap = softkeyPixmap.toSymbianCFbsBitmap(); - CFbsBitmap* nMask = softkeyAlpha.toSymbianCFbsBitmap(); - - CEikImage* myimage = new (ELeave) CEikImage; - myimage->SetPicture( nBitmap, nMask ); // nBitmap and nMask ownership transferred - - EikSoftkeyImage::SetImage(cba, *myimage, left); // Takes myimage ownership - cbaHasImage[position] = true; - ret = true; - } else { - // Restore softkey to text based - if (cbaHasImage[position]) { - EikSoftkeyImage::SetLabel(cba, left); - cbaHasImage[position] = false; - } - } - } - 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; -#ifdef SYMBIAN_VERSION_SYMBIAN3 - if (softKeyCommandActions.contains(action)) - command = softKeyCommandActions.value(action); -#endif - setNativeSoftkey(cba, position, command, nativeText); - const bool dimmed = !action->isEnabled() && !QSoftKeyManager::isForceEnabledInSofkeys(action); - cba.DimCommand(command, dimmed); - 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)) { - const Qt::WindowType windowType = initialSoftKeySource - ? initialSoftKeySource->window()->windowType() : Qt::Window; - if (windowType != Qt::Dialog && windowType != Qt::Popup) { - QString text(QSoftKeyManager::tr("Exit")); - TPtrC nativeText = qt_QString2TPtrC(text); - if (cbaHasImage[RSK_POSITION]) { - EikSoftkeyImage::SetLabel(&cba, false); - cbaHasImage[RSK_POSITION] = false; - } - setNativeSoftkey(cba, RSK_POSITION, EAknSoftkeyExit, nativeText); - cba.DimCommand(EAknSoftkeyExit, false); - 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() -{ - 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 -} - -static void resetMenuBeingConstructed(TAny* /*aAny*/) -{ - S60->menuBeingConstructed = false; -} - -void QSoftKeyManagerPrivateS60::tryDisplayMenuBarL() -{ - CleanupStack::PushL(TCleanupItem(resetMenuBeingConstructed, NULL)); - S60->menuBeingConstructed = true; - S60->menuBar()->TryDisplayMenuBarL(); - CleanupStack::PopAndDestroy(); // Reset menuBeingConstructed to false in all cases -} - -bool QSoftKeyManagerPrivateS60::handleCommand(int command) -{ - QAction *action = realSoftKeyActions.value(command); - if (action) { - bool property = QActionPrivate::get(action)->menuActionSoftkeys; - if (property) { - QT_TRAP_THROWING(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 QObject), 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<QWidget*>(); - 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(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(tryDisplayMenuBarL()); - } - - 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 |