--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emailuis/emailui/src/FreestyleEmailUiShortcutBinding.cpp Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,539 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ *
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+ *
+* Contributors:
+ *
+* Description: This file implements class CFSEmailUiShortcutBinding.
+ *
+ */
+
+
+#include "emailtrace.h"
+#include <PtiEngine.h>
+#include <PtiKeyMappings.h>
+#include <centralrepository.h>
+#include <AvkonInternalCRKeys.h>
+#include <eikmenup.h>
+
+#include "FreestyleEmailUiShortcutBinding.h"
+#include "FSEmail.pan"
+
+
+//////////////////////////////
+// The shortcut binding tables
+// ---------------------------
+// In case the same shortcut is assigned for multiple commands, the shortcut to
+// command conversion will always return the first mapping.
+//
+// Shortcuts with modifiers must be listed before unmodifed shortcuts, at least when
+// the same key has different meaning as plain key and with modifier. Otherwise,
+// the unmodified mapping will be used also for the modified key.
+
+// Shortcuts for the mail list view
+const CFSEmailUiShortcutBinding::TShortcutBinding KMailListShortcuts[] =
+ {
+ { 0, 'A', 0, EFsEmailUiCmdActionsReplyAll },
+ { 0, 'R', 0, EFsEmailUiCmdActionsReply },
+ { 0, 'F', 0, EFsEmailUiCmdActionsForward },
+ { 0, 'M', 0, EFsEmailUiCmdActionsMove },
+ { 0, 'Y', 0, EFsEmailUiCmdActionsCopyMessage },
+ { 0, 'D', 0, EFsEmailUiCmdActionsDelete },
+ { 0, EStdKeyBackspace, 0, EFsEmailUiCmdActionsDelete },
+ { 0, 'T', 0, EFsEmailUiCmdGoToTop },
+ { 0, 'B', 0, EFsEmailUiCmdGoToBottom },
+ { 0, 'J', 0, EFsEmailUiCmdPageUp },
+ { 0, 'K', 0, EFsEmailUiCmdPageDown },
+ { 0, 'L', 0, EFsEmailUiCmdActionsFlag },
+ { 0, 'C', 0, EFsEmailUiCmdCompose },
+ { 0, 'E', 0, EFsEmailUiCmdCalActionsAccept },
+ { 0, 'G', 0, EFsEmailUiCmdCalActionsTentative },
+ { 0, 'V', 0, EFsEmailUiCmdCalActionsDecline },
+ { 0, 'O', 0, EFsEmailUiCmdActionsOpen },
+ { 0, 'Z', 0, EFsEmailUiCmdSync },
+ { 0, 'S', 0, EFsEmailUiCmdSearch },
+ { 0, 'Q', 0, EFsEmailUiCmdGoToSwitchFolder },
+ { 0, 'W', 0, EFsEmailUiCmdGoToSwitchSorting },
+ { 0, 'H', 0, EFsEmailUiCmdHelp },
+
+ { 0, 'U', 0, EFsEmailUiCmdMarkAsReadUnreadToggle },
+ { 0, 'U', 0, EFsEmailUiCmdMarkAsRead },
+ { 0, 'U', 0, EFsEmailUiCmdMarkAsUnread },
+
+ { 0, 'I', 0, EFsEmailUiCmdActionsCollapseExpandAllToggle },
+ { 0, 'I', 0, EFsEmailUiCmdActionsCollapseAll },
+ { 0, 'I', 0, EFsEmailUiCmdActionsExpandAll },
+
+ { 0, 0, 0, EFsEmailUiCmdMarkUnmarkToggle },
+ { 0, 0, 0, EFsEmailUiCmdMarkMark },
+ { 0, 0, 0, EFsEmailUiCmdMarkUnmark }
+ };
+
+// Shortcuts for the mail viewer
+const CFSEmailUiShortcutBinding::TShortcutBinding KMailViewerShortcuts[] =
+ {
+ { 0, 'C', EModifierCtrl, EFsEmailUiCmdActionsCopyToClipboard },
+
+ { 0, 'A', 0, EFsEmailUiCmdActionsReplyAll },
+ { 0, 'R', 0, EFsEmailUiCmdActionsReply },
+ { 0, 'F', 0, EFsEmailUiCmdActionsForward },
+ { 0, 'F', 0, EFsEmailUiCmdActionsForward2 },
+ { 0, 'M', 0, EFsEmailUiCmdActionsMoveMessage },
+ { 0, 'Y', 0, EFsEmailUiCmdActionsCopyMessage },
+ { 0, 'D', 0, EFsEmailUiCmdActionsDelete },
+ { 0, EStdKeyBackspace, 0, EFsEmailUiCmdActionsDelete },
+ { 0, 'T', 0, EFsEmailUiCmdGoToTop },
+ { 0, 'B', 0, EFsEmailUiCmdGoToBottom },
+ { 0, 'J', 0, EFsEmailUiCmdPageUp },
+ { 0, 'K', 0, EFsEmailUiCmdPageDown },
+ { 0, 'N', 0, EFsEmailUiCmdNextMessage },
+ { 0, 'P', 0, EFsEmailUiCmdPreviousMessage },
+ { 0, 'L', 0, EFsEmailUiCmdActionsFlag },
+ { 0, 'C', 0, EFsEmailUiCmdCompose },
+ { 0, 'H', 0, EFsEmailUiCmdHelp },
+
+ { 0, 'U', 0, EFsEmailUiCmdMarkAsReadUnreadToggle },
+ { 0, 'U', 0, EFsEmailUiCmdMarkAsRead },
+ { 0, 'U', 0, EFsEmailUiCmdMarkAsUnread }
+ };
+
+// Shortcuts for the HTML viewer
+const CFSEmailUiShortcutBinding::TShortcutBinding KHtmlViewerShortcuts[] =
+ {
+ { 0, 'A', 0, EFsEmailUiCmdActionsReplyAll },
+ { 0, 'R', 0, EFsEmailUiCmdActionsReply },
+ { 0, 'F', 0, EFsEmailUiCmdActionsForward },
+ { 0, 'D', 0, EFsEmailUiCmdActionsDelete },
+ { 0, EStdKeyBackspace, 0, EFsEmailUiCmdActionsDelete },
+ { 0, 'H', 0, EFsEmailUiCmdHelp },
+ { 0, '+', 0, EFsEmailUiCmdZoomIn },
+ { 0, '-', 0, EFsEmailUiCmdZoomOut }
+ };
+
+// Shortcuts for the search results view
+const CFSEmailUiShortcutBinding::TShortcutBinding KSearchResultsShortcuts[] =
+ {
+ { 0, 'O', 0, EFsEmailUiCmdOpen },
+ { 0, 'S', 0, EFsEmailUiCmdSearch },
+ { 0, 'S', 0, EFsEmailUiCmdNewSearch },
+ { 0, 'H', 0, EFsEmailUiCmdHelp },
+ { 0, 'T', 0, EFsEmailUiCmdGoToTop },
+ { 0, 'B', 0, EFsEmailUiCmdGoToBottom },
+ { 0, 'J', 0, EFsEmailUiCmdPageUp },
+ { 0, 'K', 0, EFsEmailUiCmdPageDown },
+ { 0, 'A', 0, EFsEmailUiCmdActionsReplyAll },
+ { 0, 'R', 0, EFsEmailUiCmdActionsReply },
+ { 0, 'F', 0, EFsEmailUiCmdActionsForward },
+ { 0, 'D', 0, EFsEmailUiCmdActionsDelete },
+ { 0, EStdKeyBackspace, 0, EFsEmailUiCmdActionsDelete },
+ { 0, 'E', 0, EFsEmailUiCmdCalActionsAccept },
+ { 0, 'G', 0, EFsEmailUiCmdCalActionsTentative },
+ { 0, 'V', 0, EFsEmailUiCmdCalActionsDecline },
+ { 0, 'U', 0, EFsEmailUiCmdMarkAsReadUnreadToggle },
+ { 0, 'U', 0, EFsEmailUiCmdMarkAsRead },
+ { 0, 'U', 0, EFsEmailUiCmdMarkAsUnread }
+ };
+
+// Shortcuts for generic list views. These are used with Mail details, attachment list, etc.
+const CFSEmailUiShortcutBinding::TShortcutBinding KGenericListShortcuts[] =
+ {
+ { 0, 'C', EModifierCtrl, EFsEmailUiCmdActionsCopyToClipboard },
+
+ { 0, 'O', 0, EFsEmailUiCmdOpen },
+ { 0, 'D', 0, EFsEmailUiCmdActionsDelete },
+ { 0, EStdKeyBackspace, 0, EFsEmailUiCmdActionsDelete },
+ { 0, 'T', 0, EFsEmailUiCmdGoToTop },
+ { 0, 'B', 0, EFsEmailUiCmdGoToBottom },
+ { 0, 'J', 0, EFsEmailUiCmdPageUp },
+ { 0, 'K', 0, EFsEmailUiCmdPageDown },
+ { 0, 'H', 0, EFsEmailUiCmdHelp },
+
+ { 0, 'I', 0, EFsEmailUiCmdActionsCollapseExpandAllToggle },
+ { 0, 'I', 0, EFsEmailUiCmdActionsCollapseAll },
+ { 0, 'I', 0, EFsEmailUiCmdActionsExpandAll }
+ };
+
+// Shortcuts for the main grid
+const CFSEmailUiShortcutBinding::TShortcutBinding KMainGridShortcuts[] =
+ {
+ { 0, 'O', 0, EFsEmailUiCmdOpen },
+ { 0, 'Z', 0, EFsEmailUiCmdSync },
+ { 0, 'Z', 0, EFsEmailUiCmdSyncAll },
+ { 0, 'H', 0, EFsEmailUiCmdHelp },
+ };
+
+// Shortcuts for send attachments list view
+const CFSEmailUiShortcutBinding::TShortcutBinding KSendAttachmentListShortcuts[] =
+ {
+ { 0, 'O', 0, ESendAttachmentMenuOpen },
+ { 0, 'D', 0, ESendAttachmentMenuRemoveAttachment },
+ { 0, EStdKeyBackspace, 0, ESendAttachmentMenuRemoveAttachment },
+ { 0, 'T', 0, EFsEmailUiCmdGoToTop },
+ { 0, 'B', 0, EFsEmailUiCmdGoToBottom },
+ { 0, 'J', 0, EFsEmailUiCmdPageUp },
+ { 0, 'K', 0, EFsEmailUiCmdPageDown },
+ { 0, 'H', 0, ESendAttachmentMenuHelp },
+ { 0, 'I', 0, EFsEmailUiCmdActionsCollapseExpandAllToggle }
+ };
+
+// Shortcuts for settings and global settings views
+const CFSEmailUiShortcutBinding::TShortcutBinding KSettingsShortcuts[] =
+ {
+ { 0, 'O', 0, EFsEmailUiCmdOpen },
+ { 0, 'T', 0, EFsEmailUiCmdGoToTop },
+ { 0, 'B', 0, EFsEmailUiCmdGoToBottom },
+ { 0, 'J', 0, EFsEmailUiCmdPageUp },
+ { 0, 'K', 0, EFsEmailUiCmdPageDown },
+ { 0, 'H', 0, EFsEmailUiCmdHelp }
+ };
+
+///////////////////////
+// The class definition
+CFSEmailUiShortcutBinding* CFSEmailUiShortcutBinding::NewL()
+ {
+ FUNC_LOG;
+ CFSEmailUiShortcutBinding* self = new (ELeave) CFSEmailUiShortcutBinding();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+CFSEmailUiShortcutBinding::~CFSEmailUiShortcutBinding()
+ {
+ FUNC_LOG;
+ delete iPtiEngine;
+ iQwertyMappings = NULL; // owned by iPtiEngine
+ iHalfQwertyMappings = NULL; // ownned by iPtiEngine
+ iKbLayoutProperty.Close();
+ }
+
+
+// ----------------------------------------------------------------------------
+TInt CFSEmailUiShortcutBinding::CommandForShortcutKey( const TKeyEvent& aKey,
+ TShortcutContext aContext ) const
+ {
+ FUNC_LOG;
+ TText shortcut = aKey.iScanCode;
+ TBuf<1> keyData; // we are only interested about the first char of the key
+
+ TKeyBoardType kbType = KeyBoardType();
+
+ if ( kbType == EQwerty4x12 || kbType == EQwerty4x10 ||
+ kbType == EQwerty3x11 || kbType == ECustomQwerty )
+ {
+ // One of the QWERTY modes
+ // Map the key to the corresponding character on the current keyboard
+ // If Fn is held depressed, use the Fn mappings, otherwise use upper case mappings.
+ TPtiTextCase caseMode = EPtiCaseUpper;
+#ifdef RD_INTELLIGENT_TEXT_INPUT
+ if ( aKey.iModifiers&EModifierRightFunc )
+ {
+ caseMode = EPtiCaseFnLower;
+ }
+#endif // RD_INTELLIGENT_TEXT_INPUT
+ if ( iQwertyMappings )
+ {
+ iQwertyMappings->GetDataForKey( static_cast<TPtiKey>(aKey.iScanCode),
+ keyData, caseMode );
+ }
+ }
+ else if ( kbType == EHalfQwerty )
+ {
+ // Half-QWERTY mode
+ // Map the key to the corresponding character in the Fn mode
+ if ( iHalfQwertyMappings )
+ {
+#ifdef RD_INTELLIGENT_TEXT_INPUT
+ iHalfQwertyMappings->GetDataForKey( static_cast<TPtiKey>(aKey.iScanCode),
+ keyData, EPtiCaseFnLower );
+#endif // RD_INTELLIGENT_TEXT_INPUT
+ }
+ }
+ else
+ {
+ // ITU-T mode, use scancode directly without mapping
+ }
+
+ // Substitute the scan code with the mapped character if available
+ if ( keyData.Length() )
+ {
+ shortcut = keyData[0];
+ }
+ // Map hash and asterisk keys separately if they have not been mapped in PtiEngine
+ else if ( shortcut == EStdKeyHash )
+ {
+ shortcut = '#';
+ }
+ else if ( shortcut == EStdKeyNkpAsterisk )
+ {
+ shortcut = '*';
+ }
+
+ return CommandForShortcut( shortcut, aContext, aKey.iModifiers );
+ }
+
+
+// ----------------------------------------------------------------------------
+TInt CFSEmailUiShortcutBinding::CommandForShortcut( TText aShortcut,
+ TShortcutContext aContext,
+ TUint32 aModifiers )
+ {
+ FUNC_LOG;
+ TInt command = KErrNotFound;
+
+ if ( aShortcut ) // value 0 is used as mark for no shortcut
+ {
+ TInt count = 0;
+ const TShortcutBinding* bindings = NULL;
+
+ // Select appropriate binding table
+ GetBindingsForContext( bindings, count, aContext );
+
+ // Search command from the binding table
+ for ( TInt i=0 ; i<count && command==KErrNotFound ; ++i )
+ {
+ TBool isItutShortcut = ( aShortcut == bindings[i].iItutShortcut );
+
+ TBool isQwertyShortcut = ( aShortcut == bindings[i].iQwertyShortcut );
+ // Check the modifier keys for the QWERTY shortcut
+ if ( isQwertyShortcut )
+ {
+ TUint32 matchingModifiers = ( aModifiers & bindings[i].iQwertyModifiers );
+ if ( matchingModifiers != bindings[i].iQwertyModifiers )
+ {
+ isQwertyShortcut = EFalse;
+ }
+ }
+
+ if ( isItutShortcut || isQwertyShortcut )
+ {
+ command = bindings[i].iCommandId;
+ }
+ }
+ }
+
+ return command;
+ }
+
+
+// ----------------------------------------------------------------------------
+TText CFSEmailUiShortcutBinding::ShortcutForCommand( TInt aCommandId,
+ TShortcutContext aContext,
+ TBool aQwertyMode )
+ {
+ FUNC_LOG;
+ TText shortcut = 0;
+ TInt count = 0;
+ const TShortcutBinding* bindings = NULL;
+
+ // Select appropriate binding table
+ GetBindingsForContext( bindings, count, aContext );
+
+ // Search shortcut from the binding table
+ for ( TInt i=0 ; i<count && !shortcut ; ++i )
+ {
+ if ( aCommandId == bindings[i].iCommandId )
+ {
+ if ( aQwertyMode )
+ {
+ // Only single-key shortcuts are supported here.
+ if ( !bindings[i].iQwertyModifiers )
+ {
+ shortcut = bindings[i].iQwertyShortcut;
+ }
+ }
+ else
+ {
+ shortcut = bindings[i].iItutShortcut;
+ }
+ }
+ }
+
+ return shortcut;
+ }
+
+
+// ----------------------------------------------------------------------------
+void CFSEmailUiShortcutBinding::AppendShortcutHintsL(
+ CEikMenuPane& aMenuPane,
+ TShortcutContext aContext ) const
+ {
+ FUNC_LOG;
+ TKeyBoardType kbType = KeyBoardType();
+ TBool isQwerty =
+ ( kbType != ENoKeyboard && kbType != EItutKeyPad && kbType != EHalfQwerty );
+
+ // Browse through the commands in the menu pane and append shortcuts
+ // where available.
+ TInt count = aMenuPane.NumberOfItemsInPane();
+
+ for ( TInt i = 0; i < count; ++i )
+ {
+ CEikMenuPaneItem::SData& itemData = aMenuPane.ItemDataByIndexL( i );
+ TText hint = ShortcutForCommand(
+ itemData.iCommandId, aContext, isQwerty );
+ if ( hint )
+ {
+ AppendHintToCaption( itemData.iText, hint );
+ }
+ }
+ }
+
+
+// ----------------------------------------------------------------------------
+CFSEmailUiShortcutBinding::CFSEmailUiShortcutBinding()
+ {
+ FUNC_LOG;
+ }
+
+
+// ----------------------------------------------------------------------------
+void CFSEmailUiShortcutBinding::ConstructL()
+ {
+ FUNC_LOG;
+ iPtiEngine = CPtiEngine::NewL();
+
+ // Always use English mappings for QWERTY keyboards. This is because it is not
+ // certain that the mappings of the current language hold latin alphabet at all.
+ // English should be available in all device variants as an optional input language.
+ CPtiCoreLanguage* lang =
+ static_cast<CPtiCoreLanguage*>( iPtiEngine->GetLanguage( ELangEnglish ) );
+ if (lang)
+ {
+ iQwertyMappings = static_cast<CPtiKeyMappings*>( lang->GetQwertyKeymappings() );
+#ifdef RD_INTELLIGENT_TEXT_INPUT
+ iHalfQwertyMappings = static_cast<CPtiKeyMappings*>( lang->GetHalfQwertyKeymappings() );
+#endif // RD_INTELLIGENT_TEXT_INPUT
+ }
+ lang = NULL; // owned by iPtiEngine
+
+
+ if ( !iQwertyMappings && !iHalfQwertyMappings )
+ {
+ // In non-QWERTY devices we can free up PtiEngine right away, because
+ // it is not needed anyway.
+ delete iPtiEngine;
+ iPtiEngine = NULL;
+ }
+
+ iKbLayoutProperty.Attach( KCRUidAvkon, KAknKeyBoardLayout );
+ }
+
+
+// ----------------------------------------------------------------------------
+CFSEmailUiShortcutBinding::TKeyBoardType CFSEmailUiShortcutBinding::KeyBoardType() const
+ {
+ FUNC_LOG;
+ TInt keyboardType = ENoKeyboard;
+
+ // RProperty does not define Get() as a constant function. This is
+ // probably just a flaw in the interface. Cast away constness to
+ // circumvent this.
+ RProperty& kbProperty = const_cast<RProperty&>(iKbLayoutProperty);
+ kbProperty.Get( keyboardType );
+ return static_cast<TKeyBoardType>( keyboardType );
+ }
+
+
+// ----------------------------------------------------------------------------
+void CFSEmailUiShortcutBinding::GetBindingsForContext( const TShortcutBinding*& aBindingArray,
+ TInt& aBindingCount,
+ TShortcutContext aContext )
+ {
+ FUNC_LOG;
+ switch (aContext)
+ {
+ case EContextMailList:
+ {
+ aBindingCount = sizeof(KMailListShortcuts) / sizeof(TShortcutBinding);
+ aBindingArray = KMailListShortcuts;
+ }
+ break;
+
+ case EContextSearchResults:
+ {
+ aBindingCount = sizeof(KSearchResultsShortcuts) / sizeof(TShortcutBinding);
+ aBindingArray = KSearchResultsShortcuts;
+ }
+ break;
+
+ case EContextMailViewer:
+ {
+ aBindingCount = sizeof(KMailViewerShortcuts) / sizeof(TShortcutBinding);
+ aBindingArray = KMailViewerShortcuts;
+ }
+ break;
+
+ case EContextHtmlViewer:
+ {
+ aBindingCount = sizeof(KHtmlViewerShortcuts) / sizeof(TShortcutBinding);
+ aBindingArray = KHtmlViewerShortcuts;
+ }
+ break;
+
+ case EContextMailDetails:
+ case EContextFolderList:
+ case EContextAttachmentList:
+ case EContextDownloadManager:
+ {
+ aBindingCount = sizeof(KGenericListShortcuts) / sizeof(TShortcutBinding);
+ aBindingArray = KGenericListShortcuts;
+ }
+ break;
+
+ case EContextMainGrid:
+ {
+ aBindingCount = sizeof(KMainGridShortcuts) / sizeof(TShortcutBinding);
+ aBindingArray = KMainGridShortcuts;
+ }
+ break;
+
+ case EContextSendAttachmentList:
+ {
+ aBindingCount = sizeof(KSendAttachmentListShortcuts) / sizeof(TShortcutBinding);
+ aBindingArray = KSendAttachmentListShortcuts;
+ }
+ break;
+
+ case EContextSettings:
+ {
+ aBindingCount = sizeof(KSettingsShortcuts) / sizeof(TShortcutBinding);
+ aBindingArray = KSettingsShortcuts;
+ }
+ break;
+
+ default:
+ {
+ Panic( EFSEmailUiUnexpectedValue );
+ }
+ break;
+ }
+ }
+
+
+// ----------------------------------------------------------------------------
+void CFSEmailUiShortcutBinding::AppendHintToCaption( TDes& aCaption,
+ TText aHint )
+ {
+ FUNC_LOG;
+ static const TInt KHintLength = 4; // e.g. " [X]"
+ _LIT( KLeadingSeparator, " [" );
+ _LIT( KTailingSeparator, "]" );
+
+ if ( aCaption.MaxLength() >= aCaption.Length() + KHintLength )
+ {
+ aCaption.Append( KLeadingSeparator );
+ aCaption.Append( aHint );
+ aCaption.Append( KTailingSeparator );
+ }
+ }
+