|
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 "cnteditviewlistmodel.h" |
|
19 #include "cntextensionmanager.h" |
|
20 #include "cntuiextensionfactory.h" |
|
21 #include "cnteditviewitemsupplier.h" |
|
22 #include "cnteditviewdetailitem.h" |
|
23 #include "cnteditviewitembuilder.h" |
|
24 #include <cntviewparams.h> |
|
25 #include <QDir> |
|
26 |
|
27 CntEditViewListModel::CntEditViewListModel( QContact& aContact, CntExtensionManager& aMgr ) : |
|
28 mManager( aMgr ), |
|
29 mContact( aContact ) |
|
30 |
|
31 { |
|
32 mLookupTable.insert( EPhonenumber, -1 ); |
|
33 mLookupTable.insert( EEmailAddress, -1 ); |
|
34 mLookupTable.insert( EAddressTemplate,-1 ); |
|
35 mLookupTable.insert( EPluginItem, -1 ); |
|
36 mLookupTable.insert( EUrl, -1 ); |
|
37 mLookupTable.insert( ESeparator, -1 ); |
|
38 mLookupTable.insert( EAddressDetail, -1 ); |
|
39 mLookupTable.insert( ECompany, -1 ); |
|
40 mLookupTable.insert( EDate, -1 ); |
|
41 mLookupTable.insert( ERingingTone, -1 ); |
|
42 mLookupTable.insert( ENote, -1 ); |
|
43 mLookupTable.insert( EFamily, -1 ); |
|
44 mLookupTable.insert( ESynchronization,-1 ); |
|
45 |
|
46 mLookupMap.insert( QContactPhoneNumber::DefinitionName, EPhonenumber ); |
|
47 mLookupMap.insert( QContactOnlineAccount::DefinitionName, EPhonenumber ); |
|
48 mLookupMap.insert( QContactEmailAddress::DefinitionName, EEmailAddress ); |
|
49 mLookupMap.insert( QContactAddress::DefinitionName, EAddressDetail); |
|
50 mLookupMap.insert( QContactUrl::DefinitionName, EUrl ); |
|
51 mLookupMap.insert( QContactOrganization::DefinitionName, ECompany); |
|
52 mLookupMap.insert( QContactBirthday::DefinitionName, EDate ); |
|
53 mLookupMap.insert( QContactAnniversary::DefinitionName, EDate); |
|
54 mLookupMap.insert( QContactRingtone::DefinitionName, ERingingTone); |
|
55 mLookupMap.insert( QContactNote::DefinitionName, ENote); |
|
56 mLookupMap.insert( QContactFamily::DefinitionName, EFamily); |
|
57 |
|
58 mBuilder = new CntEditViewItemBuilder(); |
|
59 mSeparator = new CntEditViewSeparator(); |
|
60 |
|
61 refresh(); |
|
62 } |
|
63 |
|
64 CntEditViewListModel::~CntEditViewListModel() |
|
65 { |
|
66 // Delete the separator item separately if it hasn't been added to the list |
|
67 if (mSeparator && mItemList.indexOf(mSeparator) == -1) |
|
68 { |
|
69 delete mSeparator; |
|
70 mSeparator = NULL; |
|
71 } |
|
72 |
|
73 qDeleteAll( mItemList ); |
|
74 mItemList.clear(); |
|
75 |
|
76 delete mBuilder; |
|
77 mBuilder = NULL; |
|
78 } |
|
79 |
|
80 void CntEditViewListModel::updateRingtone() |
|
81 { |
|
82 beginResetModel(); |
|
83 KLookupKey key = mLookupMap.value( QContactRingtone::DefinitionName ); |
|
84 int index = mLookupTable.value( key ); |
|
85 if ( index != -1 ) |
|
86 { |
|
87 // fetch the detail item |
|
88 QContactRingtone ringtone = mContact.detail<QContactRingtone>(); |
|
89 QUrl ringtoneUrl = ringtone.audioRingtoneUrl(); |
|
90 if ( !ringtoneUrl.isEmpty() ) |
|
91 { |
|
92 CntEditViewDetailItem* detailItem = new CntEditViewDetailItem( |
|
93 ringtone, |
|
94 QContactRingtone::FieldAudioRingtoneUrl, |
|
95 ringToneFetcherView); |
|
96 detailItem->addText( hbTrId("txt_phob_formlabel_ringing_tone") ); |
|
97 QFileInfo ringtoneFileInfo(ringtoneUrl.toString()); |
|
98 QString ringtoneFileName = ringtoneFileInfo.fileName(); |
|
99 detailItem->addText( ringtoneFileName); |
|
100 mItemList.replace(index, detailItem ); |
|
101 } |
|
102 } |
|
103 else |
|
104 { |
|
105 insertDetailItem( key, mBuilder->ringtoneDetails(mContact) ); |
|
106 } |
|
107 endResetModel(); |
|
108 } |
|
109 |
|
110 int CntEditViewListModel::rowCount( const QModelIndex& aParent ) const |
|
111 { |
|
112 Q_UNUSED( aParent ); |
|
113 return mItemList.size(); |
|
114 } |
|
115 |
|
116 QVariant CntEditViewListModel::data( const QModelIndex& aIndex, int aRole ) const |
|
117 { |
|
118 if ( aIndex.row() >= 0 && aIndex.row() < mItemList.size() ) |
|
119 { |
|
120 CntEditViewItem* item = mItemList.at( aIndex.row() ); |
|
121 return item->data( aRole ); |
|
122 } |
|
123 return QVariant(); |
|
124 } |
|
125 |
|
126 Qt::ItemFlags CntEditViewListModel::flags(const QModelIndex& aIndex) const |
|
127 { |
|
128 CntEditViewItem* item = mItemList.at( aIndex.row() ); |
|
129 QVariant data = item->data( Hb::ItemTypeRole ); |
|
130 if ( data.toInt() == Hb::SeparatorItem ) |
|
131 { |
|
132 return Qt::NoItemFlags; |
|
133 } |
|
134 |
|
135 return QAbstractListModel::flags( aIndex ); |
|
136 } |
|
137 |
|
138 CntEditViewItem* CntEditViewListModel::itemAt( const QModelIndex& aIndex ) const |
|
139 { |
|
140 return mItemList.at( aIndex.row() ); |
|
141 } |
|
142 |
|
143 void CntEditViewListModel::removeItem( CntEditViewItem* aItem, const QModelIndex& aIndex ) |
|
144 { |
|
145 int index = mItemList.indexOf( aItem ); |
|
146 if ( index >= 0 ) |
|
147 { |
|
148 beginRemoveRows( aIndex.parent(), index, index ); |
|
149 // remove item from item list |
|
150 CntEditViewItem* item = mItemList.takeAt( index ); |
|
151 |
|
152 // get detailed information |
|
153 QContactDetail detail = item->data(ERoleContactDetail).value<QContactDetail>(); |
|
154 QStringList fields = item->data(ERoleContactDetailFields).toStringList(); |
|
155 |
|
156 // remove the detail from QContact |
|
157 mBuilder->removeDetail( mContact, detail, fields ); |
|
158 |
|
159 // Update lookup table. Note, in case of QContactAddress, |
|
160 // we can't remove address template, so the mapping for address always points to address detail |
|
161 KLookupKey lookupKey = mLookupMap.value( detail.definitionName() ); |
|
162 removeItem( lookupKey ); |
|
163 |
|
164 delete item; |
|
165 |
|
166 endRemoveRows(); |
|
167 |
|
168 // Remove separator item if needed |
|
169 if (mItemList.last()->data( Hb::ItemTypeRole ) == QVariant(Hb::SeparatorItem)) |
|
170 { |
|
171 int separatorIndex = mItemList.indexOf( mSeparator ); |
|
172 beginRemoveRows( aIndex.parent(), separatorIndex, separatorIndex ); |
|
173 mItemList.removeAt( separatorIndex ); |
|
174 removeItem( ESeparator ); |
|
175 |
|
176 delete mSeparator; |
|
177 mSeparator = NULL; |
|
178 |
|
179 endRemoveRows(); |
|
180 } |
|
181 |
|
182 // Check if the removed item is -1 in lookuptable and if it needs a template |
|
183 int lookupValue = mLookupTable.value( lookupKey ); |
|
184 if ( lookupValue == -1 ) |
|
185 { |
|
186 if ( detail.definitionName() == QContactPhoneNumber::DefinitionName ) |
|
187 { |
|
188 beginInsertRows(aIndex.parent(), index, index); |
|
189 insertItem( EPhonenumber, mBuilder->phoneNumberItems(mContact) ); |
|
190 endInsertRows(); |
|
191 } |
|
192 else if ( detail.definitionName() == QContactEmailAddress::DefinitionName ) |
|
193 { |
|
194 beginInsertRows(aIndex.parent(), index, index); |
|
195 insertItem( EEmailAddress, mBuilder->emailAddressItems(mContact) ); |
|
196 endInsertRows(); |
|
197 } |
|
198 else if ( detail.definitionName() == QContactAddress::DefinitionName ) |
|
199 { |
|
200 // special case: unlike the others, address template isn't in the same index as the last deleted detail |
|
201 int emailIndex = mLookupTable.value( EEmailAddress ); |
|
202 beginInsertRows(aIndex.parent(), emailIndex + 1, emailIndex + 1); |
|
203 insertItem( EAddressTemplate, mBuilder->addressItems(mContact) ); |
|
204 endInsertRows(); |
|
205 } |
|
206 else if ( detail.definitionName() == QContactUrl::DefinitionName ) |
|
207 { |
|
208 beginInsertRows(aIndex.parent(), index, index); |
|
209 insertItem( EUrl, mBuilder->urlItems(mContact) ); |
|
210 endInsertRows(); |
|
211 } |
|
212 } |
|
213 } |
|
214 } |
|
215 |
|
216 void CntEditViewListModel::refreshExtensionItems() |
|
217 { |
|
218 // remove and delete all extension items |
|
219 for( int i(mItemList.count()-1); i >= 0; i-- ) |
|
220 { |
|
221 CntEditViewItem* item = mItemList.at( i ); |
|
222 if ( item->data(ERoleItemType) == QVariant(ETypeUiExtension) ) |
|
223 { |
|
224 QModelIndex modelIndex = createIndex(i, 0); |
|
225 beginRemoveRows( modelIndex.parent(), i, i ); |
|
226 mItemList.removeAt(i); |
|
227 removeItem( EPluginItem ); |
|
228 |
|
229 delete item; |
|
230 endRemoveRows(); |
|
231 } |
|
232 } |
|
233 // query and reload extension items again |
|
234 int count = mManager.pluginCount(); |
|
235 for ( int i(0); i < count; i++ ) |
|
236 { |
|
237 CntUiExtensionFactory* factory = mManager.pluginAt(i); |
|
238 CntEditViewItemSupplier* supplier = factory->editViewItemSupplier( mContact ); |
|
239 if (supplier) |
|
240 { |
|
241 loadPluginItems( supplier ); |
|
242 } |
|
243 } |
|
244 } |
|
245 |
|
246 void CntEditViewListModel::allInUseFields( CntViewIdList& aList ) |
|
247 { |
|
248 foreach ( KLookupKey key, mLookupTable.keys() ) |
|
249 { |
|
250 int index = mLookupTable.value( key ); |
|
251 if ( index != -1 ) |
|
252 { |
|
253 switch (key) |
|
254 { |
|
255 case EAddressDetail: |
|
256 { |
|
257 // Considered to be in use if all address contexts have been added |
|
258 QList<QContactAddress> addrList = mContact.details<QContactAddress>(); |
|
259 if ( addrList.count() >= 3 ) // no context, context home, context work |
|
260 aList.append( addressEditorView ); |
|
261 } |
|
262 break; |
|
263 |
|
264 case ECompany: |
|
265 { |
|
266 // Considered in use if some details and assistant exists |
|
267 QContactOrganization org = mContact.detail( QContactOrganization::DefinitionName ); |
|
268 if ( !org.assistantName().isEmpty() && |
|
269 (!org.name().isEmpty() || !org.department().isEmpty() || !org.title().isEmpty()) ) |
|
270 aList.append( companyEditorView ); |
|
271 } |
|
272 break; |
|
273 |
|
274 case EDate: |
|
275 { |
|
276 QContactBirthday bd = mContact.detail( QContactBirthday::DefinitionName ); |
|
277 QContactAnniversary anniversary = mContact.detail( QContactAnniversary::DefinitionName ); |
|
278 // considered as in use when both birthday and anniversary has a valid date |
|
279 if ( bd.date().isValid() && anniversary.originalDate().isValid() ) |
|
280 aList.append( dateEditorView ); |
|
281 } |
|
282 break; |
|
283 |
|
284 case EFamily: |
|
285 { |
|
286 QContactFamily family = mContact.detail( QContactFamily::DefinitionName ); |
|
287 if ( !family.children().isEmpty() && !family.spouse().isEmpty() ) |
|
288 aList.append( familyDetailEditorView ); |
|
289 } |
|
290 break; |
|
291 |
|
292 case ERingingTone: |
|
293 { |
|
294 |
|
295 QContactRingtone tone = mContact.detail( QContactRingtone::DefinitionName ); |
|
296 if ( !tone.audioRingtoneUrl().isEmpty() ) |
|
297 aList.append( ringToneFetcherView ); |
|
298 |
|
299 } |
|
300 break; |
|
301 |
|
302 default: |
|
303 break; |
|
304 } |
|
305 } |
|
306 } |
|
307 } |
|
308 |
|
309 QModelIndex CntEditViewListModel::itemIndex( QContactDetail aDetail ) const |
|
310 { |
|
311 QModelIndex itemIndex; |
|
312 for ( int i(0); i < mItemList.count(); i++ ) { |
|
313 CntEditViewItem* item = mItemList.at( i ); |
|
314 QVariant data = item->data( ERoleContactDetail ); |
|
315 if ( data.value<QContactDetail>() == aDetail ) |
|
316 { |
|
317 itemIndex = index( i ); |
|
318 break; |
|
319 } |
|
320 } |
|
321 return itemIndex; |
|
322 } |
|
323 |
|
324 void CntEditViewListModel::refresh() |
|
325 { |
|
326 insertItem( EPhonenumber, mBuilder->phoneNumberItems(mContact) ); |
|
327 insertItem( EEmailAddress, mBuilder->emailAddressItems(mContact) ); |
|
328 insertItem( EAddressTemplate, mBuilder->addressItems(mContact) ); |
|
329 insertItem( EUrl, mBuilder->urlItems(mContact) ); |
|
330 |
|
331 int count = mManager.pluginCount(); |
|
332 for ( int i(0); i < count; i++ ) |
|
333 { |
|
334 CntUiExtensionFactory* factory = mManager.pluginAt(i); |
|
335 CntEditViewItemSupplier* supplier = factory->editViewItemSupplier( mContact ); |
|
336 if (supplier) |
|
337 { |
|
338 loadPluginItems( supplier ); |
|
339 } |
|
340 } |
|
341 |
|
342 insertDetailItem( EAddressDetail, mBuilder->addressDetails(mContact) ); |
|
343 insertDetailItem( ECompany, mBuilder->companyDetails(mContact) ); |
|
344 insertDetailItem( EDate, mBuilder->dateDetails(mContact) ); |
|
345 insertDetailItem( ENote, mBuilder->noteDetails(mContact) ); |
|
346 insertDetailItem( EFamily, mBuilder->familyDetails(mContact) ); |
|
347 insertDetailItem( ERingingTone, mBuilder->ringtoneDetails(mContact) ); |
|
348 } |
|
349 |
|
350 bool CntEditViewListModel::isEmptyItem( CntEditViewItem* aItem ) |
|
351 { |
|
352 if ( aItem ) |
|
353 { |
|
354 QContactDetail d = aItem->data( ERoleContactDetail ).value<QContactDetail>(); |
|
355 QStringList fields = aItem->data( ERoleContactDetailFields ).toStringList(); |
|
356 |
|
357 foreach ( QString field, fields ) |
|
358 { |
|
359 if ( !d.value(field).isEmpty() || !d.value<QStringList>(field).isEmpty() ) |
|
360 { |
|
361 return false; |
|
362 } |
|
363 } |
|
364 } |
|
365 return true; |
|
366 } |
|
367 |
|
368 void CntEditViewListModel::loadPluginItems( CntEditViewItemSupplier* aSupplier ) |
|
369 { |
|
370 QList<CntEditViewItem*> list; |
|
371 int count = aSupplier->itemCount(); |
|
372 for ( int i(0); i < count; i++ ) |
|
373 { |
|
374 CntEditViewItem* item = aSupplier->itemAt( i ); |
|
375 if ( item ) |
|
376 { |
|
377 list << item; |
|
378 } |
|
379 } |
|
380 |
|
381 if ( !list.isEmpty() ) |
|
382 { |
|
383 // the new items will be inserted under already existing plugin items... |
|
384 int index = mLookupTable.value( EPluginItem ); |
|
385 |
|
386 // ... or under the address template (if no plugins exist) |
|
387 if (index == -1) |
|
388 { |
|
389 index = mLookupTable.value( EAddressTemplate ); |
|
390 } |
|
391 |
|
392 // ... or as a final choice, under the email address items (if address template doesn't exist) |
|
393 if (index == -1) |
|
394 { |
|
395 index = mLookupTable.value( EEmailAddress ); |
|
396 } |
|
397 QModelIndex modelIndex = createIndex(index, 0); |
|
398 beginInsertRows(modelIndex.parent(), index + 1, index + count); |
|
399 insertItem( EPluginItem, list ); |
|
400 endInsertRows(); |
|
401 } |
|
402 } |
|
403 |
|
404 void CntEditViewListModel::insertDetailItem( KLookupKey aKey, QList<CntEditViewItem*> aList ) |
|
405 { |
|
406 if ( !aList.isEmpty() ) |
|
407 { |
|
408 insertSeparator(); |
|
409 insertItem( aKey, aList ); |
|
410 } |
|
411 } |
|
412 |
|
413 void CntEditViewListModel::insertItem( KLookupKey aLookupKey, QList<CntEditViewItem*> aList ) |
|
414 { |
|
415 if ( !aList.isEmpty() ) |
|
416 { |
|
417 QList<KLookupKey> keys = mLookupTable.keys(); |
|
418 int ind = keys.indexOf( aLookupKey ); |
|
419 for ( int i=ind; i >= 0; i-- ) |
|
420 { |
|
421 KLookupKey key = keys.at( i ); |
|
422 int lastIndexValue = mLookupTable.value( key ); |
|
423 // search next suitable "lastindex" where to insert the items |
|
424 if ( i != 0 && lastIndexValue == -1 ) |
|
425 continue; |
|
426 |
|
427 // insert items to current index |
|
428 for ( int j(0); j < aList.count(); j++ ) |
|
429 { |
|
430 mItemList.insert( lastIndexValue + j + 1, aList[j] ); |
|
431 } |
|
432 |
|
433 // lookup keys value "lastindex" |
|
434 int listCount = aList.count(); |
|
435 lastIndexValue = lastIndexValue + listCount; |
|
436 mLookupTable.insert( aLookupKey, lastIndexValue ); |
|
437 // update all indexes in lookuptable |
|
438 for ( int k(ind+1); k < keys.size(); k++ ) |
|
439 { |
|
440 int value = mLookupTable.value(keys[k]); |
|
441 if ( value != -1 ) |
|
442 { |
|
443 mLookupTable.insert( keys[k], value + aList.count() ); |
|
444 } |
|
445 } |
|
446 break; |
|
447 } |
|
448 } |
|
449 } |
|
450 |
|
451 void CntEditViewListModel::removeItem( KLookupKey aKey ) |
|
452 { |
|
453 QList<KLookupKey> keys = mLookupTable.keys(); |
|
454 int ind = keys.indexOf( aKey ); |
|
455 for ( int i(ind); i < keys.count(); i++ ) |
|
456 { |
|
457 KLookupKey key = keys.at( i ); |
|
458 int lastIndexValue = mLookupTable.value( key ) - 1; |
|
459 |
|
460 // climb the keys (bottom to top) and see if somebody has the same value (then set value to -1) |
|
461 for ( int j(ind); j >= 0; j-- ) |
|
462 { |
|
463 if ( mLookupTable.value(keys[j]) == lastIndexValue ) |
|
464 { |
|
465 lastIndexValue = -1; |
|
466 break; |
|
467 } |
|
468 } |
|
469 |
|
470 mLookupTable.insert( key, lastIndexValue ); |
|
471 // update rest of the keys by reducing one (top to bottom) |
|
472 for ( int k(ind+1); k < keys.count(); k++ ) |
|
473 { |
|
474 KLookupKey tmp = keys.at( k ); |
|
475 int value = mLookupTable.value( tmp ); |
|
476 if ( value != -1 ) |
|
477 { |
|
478 mLookupTable.insert( tmp, value - 1 ); |
|
479 } |
|
480 } |
|
481 |
|
482 break; |
|
483 } |
|
484 } |
|
485 |
|
486 void CntEditViewListModel::insertSeparator() |
|
487 { |
|
488 if ( mItemList.indexOf(mSeparator) == -1 ) |
|
489 { |
|
490 QList<CntEditViewItem*> list; |
|
491 if (!mSeparator) |
|
492 { |
|
493 mSeparator = new CntEditViewSeparator(); |
|
494 } |
|
495 list << mSeparator; |
|
496 insertItem( ESeparator, list ); |
|
497 } |
|
498 } |
|
499 |
|
500 // End of File |