--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/cntcommonui/contacteditors/cnteditviewlistmodel.cpp Tue Sep 21 17:07:25 2010 +0300
@@ -0,0 +1,500 @@
+/*
+* Copyright (c) 2009 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:
+*
+*/
+
+#include "cnteditviewlistmodel.h"
+#include "cntextensionmanager.h"
+#include "cntuiextensionfactory.h"
+#include "cnteditviewitemsupplier.h"
+#include "cnteditviewdetailitem.h"
+#include "cnteditviewitembuilder.h"
+#include <cntviewparams.h>
+#include <QDir>
+
+CntEditViewListModel::CntEditViewListModel( QContact& aContact, CntExtensionManager& aMgr ) :
+mManager( aMgr ),
+mContact( aContact )
+
+{
+ mLookupTable.insert( EPhonenumber, -1 );
+ mLookupTable.insert( EEmailAddress, -1 );
+ mLookupTable.insert( EAddressTemplate,-1 );
+ mLookupTable.insert( EPluginItem, -1 );
+ mLookupTable.insert( EUrl, -1 );
+ mLookupTable.insert( ESeparator, -1 );
+ mLookupTable.insert( EAddressDetail, -1 );
+ mLookupTable.insert( ECompany, -1 );
+ mLookupTable.insert( EDate, -1 );
+ mLookupTable.insert( ERingingTone, -1 );
+ mLookupTable.insert( ENote, -1 );
+ mLookupTable.insert( EFamily, -1 );
+ mLookupTable.insert( ESynchronization,-1 );
+
+ mLookupMap.insert( QContactPhoneNumber::DefinitionName, EPhonenumber );
+ mLookupMap.insert( QContactOnlineAccount::DefinitionName, EPhonenumber );
+ mLookupMap.insert( QContactEmailAddress::DefinitionName, EEmailAddress );
+ mLookupMap.insert( QContactAddress::DefinitionName, EAddressDetail);
+ mLookupMap.insert( QContactUrl::DefinitionName, EUrl );
+ mLookupMap.insert( QContactOrganization::DefinitionName, ECompany);
+ mLookupMap.insert( QContactBirthday::DefinitionName, EDate );
+ mLookupMap.insert( QContactAnniversary::DefinitionName, EDate);
+ mLookupMap.insert( QContactRingtone::DefinitionName, ERingingTone);
+ mLookupMap.insert( QContactNote::DefinitionName, ENote);
+ mLookupMap.insert( QContactFamily::DefinitionName, EFamily);
+
+ mBuilder = new CntEditViewItemBuilder();
+ mSeparator = new CntEditViewSeparator();
+
+ refresh();
+}
+
+CntEditViewListModel::~CntEditViewListModel()
+{
+ // Delete the separator item separately if it hasn't been added to the list
+ if (mSeparator && mItemList.indexOf(mSeparator) == -1)
+ {
+ delete mSeparator;
+ mSeparator = NULL;
+ }
+
+ qDeleteAll( mItemList );
+ mItemList.clear();
+
+ delete mBuilder;
+ mBuilder = NULL;
+}
+
+void CntEditViewListModel::updateRingtone()
+{
+ beginResetModel();
+ KLookupKey key = mLookupMap.value( QContactRingtone::DefinitionName );
+ int index = mLookupTable.value( key );
+ if ( index != -1 )
+ {
+ // fetch the detail item
+ QContactRingtone ringtone = mContact.detail<QContactRingtone>();
+ QUrl ringtoneUrl = ringtone.audioRingtoneUrl();
+ if ( !ringtoneUrl.isEmpty() )
+ {
+ CntEditViewDetailItem* detailItem = new CntEditViewDetailItem(
+ ringtone,
+ QContactRingtone::FieldAudioRingtoneUrl,
+ ringToneFetcherView);
+ detailItem->addText( hbTrId("txt_phob_formlabel_ringing_tone") );
+ QFileInfo ringtoneFileInfo(ringtoneUrl.toString());
+ QString ringtoneFileName = ringtoneFileInfo.fileName();
+ detailItem->addText( ringtoneFileName);
+ mItemList.replace(index, detailItem );
+ }
+ }
+ else
+ {
+ insertDetailItem( key, mBuilder->ringtoneDetails(mContact) );
+ }
+ endResetModel();
+}
+
+int CntEditViewListModel::rowCount( const QModelIndex& aParent ) const
+{
+ Q_UNUSED( aParent );
+ return mItemList.size();
+}
+
+QVariant CntEditViewListModel::data( const QModelIndex& aIndex, int aRole ) const
+{
+ if ( aIndex.row() >= 0 && aIndex.row() < mItemList.size() )
+ {
+ CntEditViewItem* item = mItemList.at( aIndex.row() );
+ return item->data( aRole );
+ }
+ return QVariant();
+}
+
+Qt::ItemFlags CntEditViewListModel::flags(const QModelIndex& aIndex) const
+{
+ CntEditViewItem* item = mItemList.at( aIndex.row() );
+ QVariant data = item->data( Hb::ItemTypeRole );
+ if ( data.toInt() == Hb::SeparatorItem )
+ {
+ return Qt::NoItemFlags;
+ }
+
+ return QAbstractListModel::flags( aIndex );
+}
+
+CntEditViewItem* CntEditViewListModel::itemAt( const QModelIndex& aIndex ) const
+{
+ return mItemList.at( aIndex.row() );
+}
+
+void CntEditViewListModel::removeItem( CntEditViewItem* aItem, const QModelIndex& aIndex )
+{
+ int index = mItemList.indexOf( aItem );
+ if ( index >= 0 )
+ {
+ beginRemoveRows( aIndex.parent(), index, index );
+ // remove item from item list
+ CntEditViewItem* item = mItemList.takeAt( index );
+
+ // get detailed information
+ QContactDetail detail = item->data(ERoleContactDetail).value<QContactDetail>();
+ QStringList fields = item->data(ERoleContactDetailFields).toStringList();
+
+ // remove the detail from QContact
+ mBuilder->removeDetail( mContact, detail, fields );
+
+ // Update lookup table. Note, in case of QContactAddress,
+ // we can't remove address template, so the mapping for address always points to address detail
+ KLookupKey lookupKey = mLookupMap.value( detail.definitionName() );
+ removeItem( lookupKey );
+
+ delete item;
+
+ endRemoveRows();
+
+ // Remove separator item if needed
+ if (mItemList.last()->data( Hb::ItemTypeRole ) == QVariant(Hb::SeparatorItem))
+ {
+ int separatorIndex = mItemList.indexOf( mSeparator );
+ beginRemoveRows( aIndex.parent(), separatorIndex, separatorIndex );
+ mItemList.removeAt( separatorIndex );
+ removeItem( ESeparator );
+
+ delete mSeparator;
+ mSeparator = NULL;
+
+ endRemoveRows();
+ }
+
+ // Check if the removed item is -1 in lookuptable and if it needs a template
+ int lookupValue = mLookupTable.value( lookupKey );
+ if ( lookupValue == -1 )
+ {
+ if ( detail.definitionName() == QContactPhoneNumber::DefinitionName )
+ {
+ beginInsertRows(aIndex.parent(), index, index);
+ insertItem( EPhonenumber, mBuilder->phoneNumberItems(mContact) );
+ endInsertRows();
+ }
+ else if ( detail.definitionName() == QContactEmailAddress::DefinitionName )
+ {
+ beginInsertRows(aIndex.parent(), index, index);
+ insertItem( EEmailAddress, mBuilder->emailAddressItems(mContact) );
+ endInsertRows();
+ }
+ else if ( detail.definitionName() == QContactAddress::DefinitionName )
+ {
+ // special case: unlike the others, address template isn't in the same index as the last deleted detail
+ int emailIndex = mLookupTable.value( EEmailAddress );
+ beginInsertRows(aIndex.parent(), emailIndex + 1, emailIndex + 1);
+ insertItem( EAddressTemplate, mBuilder->addressItems(mContact) );
+ endInsertRows();
+ }
+ else if ( detail.definitionName() == QContactUrl::DefinitionName )
+ {
+ beginInsertRows(aIndex.parent(), index, index);
+ insertItem( EUrl, mBuilder->urlItems(mContact) );
+ endInsertRows();
+ }
+ }
+ }
+}
+
+void CntEditViewListModel::refreshExtensionItems()
+{
+ // remove and delete all extension items
+ for( int i(mItemList.count()-1); i >= 0; i-- )
+ {
+ CntEditViewItem* item = mItemList.at( i );
+ if ( item->data(ERoleItemType) == QVariant(ETypeUiExtension) )
+ {
+ QModelIndex modelIndex = createIndex(i, 0);
+ beginRemoveRows( modelIndex.parent(), i, i );
+ mItemList.removeAt(i);
+ removeItem( EPluginItem );
+
+ delete item;
+ endRemoveRows();
+ }
+ }
+ // query and reload extension items again
+ int count = mManager.pluginCount();
+ for ( int i(0); i < count; i++ )
+ {
+ CntUiExtensionFactory* factory = mManager.pluginAt(i);
+ CntEditViewItemSupplier* supplier = factory->editViewItemSupplier( mContact );
+ if (supplier)
+ {
+ loadPluginItems( supplier );
+ }
+ }
+}
+
+void CntEditViewListModel::allInUseFields( CntViewIdList& aList )
+{
+ foreach ( KLookupKey key, mLookupTable.keys() )
+ {
+ int index = mLookupTable.value( key );
+ if ( index != -1 )
+ {
+ switch (key)
+ {
+ case EAddressDetail:
+ {
+ // Considered to be in use if all address contexts have been added
+ QList<QContactAddress> addrList = mContact.details<QContactAddress>();
+ if ( addrList.count() >= 3 ) // no context, context home, context work
+ aList.append( addressEditorView );
+ }
+ break;
+
+ case ECompany:
+ {
+ // Considered in use if some details and assistant exists
+ QContactOrganization org = mContact.detail( QContactOrganization::DefinitionName );
+ if ( !org.assistantName().isEmpty() &&
+ (!org.name().isEmpty() || !org.department().isEmpty() || !org.title().isEmpty()) )
+ aList.append( companyEditorView );
+ }
+ break;
+
+ case EDate:
+ {
+ QContactBirthday bd = mContact.detail( QContactBirthday::DefinitionName );
+ QContactAnniversary anniversary = mContact.detail( QContactAnniversary::DefinitionName );
+ // considered as in use when both birthday and anniversary has a valid date
+ if ( bd.date().isValid() && anniversary.originalDate().isValid() )
+ aList.append( dateEditorView );
+ }
+ break;
+
+ case EFamily:
+ {
+ QContactFamily family = mContact.detail( QContactFamily::DefinitionName );
+ if ( !family.children().isEmpty() && !family.spouse().isEmpty() )
+ aList.append( familyDetailEditorView );
+ }
+ break;
+
+ case ERingingTone:
+ {
+
+ QContactRingtone tone = mContact.detail( QContactRingtone::DefinitionName );
+ if ( !tone.audioRingtoneUrl().isEmpty() )
+ aList.append( ringToneFetcherView );
+
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+QModelIndex CntEditViewListModel::itemIndex( QContactDetail aDetail ) const
+{
+ QModelIndex itemIndex;
+ for ( int i(0); i < mItemList.count(); i++ ) {
+ CntEditViewItem* item = mItemList.at( i );
+ QVariant data = item->data( ERoleContactDetail );
+ if ( data.value<QContactDetail>() == aDetail )
+ {
+ itemIndex = index( i );
+ break;
+ }
+ }
+ return itemIndex;
+}
+
+void CntEditViewListModel::refresh()
+{
+ insertItem( EPhonenumber, mBuilder->phoneNumberItems(mContact) );
+ insertItem( EEmailAddress, mBuilder->emailAddressItems(mContact) );
+ insertItem( EAddressTemplate, mBuilder->addressItems(mContact) );
+ insertItem( EUrl, mBuilder->urlItems(mContact) );
+
+ int count = mManager.pluginCount();
+ for ( int i(0); i < count; i++ )
+ {
+ CntUiExtensionFactory* factory = mManager.pluginAt(i);
+ CntEditViewItemSupplier* supplier = factory->editViewItemSupplier( mContact );
+ if (supplier)
+ {
+ loadPluginItems( supplier );
+ }
+ }
+
+ insertDetailItem( EAddressDetail, mBuilder->addressDetails(mContact) );
+ insertDetailItem( ECompany, mBuilder->companyDetails(mContact) );
+ insertDetailItem( EDate, mBuilder->dateDetails(mContact) );
+ insertDetailItem( ENote, mBuilder->noteDetails(mContact) );
+ insertDetailItem( EFamily, mBuilder->familyDetails(mContact) );
+ insertDetailItem( ERingingTone, mBuilder->ringtoneDetails(mContact) );
+}
+
+bool CntEditViewListModel::isEmptyItem( CntEditViewItem* aItem )
+{
+ if ( aItem )
+ {
+ QContactDetail d = aItem->data( ERoleContactDetail ).value<QContactDetail>();
+ QStringList fields = aItem->data( ERoleContactDetailFields ).toStringList();
+
+ foreach ( QString field, fields )
+ {
+ if ( !d.value(field).isEmpty() || !d.value<QStringList>(field).isEmpty() )
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+void CntEditViewListModel::loadPluginItems( CntEditViewItemSupplier* aSupplier )
+{
+ QList<CntEditViewItem*> list;
+ int count = aSupplier->itemCount();
+ for ( int i(0); i < count; i++ )
+ {
+ CntEditViewItem* item = aSupplier->itemAt( i );
+ if ( item )
+ {
+ list << item;
+ }
+ }
+
+ if ( !list.isEmpty() )
+ {
+ // the new items will be inserted under already existing plugin items...
+ int index = mLookupTable.value( EPluginItem );
+
+ // ... or under the address template (if no plugins exist)
+ if (index == -1)
+ {
+ index = mLookupTable.value( EAddressTemplate );
+ }
+
+ // ... or as a final choice, under the email address items (if address template doesn't exist)
+ if (index == -1)
+ {
+ index = mLookupTable.value( EEmailAddress );
+ }
+ QModelIndex modelIndex = createIndex(index, 0);
+ beginInsertRows(modelIndex.parent(), index + 1, index + count);
+ insertItem( EPluginItem, list );
+ endInsertRows();
+ }
+}
+
+void CntEditViewListModel::insertDetailItem( KLookupKey aKey, QList<CntEditViewItem*> aList )
+{
+ if ( !aList.isEmpty() )
+ {
+ insertSeparator();
+ insertItem( aKey, aList );
+ }
+}
+
+void CntEditViewListModel::insertItem( KLookupKey aLookupKey, QList<CntEditViewItem*> aList )
+{
+ if ( !aList.isEmpty() )
+ {
+ QList<KLookupKey> keys = mLookupTable.keys();
+ int ind = keys.indexOf( aLookupKey );
+ for ( int i=ind; i >= 0; i-- )
+ {
+ KLookupKey key = keys.at( i );
+ int lastIndexValue = mLookupTable.value( key );
+ // search next suitable "lastindex" where to insert the items
+ if ( i != 0 && lastIndexValue == -1 )
+ continue;
+
+ // insert items to current index
+ for ( int j(0); j < aList.count(); j++ )
+ {
+ mItemList.insert( lastIndexValue + j + 1, aList[j] );
+ }
+
+ // lookup keys value "lastindex"
+ int listCount = aList.count();
+ lastIndexValue = lastIndexValue + listCount;
+ mLookupTable.insert( aLookupKey, lastIndexValue );
+ // update all indexes in lookuptable
+ for ( int k(ind+1); k < keys.size(); k++ )
+ {
+ int value = mLookupTable.value(keys[k]);
+ if ( value != -1 )
+ {
+ mLookupTable.insert( keys[k], value + aList.count() );
+ }
+ }
+ break;
+ }
+ }
+}
+
+void CntEditViewListModel::removeItem( KLookupKey aKey )
+{
+ QList<KLookupKey> keys = mLookupTable.keys();
+ int ind = keys.indexOf( aKey );
+ for ( int i(ind); i < keys.count(); i++ )
+ {
+ KLookupKey key = keys.at( i );
+ int lastIndexValue = mLookupTable.value( key ) - 1;
+
+ // climb the keys (bottom to top) and see if somebody has the same value (then set value to -1)
+ for ( int j(ind); j >= 0; j-- )
+ {
+ if ( mLookupTable.value(keys[j]) == lastIndexValue )
+ {
+ lastIndexValue = -1;
+ break;
+ }
+ }
+
+ mLookupTable.insert( key, lastIndexValue );
+ // update rest of the keys by reducing one (top to bottom)
+ for ( int k(ind+1); k < keys.count(); k++ )
+ {
+ KLookupKey tmp = keys.at( k );
+ int value = mLookupTable.value( tmp );
+ if ( value != -1 )
+ {
+ mLookupTable.insert( tmp, value - 1 );
+ }
+ }
+
+ break;
+ }
+}
+
+void CntEditViewListModel::insertSeparator()
+{
+ if ( mItemList.indexOf(mSeparator) == -1 )
+ {
+ QList<CntEditViewItem*> list;
+ if (!mSeparator)
+ {
+ mSeparator = new CntEditViewSeparator();
+ }
+ list << mSeparator;
+ insertItem( ESeparator, list );
+ }
+}
+
+// End of File