menucontentsrv/src/menuitem.cpp
changeset 0 79c6a41cd166
equal deleted inserted replaced
-1:000000000000 0:79c6a41cd166
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 // INCLUDE FILES
       
    19 
       
    20 #include <s32strm.h>
       
    21 
       
    22 #include "mcsmenuitem.h"
       
    23 #include "menuitemattr.h"
       
    24 #include "menubuf.h"
       
    25 #include "mcsmenu.h"
       
    26 #include "menuclientoperation.h"
       
    27 #include "menucompletedoperation.h"
       
    28 
       
    29 
       
    30 NONSHARABLE_CLASS( CMenuItem::TData )
       
    31     {
       
    32 
       
    33 public:     // construction
       
    34 
       
    35     TData( RMenu& aMenu ): iMenu( aMenu ) {}
       
    36 
       
    37 public:     // data
       
    38 
       
    39     RMenu& iMenu;
       
    40     TMenuItem iHdr;
       
    41     TUint32 iOrigFlags;
       
    42     RMenuItemAttrArray iAttrCache;
       
    43     TInt iInsertBefore;
       
    44 
       
    45     };
       
    46 
       
    47 // ================= LOCAL FUNCTIONS =======================
       
    48 
       
    49 /**
       
    50 * Check if this is a valid attribute name. Leave with KErrArgument if not.
       
    51 * We don't accept whitespace or exotic characters anywhere, and also
       
    52 * forbid setting reserved attribute "flags".
       
    53 * The Engine also checks this, but it's more friendly to leave on client
       
    54 * side too - no point in attempting something that we know will fail.
       
    55 */
       
    56 LOCAL_C void CheckAttrNameL( const TDesC& aAttrName )
       
    57     {
       
    58     if ( !aAttrName.Length() )
       
    59         {
       
    60         User::Leave( KErrArgument );
       
    61         }
       
    62     if ( KMenuAttrFlags() == aAttrName || KMenuAttrId() == aAttrName )
       
    63         {
       
    64         // Internal attributes, disallow.
       
    65         User::Leave( KErrArgument );
       
    66         }
       
    67     for ( TInt i = 0; i < aAttrName.Length(); i++ )
       
    68         {
       
    69         const TChar c = aAttrName[i];
       
    70         // Allowed set of characters
       
    71         if ( !c.IsAlphaDigit() &&
       
    72              '_' != c &&
       
    73              '-' != c &&
       
    74              ':' != c )
       
    75             {
       
    76             User::Leave( KErrArgument );
       
    77             }
       
    78         }
       
    79     }
       
    80 
       
    81 
       
    82 // ================= MEMBER FUNCTIONS =======================
       
    83 
       
    84 // ---------------------------------------------------------
       
    85 // TMenuItem::ExternalizeL
       
    86 // ---------------------------------------------------------
       
    87 //
       
    88 void TMenuItem::ExternalizeL( RWriteStream& aStream ) const
       
    89     {
       
    90     aStream.WriteInt32L( iId );
       
    91     aStream.WriteInt32L( iParent );
       
    92     aStream.WriteUint32L( iFlags );
       
    93     aStream.WriteInt32L( iType.Length() );
       
    94     aStream.WriteL( iType );
       
    95     }
       
    96 
       
    97 // ---------------------------------------------------------
       
    98 // TMenuItem::InternalizeL
       
    99 // ---------------------------------------------------------
       
   100 //
       
   101 void TMenuItem::InternalizeL( RReadStream& aStream )
       
   102     {
       
   103     iId = aStream.ReadInt32L();
       
   104     iParent = aStream.ReadInt32L();
       
   105     iFlags = aStream.ReadUint32L();
       
   106     TInt len = aStream.ReadInt32L();
       
   107     aStream.ReadL( iType, len );
       
   108     }
       
   109 
       
   110 // ================= MEMBER FUNCTIONS =======================
       
   111 
       
   112 // ---------------------------------------------------------
       
   113 // CMenuItem::~CMenuItem
       
   114 // ---------------------------------------------------------
       
   115 //
       
   116 EXPORT_C CMenuItem::~CMenuItem()
       
   117     {
       
   118     if ( iData )
       
   119         {
       
   120         iData->iAttrCache.ResetAndDestroy();
       
   121         delete iData;
       
   122         }
       
   123     }
       
   124 
       
   125 // ---------------------------------------------------------
       
   126 // CMenuItem::CreateL
       
   127 // ---------------------------------------------------------
       
   128 //
       
   129 EXPORT_C CMenuItem* CMenuItem::CreateL
       
   130 ( RMenu& aMenu, const TDesC& aType, TInt aFolder, TInt aInsertBefore )
       
   131     {
       
   132     if ( KMenuTypeData() == aType )
       
   133         {
       
   134         // Internal type, disallow.
       
   135         User::Leave( KErrArgument );
       
   136         }
       
   137     // Item created locally, no IPC.
       
   138     CMenuItem* item = NewLC( aMenu );
       
   139     item->iData->iHdr.SetType( aType );
       
   140     item->iData->iHdr.SetParent( aFolder );
       
   141     item->iData->iOrigFlags = item->iData->iHdr.Flags();
       
   142     item->iData->iInsertBefore = aInsertBefore;
       
   143     CleanupStack::Pop( item );
       
   144     return item;
       
   145     }
       
   146 
       
   147 // ---------------------------------------------------------
       
   148 // CMenuItem::OpenL
       
   149 // ---------------------------------------------------------
       
   150 //
       
   151 EXPORT_C CMenuItem* CMenuItem::OpenL( RMenu& aMenu, TInt aId )
       
   152     {
       
   153     // Get header from server, IPC needed.
       
   154     return OpenL( aMenu, aMenu.GetHdrL( aId ) );
       
   155     }
       
   156 
       
   157 // ---------------------------------------------------------
       
   158 // CMenuItem::OpenL
       
   159 // ---------------------------------------------------------
       
   160 //
       
   161 EXPORT_C CMenuItem* CMenuItem::OpenL( RMenu& aMenu, const TMenuItem& aHdr )
       
   162     {
       
   163     // We accept the existing header, no IPC needed.
       
   164     CMenuItem* item = NewLC( aMenu );
       
   165     item->iData->iHdr = aHdr;
       
   166     item->iData->iOrigFlags = item->iData->iHdr.Flags();
       
   167     CleanupStack::Pop( item );
       
   168     return item;
       
   169     }
       
   170 
       
   171 // ---------------------------------------------------------
       
   172 // CMenuItem::CMenuItem
       
   173 // ---------------------------------------------------------
       
   174 //
       
   175 CMenuItem::CMenuItem()
       
   176     {
       
   177     }
       
   178 
       
   179 // ---------------------------------------------------------
       
   180 // CMenuItem::NewLC
       
   181 // ---------------------------------------------------------
       
   182 //
       
   183 CMenuItem* CMenuItem::NewLC( RMenu& aMenu )
       
   184     {
       
   185     CMenuItem* item = new (ELeave) CMenuItem();
       
   186     CleanupStack::PushL( item );
       
   187     item->iData = new (ELeave) CMenuItem::TData( aMenu );
       
   188     return item;
       
   189     }
       
   190 
       
   191 // ---------------------------------------------------------
       
   192 // CMenuItem::Id
       
   193 // ---------------------------------------------------------
       
   194 //
       
   195 EXPORT_C TInt CMenuItem::Id() const
       
   196     {
       
   197     return iData->iHdr.Id();
       
   198     }
       
   199 
       
   200 // ---------------------------------------------------------
       
   201 // CMenuItem::Parent
       
   202 // ---------------------------------------------------------
       
   203 //
       
   204 EXPORT_C TInt CMenuItem::Parent() const
       
   205     {
       
   206     return iData->iHdr.Parent();
       
   207     }
       
   208 
       
   209 // ---------------------------------------------------------
       
   210 // CMenuItem::Flags
       
   211 // ---------------------------------------------------------
       
   212 //
       
   213 EXPORT_C TUint32 CMenuItem::Flags() const
       
   214     {
       
   215     return iData->iHdr.Flags();
       
   216     }
       
   217 
       
   218 // ---------------------------------------------------------
       
   219 // CMenuItem::SetFlags
       
   220 // ---------------------------------------------------------
       
   221 //
       
   222 EXPORT_C void CMenuItem::SetFlags( TUint32 aMask, TBool aOn )
       
   223     {
       
   224     if ( aOn )
       
   225         {
       
   226         iData->iHdr.SetFlags( iData->iHdr.Flags() | aMask );
       
   227         }
       
   228     else
       
   229         {
       
   230         iData->iHdr.SetFlags( iData->iHdr.Flags() & ~aMask );
       
   231         }
       
   232     }
       
   233 
       
   234 // ---------------------------------------------------------
       
   235 // CMenuItem::Type
       
   236 // ---------------------------------------------------------
       
   237 //
       
   238 EXPORT_C TPtrC CMenuItem::Type() const
       
   239     {
       
   240     return iData->iHdr.Type();
       
   241     }
       
   242 
       
   243 // ---------------------------------------------------------
       
   244 // CMenuItem::GetAttributeL
       
   245 // ---------------------------------------------------------
       
   246 //
       
   247 EXPORT_C TPtrC CMenuItem::GetAttributeL
       
   248 ( const TDesC& aAttrName, TBool& aAttrExists )
       
   249     {
       
   250     CheckAttrNameL( aAttrName );
       
   251     CMenuItemAttr* attr = NULL;
       
   252     TInt i = iData->iAttrCache.Find( aAttrName );
       
   253     if ( KErrNotFound == i )
       
   254         {
       
   255         attr = CMenuItemAttr::NewLC( aAttrName );
       
   256         HBufC* value;
       
   257         if( iData->iHdr.Id() )
       
   258             {
       
   259             value = iData->iMenu.GetAttributeL( Id(), aAttrName );
       
   260             }
       
   261            else
       
   262             {
       
   263             value = NULL;
       
   264             }
       
   265 
       
   266         attr->SetValue( value ); // Takes ownership.
       
   267         attr->SetChanged( EFalse ); // New in cache -> not changed.
       
   268         iData->iAttrCache.AppendL( attr );
       
   269         CleanupStack::Pop( attr ); // Now owned by the cache.
       
   270         }
       
   271     else
       
   272         {
       
   273         attr = iData->iAttrCache[i];
       
   274         }
       
   275     __ASSERT_DEBUG( attr, User::Invariant() ); // Should be cached by now.
       
   276     if ( attr->Value() )
       
   277         {
       
   278         aAttrExists = ETrue;
       
   279         return *attr->Value();
       
   280         }
       
   281     aAttrExists = EFalse;
       
   282     return KNullDesC();
       
   283     }
       
   284 
       
   285 // ---------------------------------------------------------
       
   286 // CMenuItem::GetAttributeL
       
   287 // ---------------------------------------------------------
       
   288 //
       
   289 EXPORT_C void CMenuItem::GetAttributeListL( RArray<TAttributeName>& aList )
       
   290     {
       
   291     iData->iMenu.GetAttributeListL( Id(), aList );
       
   292     }
       
   293 
       
   294 // ---------------------------------------------------------
       
   295 // CMenuItem::SetAttributeL
       
   296 // ---------------------------------------------------------
       
   297 //
       
   298 EXPORT_C void CMenuItem::SetAttributeL
       
   299 ( const TDesC& aAttrName, const TDesC& aAttrValue )
       
   300     {
       
   301     CheckAttrNameL( aAttrName );
       
   302     CMenuItemAttr* attr = NULL;
       
   303     TInt i = iData->iAttrCache.Find( aAttrName );
       
   304     if ( KErrNotFound == i )
       
   305         {
       
   306         attr = CMenuItemAttr::NewLC( aAttrName );
       
   307         attr->SetChanged( ETrue ); // Changed.
       
   308         iData->iAttrCache.AppendL( attr );
       
   309         CleanupStack::Pop( attr ); // Now owned by the cache.
       
   310         }
       
   311     else
       
   312         {
       
   313         attr = iData->iAttrCache[i];
       
   314         }
       
   315     __ASSERT_DEBUG( attr, User::Invariant() ); // Should be cached by now.
       
   316     attr->SetValue( aAttrValue.AllocL() ); // Sets changed bit as needed.
       
   317     }
       
   318 
       
   319 // ---------------------------------------------------------
       
   320 // CMenuItem::RemoveAttributeL
       
   321 // ---------------------------------------------------------
       
   322 //
       
   323 EXPORT_C void CMenuItem::RemoveAttributeL( const TDesC& aAttrName )
       
   324     {
       
   325     CheckAttrNameL( aAttrName );
       
   326     CMenuItemAttr* attr = NULL;
       
   327     TInt i = iData->iAttrCache.Find( aAttrName );
       
   328     if ( KErrNotFound == i )
       
   329         {
       
   330         attr = CMenuItemAttr::NewLC( aAttrName );
       
   331         attr->SetChanged( ETrue ); // Changed.
       
   332         iData->iAttrCache.AppendL( attr );
       
   333         CleanupStack::Pop( attr ); // Now owned by the cache.
       
   334         }
       
   335     else
       
   336         {
       
   337         attr = iData->iAttrCache[i];
       
   338         }
       
   339     __ASSERT_DEBUG( attr, User::Invariant() ); // Should be cached by now.
       
   340     attr->SetValue( NULL ); // Sets changed bit as needed.
       
   341     }
       
   342 
       
   343 // ---------------------------------------------------------
       
   344 // CMenuItem::SaveL
       
   345 // ---------------------------------------------------------
       
   346 //
       
   347 EXPORT_C CMenuOperation* CMenuItem::SaveL( TRequestStatus& aStatus )
       
   348     {
       
   349     if ( !Changed() )
       
   350         {
       
   351         return CMenuCompletedOperation::NewL
       
   352             ( iData->iMenu, CActive::EPriorityStandard, aStatus, KErrNone );
       
   353         }
       
   354     if ( Id() )
       
   355         {
       
   356         return UpdateL( aStatus );
       
   357         }
       
   358     return AddL( aStatus );
       
   359     }
       
   360 
       
   361 // ---------------------------------------------------------
       
   362 // CMenuItem::HandleCommandL
       
   363 // ---------------------------------------------------------
       
   364 //
       
   365 EXPORT_C CMenuOperation* CMenuItem::HandleCommandL(
       
   366         const TDesC8& aCommand,
       
   367         const TDesC8& aParams,
       
   368         TRequestStatus& aStatus )
       
   369     {
       
   370     return iData->iMenu.HandleCommandL( *this, aCommand, aParams, aStatus );
       
   371     }
       
   372 
       
   373 // ---------------------------------------------------------
       
   374 // CMenuItem::AddL
       
   375 // ---------------------------------------------------------
       
   376 //
       
   377 CMenuOperation* CMenuItem::AddL( TRequestStatus& aStatus )
       
   378     {
       
   379     __ASSERT_DEBUG( Changed(), User::Invariant() );
       
   380     __ASSERT_DEBUG( !Id(), User::Invariant() );
       
   381     RMenuBuf buf;
       
   382     User::LeaveIfError( buf.Open( iData->iMenu ) );
       
   383     CleanupClosePushL( buf );
       
   384     RWriteStream stream( &buf );
       
   385     // Flags.
       
   386     stream.WriteUint32L( iData->iHdr.Flags() );
       
   387     __ASSERT_DEBUG( 0 == iData->iOrigFlags, User::Invariant() ); // New item!
       
   388     // Attributes.
       
   389     __ASSERT_DEBUG( iData->iAttrCache.Count() == \
       
   390         iData->iAttrCache.CountChanged(), User::Invariant() ); // New item!
       
   391     iData->iAttrCache.ExternalizeL( stream );
       
   392     // Parent folder and insertion point.
       
   393     stream.WriteInt32L( Parent() );
       
   394     stream.WriteInt32L( iData->iInsertBefore );
       
   395     stream.CommitL();
       
   396     CMenuClientOperation* op = new (ELeave) CMenuClientOperation
       
   397         ( iData->iMenu, CActive::EPriorityStandard, aStatus );
       
   398     CleanupStack::PushL( op );
       
   399     TInt id = op->AddL( Type(), buf );
       
   400     __ASSERT_DEBUG( id, User::Invariant() );
       
   401     iData->iHdr.SetId( id ); // Write ID back.
       
   402     CleanupStack::Pop( op );
       
   403     CleanupStack::PopAndDestroy( &buf );
       
   404     ClearChanged();
       
   405     return op;
       
   406     }
       
   407 
       
   408 // ---------------------------------------------------------
       
   409 // CMenuItem::UpdateL
       
   410 // ---------------------------------------------------------
       
   411 //
       
   412 CMenuOperation* CMenuItem::UpdateL( TRequestStatus& aStatus )
       
   413     {
       
   414     __ASSERT_DEBUG( Changed(), User::Invariant() );
       
   415     __ASSERT_DEBUG( Id(), User::Invariant() );
       
   416     RMenuBuf buf;
       
   417     User::LeaveIfError( buf.Open( iData->iMenu ) );
       
   418     CleanupClosePushL( buf );
       
   419     RWriteStream stream( &buf );
       
   420     // Flags and flag changes (small -> always sent).
       
   421     stream.WriteUint32L( iData->iHdr.Flags() );
       
   422     stream.WriteUint32L( iData->iOrigFlags ^ iData->iHdr.Flags() );
       
   423     // Changed attributes.
       
   424     iData->iAttrCache.ExternalizeChangesL( stream );
       
   425     stream.CommitL();
       
   426     CMenuClientOperation* op = new (ELeave) CMenuClientOperation
       
   427         ( iData->iMenu, CActive::EPriorityStandard, aStatus );
       
   428     CleanupStack::PushL( op );
       
   429     op->UpdateL( Id(), buf );
       
   430     CleanupStack::Pop( op );
       
   431     CleanupStack::PopAndDestroy( &buf );
       
   432     ClearChanged();
       
   433     return op;
       
   434     }
       
   435 
       
   436 // ---------------------------------------------------------
       
   437 // CMenuItem::Changed
       
   438 // ---------------------------------------------------------
       
   439 //
       
   440 TBool CMenuItem::Changed() const
       
   441     {
       
   442     return !iData->iHdr.Id() || // New item
       
   443            iData->iHdr.Flags() != iData->iOrigFlags || // Changed flags
       
   444            iData->iAttrCache.CountChanged(); // Changed attributes
       
   445     }
       
   446 
       
   447 // ---------------------------------------------------------
       
   448 // CMenuItem::ClearChanged
       
   449 // ---------------------------------------------------------
       
   450 //
       
   451 void CMenuItem::ClearChanged()
       
   452     {
       
   453     iData->iAttrCache.ClearChanged();
       
   454     iData->iOrigFlags = iData->iHdr.Flags();
       
   455     }
       
   456 
       
   457 
       
   458 // ---------------------------------------------------------
       
   459 // CMenuItem::RunningStatus
       
   460 // ---------------------------------------------------------
       
   461 //
       
   462 EXPORT_C TBool CMenuItem::RunningStatusL()
       
   463     {
       
   464     TBool ret(EFalse);
       
   465     HBufC* value;
       
   466     value = iData->iMenu.GetAttributeL( Id(), KRunningStatus );
       
   467     if( value )
       
   468     	{
       
   469     	ret = ETrue;
       
   470     	}
       
   471     delete value;
       
   472     return ret;
       
   473     }
       
   474 
       
   475