summaryrefslogtreecommitdiffstats
path: root/plugins/contacts/symbian/contactsmodel/cntplsql/src/cidlecontactsorter.cpp
blob: af4adae85aa046bf4a6d8a3f3fef8847902a58fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
/*
* Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
* Contact: http://www.qt-project.org/legal
* 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: 
*
*/


/**
 @file
 @internalComponent
 @released
*/

#include "cviewcontactmanager.h"
#include "cntviewprivate.h"
#include "cntstd.h"

/*
 * Factory constructor.
 */
CIdleContactSorter* CIdleContactSorter::NewL(MContactViewSortObserver& aObserver, MLplPersistenceLayerFactory& aFactory, TContactViewPreferences aRequestedViewPrefs)
	{
	CIdleContactSorter* self = new (ELeave) CIdleContactSorter(aObserver, aRequestedViewPrefs);
	CleanupStack::PushL(self);
	self->ConstructL(aFactory);
	CleanupStack::Pop(self);
	return self;
	}

	
/* Constructor */
CIdleContactSorter::CIdleContactSorter(MContactViewSortObserver& aObserver, TContactViewPreferences aRequestedViewPrefs) 
: CAsyncOneShot(CActive::EPriorityLow), 
  iSortObserver(aObserver), 
  iRequestedView(aRequestedViewPrefs)
    {
    }

	
/* 
 * Second phase construction.
 * Copy the View's requested preferences, get link to ICC phonebook watcher
 */
void CIdleContactSorter::ConstructL(MLplPersistenceLayerFactory& aFactory)
	{
	// is ICC phonebook sync expected?
	if (iRequestedView & (EICCEntriesOnly | EICCEntriesAndContacts))
		{
		iPhbkSyncWatcher = CContactPhbkSyncWatcher::NewL(aFactory.GetContactSynchroniserL(KMaxTUint32));

		// observe ICC sync events
		iPhbkSyncWatcher->AddPhbkObserverL(*this);
		}
	}
	
	
/* Destructor */
CIdleContactSorter::~CIdleContactSorter()
	{
	Cancel();

	if (iPhbkSyncWatcher)
		{
		iPhbkSyncWatcher->RemovePhbkObserver(*this);
		if (iPhbkSyncWatcher->ObserverCount() == 0)
			{
			delete iPhbkSyncWatcher;
			}
		} //if (iPhbkSyncWatcher)
	}

	
/* Cancel any active requests to the phonebook synchroniser */
void CIdleContactSorter::DoCancel()
	{
	// Nothing to do.
	}

	
/** 
 * Uses a simple state machine, initial iSortState is set by Start() to either
 * EInsertSortFinal or EWaitingForInitialICCReady
 *
 * Either Insert Sort all or part of the requested view.
 * (CIdle::RunL calls back to the Insert Sort code.)
 *    State
 *    EInsertContactsOnlyIccLocked		  insert Contacts only (in a mixed view)
 *        goes to EContactsReadyWaitICCUnlock
 *    EInsertSortFinal                    insert all Contacts & ICC entries, or
 *        goes to ESortDone               add ICC entries to mixed view
 *                                        (iSortView specifies which)
 * Or wait for Phonebook Synchroniser to either finish or fail
 *    (failure other than SIM Locked causes a Sort Error) 
 *    State
 *    EWaitingForInitialICCReady          the view has nothing in: Phonebook
 *        goes to EInsertSortFinal        Synchronised allows full view to be available;
 *        or EInsertContactsOnlyIccLocked SIM Locked allows a view without ICC entries to 
 *                                        accessible
 *    EContactsReadyWaitICCUnlock         SIM was previously found to be locked, if/when
 *        goes to EInsertSortFinal        Phonebook Synchroniser completes we can merge in
 *                                        requested ICC entries
 *
 * The check whether the phonebook synchroniser is in a cache-valid state:-
 *
 * This check is done by making a async request to be completed when the 
 * phbksync cache state has changed, checking the current cache state and 
 * if the cache is valid already cancelling the request.
 * (The cancelled request will complete, causing RunL to run again.)
 * If there was a phbksync error check the error code, if it is not due to the
 * SIM card being locked then Leave.
 */
