quick_recipes (779892), страница 21
Текст из файла (страница 21)
It is not necessary to call CompactL() after each deletion, but agood idea to do so after you have removed a few.4.2.3.5Modify a Calendar EventAmount of time required: 15 minutesLocation of example code: \PIM\AgendaUpdateRequired library(s): calinterimapi.libRequired header file(s): calsession.h, calentryview.h,calprogresscallback.hRequired platform security capability(s): ReadUserData WriteUserDataProblem: You want to reschedule an event to start at a new time.Solution: The first step is to open the Calendar database so it can bemodified. Modifying the content of one item is not complex in itself.Think of it as executing an SQL UPDATE statement.#include <calsession.h> // and link to calinterimapi.lib#include <calentryview.h>#include <calprogresscallback.h>class CCalWrite : public CBase, public MCalProgressCallBack{public:static CCalWrite* NewL();∼CCalWrite(); // to delete iCalSes and iCalViewvoid RescheduleL(TCalLocalUid aEventId, TTime aNewTimeUtc);public: // from MCalProgressCallBackvoid Progress(TInt){};116SYMBIAN C++ RECIPESvoid Completed(TInt){};TBool NotifyProgress(){return EFalse;};private:void ConstructL();private:CCalSession* iCalSes;CCalEntryView* iCalView;};// You need an opened calendar database (often this// is the default calendar database on the phone).// You should always assume that it may not have been created before.void CCalWrite::ConstructL(){iCalSes = CCalSession::NewL();const TDesC& name = iCalSes->DefaultFileNameL();TRAPD(error, iCalSes->CreateCalFileL(name));if (KErrAlreadyExists != error){// Leave if an error occurs (but not if it already exists)User::LeaveIfError(error);}iCalSes->OpenL(KNullDesC());// Create a calendar viewiCalView = CCalEntryView::NewL(*iCalSes, *this);}void CCalWrite::RescheduleL(TCalLocalUid aEventId, TTime aNewTimeUtc){// find the eventCCalEntry* entry = iCalView->FetchL(aEventId);if (NULL == entry){User::Leave(KErrNotFound);}else{// Reschedule it, but keep original duration.CleanupStack::PushL(entry);TCalTime start = entry->StartTimeL();TCalTime end = entry->EndTimeL();TTime startUtc = start.TimeUtcL();TTime endUtc = end.TimeUtcL();TTimeIntervalMicroSeconds duration =endUtc.MicroSecondsFrom(startUtc);start.SetTimeUtcL(aNewTimeUtc);end.SetTimeUtcL(aNewTimeUtc + duration);entry->SetStartAndEndTimeL(start, end);// Commit it to the databaseRPointerArray<CCalEntry> array;CleanupClosePushL(array);array.AppendL(entry);////////We are doing something weird here because we aredealing with only one entry.We don’t transfer ownership of entryto the array.
When array is closedCONTACTS AND CALENDAR117// it won’t delete entry.// So we keep entry on the cleanup stack.TInt success=0;// Update the viewiCalView->UpdateL(array, success);if (success < 1){// Partial success is possible when updating// several calendar entries at once.User::Leave(KErrGeneral);}CleanupStack::PopAndDestroy(2, entry); // array, entry}}What may go wrong when you do this: There are some modificationsyou can apply to a CCalEntry that CCalEntryView::UpdateL()may not fully commit to the Calendar database. You will need toexperiment a little, and you may have to write a method that willcopy an entry, modify the copy, store the new entry and delete the oldone from the Calendar database.
At this point, atomicity of updatesbecomes an issue.4.2.3.6Add a New Calendar EventAmount of time required: 30 minutesLocation of example code: \PIM\AgendaAddRequired library(s): calinterimapi.libRequired header file(s): calsession.h, calentryview.h,calprogresscallback.hRequired platform security capability(s): ReadUserData WriteUserDataProblem: You want to add a new appointment to your calendar.Solution: You will need a GUID, which is a globally unique string, topermanently identify your calendar entry. S60 provides an API for thispurpose (CalenInterimUtils::GlobalUidL()) in caleninterimutils.h (you need to link to caleninterimutils.lib), but it isnot available to UIQ developers.
RFC 2445 (www.faqs.org/rfcs/rfc2445.html) gives some recommendations on how to obtain a globally uniqueID in section 4.8.4.7 (search for ‘Unique Identifier’).Since there is no enforced standard in the matter, there is technicallyno way to make sure any string you come up with won’t be duplicatedby another application, but there are a few basic techniques that can beused to greatly reduce the probability of a conflict.118SYMBIAN C++ RECIPESHere are a few useful techniques that can be used to create a GUID:• Use your application’s Symbian Signed UID and your company name.• Use random number generation.• Use the current time (introduce a delay between the creation of twoGUIDs).• Use a dedicated GUID-generation server, either remote or local.• Use the device’s Bluetooth MAC address, its phone and IMEI number(there may be a cost to the user if you open a network connection).• Use a cryptographic hash and your public key.It is recommended that you use a combination of several of thesetechniques.In order to add a new calendar event, you must first open the databaseas described in Recipe 4.2.3.1:#include <calsession.h> // and link to calinterimapi.lib#include <calentryview.h>#include <calprogresscallback.h>class CCalWrite : public CBase, public MCalProgressCallBack{public:static CCalWrite* NewL();∼CCalWrite(); // to delete iCalSes and iCalViewvoid AddNewL(TTime aStartUtc, const TDesC& aDescription);public: // from MCalProgressCallBackvoid Progress(TInt){};void Completed(TInt){};TBool NotifyProgress(){return EFalse;};private:void ConstructL();HBufC8* MakeGuidLC();private:CCalSession* iCalSes;CCalEntryView* iCalView;};void CCalWrite::AddNewL(TTime aStartUtc, const TDesC& aDescription){// create a new entryHBufC8* guid = MakeGuidLC();CCalEntry* entry = CCalEntry::NewL(CCalEntry::EAppt, guid,CCalEntry::EMethodNone, 0);CleanupStack::Pop(guid);CleanupStack::PushL(entry);// set some valuesTCalTime start;start.SetTimeUtcL(aStartUtc);TTime endUtc = aStartUtc;CONTACTS AND CALENDAR119endUtc += TTimeIntervalHours(1);TCalTime end;end.SetTimeUtcL(endUtc);entry->SetStartAndEndTimeL(start, end);entry->SetDescriptionL(aDescription);// add the entry to the databaseRPointerArray<CCalEntry> array;CleanupClosePushL(array);array.AppendL(entry);// Don’t transfer ownership of entry to array.TInt success = 0;iCalView->StoreL(array, success);if (success < 1){User::Leave(KErrGeneral);}CleanupStack::PopAndDestroy(2, entry); // array, entry}////////A simplified version of a unique Id generator.It transfers the ownership of its result to the caller.You can roll your own or useCalenInterimUtils::GlobalUidL() in S60 codeconst TInt KMaxGuidSize = 64;_LIT(KDateFormat,"%F%Y%M%D");_LIT(KTimeSeparator,"T");_LIT(KTimeFormat,"%F%H%T%S");_LIT(KTimeDivider,"-");_LIT(KAddress,"0x2000DF18_QuickRecipes@SymbianPress.com");HBufC8* CCalWrite::MakeGuidLC(){TTime now;now.UniversalTime();TBuf<KMaxGuidSize> time;now.FormatL(time,KTimeFormat);TBuf<KMaxGuidSize> date;now.FormatL(date,KDateFormat);HBufC8* guid = HBufC8::NewLC(KMaxGuidSize);TPtr8 guidPtr = guid->Des();guidPtr.Zero();guidPtr.Append(date);guidPtr.Append(KTimeSeparator());guidPtr.Append(time);guidPtr.Append(KTimeDivider());guidPtr.Append(KAddress());return guid;}What may go wrong when you do this: Given that you may be writingyour own GUID generation function, you need to deal with the fact120SYMBIAN C++ RECIPESthat CCalEntry::NewL() could fail if another item already has thesame GUID.You also need to be careful with the amount of data you append tothe GUID descriptor or you will get a descriptor overflow panic.4.2.3.7Remove a Calendar EventAmount of time required: 10 minutesLocation of example code: \PIM\AgendaRemoveRequired library(s): calinterimapi.libRequired header file(s): calsession.h, calentryview.h,calprogresscallback.hRequired platform security capability(s): ReadUserData WriteUserDataProblem: You want to delete an event from the Calendar database.Solution: You must first open the database as you did in Recipe 4.2.3.1:#include#include#include#include#include<calsession.h> // and link to calinterimapi.lib<caltime.h><calentryview.h><calentry.h><calprogresscallback.h>class CCalWrite : public CBase, public MCalProgressCallBack{public:static CCalWrite* NewL();∼CCalWrite(); // to delete iCalSes and iCalViewvoid RemoveL(TCalLocalUid aEventId);public: // from MCalProgressCallBackvoid Progress(TInt){};void Completed(TInt){};TBool NotifyProgress(){return EFalse;};private:void ConstructL();private:CCalSession* iCalSes;CCalEntryView* iCalView;};void CCalWrite::RemoveL(TCalLocalUid aEventId){RArray<TCalLocalUid> array;CleanupClosePushL(array);array.AppendL(aEventId);TInt success = 0;iCalView->DeleteL(array, success);// no real need to deal with failure hereCleanupStack::PopAndDestroy(&array);}CONTACTS AND CALENDAR1214.2.4 Intermediate Recipes4.2.4.1Sort ContactsAmount of time required: 40 minutesLocation of example code: \PIM\ContactSortRequired library(s): cntmodel.libRequired header file(s): cntdb.h, cntitem.h, cntfield.h,cntdef.hRequired platform security capability(s): ReadUserData WriteUserDataProblem: You want to sort the contacts in the database, by name, inalphabetical order.Solution: What you want is a collection of TContactItemId objects.The elements are sorted according to your criteria.