void CIdleContactSorter::RunL()
	{
	User::LeaveIfError(iStatus.Int());

	// either sort or wait for ICC ready / phonebook synch state change
	switch (iSortState)
		{
		// states that are sorting all or part of view
	case EInsertSortFinal:				// full insert sort or Phonebook Synched so add ICC entries
	case EInsertContactsOnlyIccLocked:	// insert Contacts for now, then wait for SIM to be unlocked
		// do slice of full / Contacts only /ICC only insert sort
		if (iSortObserver.IdleSorterNotifyL(KErrNone))
			{ // CAsyncOneShot::Call()
			Call();
			}
		else if(iSortState == EInsertContactsOnlyIccLocked)
			{
			// we are now waiting for phbksync, so that we can add ICC entries
			ChangeSortState(EContactsReadyWaitICCUnlock);
			}
		else
			{
			// CIdleContactSorter all done
			iSortState = ESortAllDone;
			}
		
		break;

		// states that are waiting for a phonebook sync event
	case EWaitingForInitialICCReady:	// ICC entries in view, waiting for Phonebook Synch state change
		// ICC entries are included in view:
		if (iPhbkSyncWatcher->PhonebooksReady() > 0)
			{
			// ICC sync complete - can immediately sort everything
			ChangeSortState(EInsertSortFinal);
			}
		else if (iPhbkSyncWatcher->PhonebooksWaiting() > 0)
			{
			// SIM card is locked and, this is the first time we've seen this

			// Insert Contacts (if wanted) into View now
			// Afterwards we will wait again for SIM to unlock & Phonebook Synch to complete
			if(iRequestedView & EICCEntriesAndContacts)
				{
				// insert/sort view, but without the requested ICC entries
				iSortView = static_cast<TContactViewPreferences>(iSortView & ~EICCEntriesAndContacts);
				ChangeSortState(EInsertContactsOnlyIccLocked);
				}
			else 
				{
				iSortObserver.IccViewNotifyL(MContactViewSortObserver::TIccViewNotify_IccOnlyLocked);
				
				// now wait for SIM to unlock & Phonebook Synch to complete
				ChangeSortState(EContactsReadyWaitICCUnlock);
				} 
			}
		else
			{
			// synchronisation finished with an error?
			User::LeaveIfError(iPhbkSyncWatcher->PhonebookSyncError());
			}

		// otherwise wait for a Phonebook Synch event
		break;

	case EContactsReadyWaitICCUnlock:	// when SIM is unlocked add ICC Entries to this view
		// ICC entries are included in view:
		if (iPhbkSyncWatcher->PhonebooksReady() > 0)
			{
			// ICC sync complete - can sort everything
			ChangeSortState(EInsertSortFinal);

			// add requested ICC entries into the sorted view
			iSortView = STATIC_CAST(TContactViewPreferences, (iSortView & ~EContactsOnly) | EICCEntriesOnly);
			
			iSortObserver.IccViewNotifyL(MContactViewSortObserver::TIccViewNotify_IccUnlocked);
			}	

		// otherwise wait for a Phonebook Synch event
		break;

	case ESortAllDone: // shouldn't have come back here
	default:
		Panic(ECntPanicViewSorterStateMachine);
		break;
		}

	}


/* 
 * Change the current sort state.
 * 
 * @param aNewSortState the new sort state to be set.
 */
void CIdleContactSorter::ChangeSortState(TSorterState aNewSortState)
	{
	// new state
	iSortState = aNewSortState;
	// make the active object to run, CAsyncOneShot::Call()
	Call();
	}


/* 
 * Handle any leave during CIdleContactSorter::RunL. 
 * The local view is informed of that the view construction failed.
 * It will broadcast indirectly an ESortError view event to all clients of this view.
 * 
 * @param aError Leave code from RunL
 */
TInt CIdleContactSorter::RunError(TInt aError)
	{
	if ((aError != KErrCancel) && (iSortState != ESortAllDone))
		{
		TInt err = KErrNone;
		TRAP(err, iSortObserver.IdleSorterNotifyL(aError));
		iSortState = ESortAllDone;
		}
	return KErrNone;
	}


/*
 Initialise Idle Contact Sorter for a new sort

 Re-init iSortView - the view filter for the Insert Sort
 Decide the initial iSortState for RunL:
   Contacts only view -> EInsertSortFinal
   ICC entries included -> EWaitingForInitialICCReady
 */
void CIdleContactSorter::Start()
	{
	// initially we will try to insert sort everything requested
	iSortView = iRequestedView;

	if (iPhbkSyncWatcher)
		{
		// ICC entries included in view, must wait for Phonebook Synch
		iSortState = EWaitingForInitialICCReady;
		}
	else
		{
		// Only Contacts wanted in view, we can Sort straight away
		iSortState = EInsertSortFinal;
		}

	// set Active for the first time, CAsyncOneShot::Call()
	Call();
	}


/*
 Stop any sort that is already in progress
 */
void CIdleContactSorter::Stop()
	{
	if (iSortState != ESortAllDone)
 		{
		// stop sorting
		iSortState = ESortAllDone;
		Cancel();
 		}
	}


/* 
 * Determines whether view events should be queued.
 * 
 * @return ETrue, if view events should be queued. EFalse, otherwise
 */
TBool CIdleContactSorter::IsICCSynchronised() const
	{
	// Initial wait for phonebook synch (i.e. waiting for ICC ready or locked) ?
	if(iSortState == EWaitingForInitialICCReady)
		{
		return EFalse;
		}
	return ETrue;
	}

	
/**
 * Current View Preferences for insert sort in to View
 *
 * May be a subset of the requested View.
 * If the SIM card is locked this will initially be a View without ICC entries.
 * If the SIM becomes unlocked a second pass then picks out ICC entries only.
 *
 */
TContactViewPreferences CIdleContactSorter::SortViewPreferences() const
	{
	return iSortView;
	}


/**
 * Modifies View Preferences for inserting into View
 *
 * May be a subset of the requested View:
 * If a Mixed (Contacts & ICC view) is requested and the Phonebook Synch has NOT
 * completed then only Contacts entries are added to the view. When the PhoneBook Synch 
 * completes all ICC entries will at the same time.
 *
 */
TBool CIdleContactSorter::InsertViewPreferences(TContactViewPreferences &aInsertView) const
	{
	TBool okayToInsert = ETrue;

	switch (iSortState)
		{
	case EInsertSortFinal:				// full insert sort or Phonebook Synched so add ICC entries
	case ESortAllDone:
		// view is finished or finishing, can Insert any contact
		break;

	case EInsertContactsOnlyIccLocked:	// insert Contacts for now, then wait for SIM to be unlocked
		// only Contacts can be inserted now, no ICC entries
		aInsertView = iSortView;
		break;

	case EWaitingForInitialICCReady:	// ICC entries in view, waiting for Phonebook Synch state change
		// Waiting for initial ICC Synch result, insert nothing
		okayToInsert = EFalse;
		break;

	case EContactsReadyWaitICCUnlock:	// when SIM is unlocked add ICC Entries to this view
		if (aInsertView & EICCEntriesOnly)
			{
			okayToInsert = EFalse;		// can't insert ICC entries yet
			}
		else
			{
			aInsertView = iSortView;	// only Insert Contacts
			}
		break;
		}

	return okayToInsert;
	}

	
/**
 * PhoneBook Synch event handler
 *
 * @param aPhbkState the new phone book synch state.
 */
void CIdleContactSorter::ContactPhbkSyncEventHandler(TPhonebookState aPhbkState)
	{
	switch (aPhbkState)
		{
		case EIccPhbkNotSynchronised:
			/* Initial state, or ICC card has 'gone away' (e.g. ICC is resetting). */
			// no action - may want to act on this in future
			break;

		case EIccPhbkSynchronised:	// ICC Phonebook has completed synchronisation.

		case EIccWaitForPhbkToBeReady:	// Sync failed due to ICC being locked or not ready.

		case EIccPhbkSyncError:		//	Sync with Phbk Server failed.

			// in a sorting state where we care?
			if ((iSortState == EWaitingForInitialICCReady) || (iSortState == EContactsReadyWaitICCUnlock))
				{
				// let state machine in RunL() deal with the event
				if (!IsActive())
					{ // CAsyncOneShot::Call()
					Call();
					}
				}
			break;
		}
	}