messagingapp/msgui/unifiededitor/src/msgunieditoraddress.cpp
changeset 37 518b245aa84c
parent 25 84d9eb65b26f
child 38 4e4b6adb1024
equal deleted inserted replaced
25:84d9eb65b26f 37:518b245aa84c
    14  * Description:
    14  * Description:
    15  *
    15  *
    16  */
    16  */
    17 
    17 
    18 // INCLUDES
    18 // INCLUDES
    19 #include "debugtraces.h"
    19 #include <QTimer>
    20 #include <HbTextItem>
    20 #include <HbTextItem>
    21 #include <HbPushButton>
    21 #include <HbPushButton>
    22 #include <HbAction>
    22 #include <HbAction>
    23 #include <hbinputeditorinterface.h>
    23 #include <hbmessagebox.h>
    24 #include <cntservicescontact.h>
    24 #include <cntservicescontact.h>
    25 #include <xqaiwrequest.h>
    25 #include <xqaiwrequest.h>
    26 #include <xqappmgr.h>
    26 #include <xqappmgr.h>
    27 #include <telconfigcrkeys.h>        // KCRUidTelephonyConfiguration
    27 #include <telconfigcrkeys.h>        // KCRUidTelephonyConfiguration
    28 #include <centralrepository.h>
    28 #include <centralrepository.h>
       
    29 #include <HbNotificationDialog>
       
    30 #include <commonphoneparser.h>      // Common phone number validity checker
       
    31 #include <xqconversions.h>
    29 
    32 
    30 // USER INCLUDES
    33 // USER INCLUDES
       
    34 #include "debugtraces.h"
    31 #include "msgunieditoraddress.h"
    35 #include "msgunieditoraddress.h"
    32 #include "msgunifiededitorlineedit.h"
    36 #include "msgunieditorlineedit.h"
       
    37 #include "msgunieditormonitor.h"
       
    38 #include "UniEditorGenUtils.h"
    33 
    39 
    34 const QString PBK_ICON("qtg_mono_contacts");
    40 const QString PBK_ICON("qtg_mono_contacts");
    35 const QString SEND_ICON("qtg_mono_send");
    41 const QString REPLACEMENT_STR("; ");
       
    42 const QString COMMA_SEPERATOR(",");
    36 
    43 
    37 // Constants
    44 // Constants
    38 const int KDefaultGsmNumberMatchLength = 7;  //matching unique ph numbers
    45 const int KDefaultGsmNumberMatchLength = 7;  //matching unique ph numbers
       
    46 #define LOC_SMS_RECIPIENT_LIMIT_REACHED hbTrId("txt_messaging_dialog_number_of_recipients_exceeded")
       
    47 #define LOC_MMS_RECIPIENT_LIMIT_REACHED hbTrId("txt_messaging_dpopinfo_unable_to_add_more_recipien")
       
    48 #define LOC_DIALOG_OK hbTrId("txt_common_button_ok")
       
    49 #define LOC_BUTTON_CANCEL hbTrId("txt_common_button_cancel")
       
    50 #define LOC_INVALID_RECIPIENT hbTrId("txt_messaging_dialog_invalid_recipient_found")
       
    51 #define LOC_INVALID_RECIPIENT_NOT_ADDED hbTrId("txt_messaging_dialog_invalid_recipient_not_added")
       
    52 #define LOC_INVALID_RECIPIENTS_NOT_ADDED hbTrId("txt_messaging_dialog_invalid_recipients_not_added")
       
    53 
       
    54 
       
    55 
       
    56 
    39 
    57 
    40 MsgUnifiedEditorAddress::MsgUnifiedEditorAddress( const QString& label,
    58 MsgUnifiedEditorAddress::MsgUnifiedEditorAddress( const QString& label,
    41                                                   const QString& pluginPath,
       
    42                                                   QGraphicsItem *parent ) :
    59                                                   QGraphicsItem *parent ) :
    43 HbWidget(parent),
    60 MsgUnifiedEditorBaseWidget(parent),
    44 mPluginPath(pluginPath)
    61 mSkipMaxRecipientQuery(false),
    45 {
    62 mAboutToExceedMaxSmsRecipients(false),
    46     #ifdef _DEBUG_TRACES_
    63 mAboutToExceedMaxMmsRecipients(false),
    47     qDebug() << "MsgUnifiedEditorAddress calling HbStyle::registerPlugin";
    64 mExceedsMaxMmsRecipientsBy(0)
    48     #endif
    65 {
    49 
       
    50     this->setContentsMargins(0,0,0,0);
    66     this->setContentsMargins(0,0,0,0);
    51     setPluginBaseId(style()->registerPlugin(mPluginPath));
    67 
    52     
       
    53     mLaunchBtn = new HbPushButton(this);
    68     mLaunchBtn = new HbPushButton(this);
    54     HbStyle::setItemName(mLaunchBtn,"launchBtn");
    69     HbStyle::setItemName(mLaunchBtn,"launchBtn");
    55     connect(mLaunchBtn,SIGNAL(clicked()),this,SLOT(fetchContacts()));
    70     connect(mLaunchBtn,SIGNAL(clicked()),this,SLOT(fetchContacts()));
    56 
    71 
    57     mLaunchBtn->setIcon(HbIcon(PBK_ICON));
    72     mLaunchBtn->setIcon(HbIcon(PBK_ICON));
    59     mAddressEdit = new MsgUnifiedEditorLineEdit(label,this);
    74     mAddressEdit = new MsgUnifiedEditorLineEdit(label,this);
    60     HbStyle::setItemName(mAddressEdit,"addressField");
    75     HbStyle::setItemName(mAddressEdit,"addressField");
    61 
    76 
    62     mAddressEdit->setMaxRows(40);
    77     mAddressEdit->setMaxRows(40);
    63     connect(mAddressEdit, SIGNAL(contentsChanged(const QString&)),
    78     connect(mAddressEdit, SIGNAL(contentsChanged(const QString&)),
    64             this, SLOT(onContentsAdded(const QString&)));
    79             this, SLOT(onContentsChanged(const QString&)));
    65 
    80 
    66     // add "Send" action in VKB
       
    67     HbEditorInterface editorInterface(mAddressEdit);
       
    68     mAddressEdit->setInputMethodHints(Qt::ImhPreferNumbers);
    81     mAddressEdit->setInputMethodHints(Qt::ImhPreferNumbers);
    69     HbAction *sendAction = new HbAction(HbIcon(SEND_ICON), QString(),this);
    82 }
    70     connect(sendAction, SIGNAL(triggered()),this, SIGNAL(sendMessage()));
       
    71     editorInterface.addAction(sendAction);
       
    72     
       
    73     }
       
    74 
    83 
    75 MsgUnifiedEditorAddress::~MsgUnifiedEditorAddress()
    84 MsgUnifiedEditorAddress::~MsgUnifiedEditorAddress()
    76 {
    85 {
    77     style()->unregisterPlugin(mPluginPath);
    86 	//TODO: Should remove this code depending on orbit's reply whether it is needed
       
    87 	//to unregister the same plugin registered on two different widgets twice.
       
    88     //style()->unregisterPlugin(mPluginPath);
    78 }
    89 }
    79 
    90 
    80 void MsgUnifiedEditorAddress::fetchContacts()
    91 void MsgUnifiedEditorAddress::fetchContacts()
    81 {
    92 {
       
    93     mLaunchBtn->blockSignals(true);
       
    94 
    82     QList<QVariant> args;
    95     QList<QVariant> args;
    83     QString serviceName("com.nokia.services.phonebookservices");
    96     QString serviceName("com.nokia.services.phonebookservices");
    84     QString operation("fetch(QString,QString,QString)");
    97     QString operation("fetch(QString,QString,QString)");
    85     XQAiwRequest* request;
    98     XQAiwRequest* request;
    86     XQApplicationManager appManager;
    99     XQApplicationManager appManager;
    87     request = appManager.create(serviceName, "Fetch", operation, true); // embedded
   100     request = appManager.create(serviceName, "Fetch", operation, true); // embedded
    88     if ( request == NULL )
   101     if ( request == NULL )
    89         {
   102         {
    90         return;       
   103         return;
    91         }
   104         }
    92 
   105 
    93     // Result handlers
   106     // Result handlers
    94     connect (request, SIGNAL(requestOk(const QVariant&)), this, SLOT(handleOk(const QVariant&)));
   107     connect (request, SIGNAL(requestOk(const QVariant&)), this, SLOT(handleOk(const QVariant&)));
    95     connect (request, SIGNAL(requestError(int,const QString&)), this, SLOT(handleError(int,const QString&)));
   108     connect (request, SIGNAL(requestError(int,const QString&)), this, SLOT(handleError(int,const QString&)));
    96     
   109 
    97     args << QString(tr("Phonebook")); 
   110     args << QString(tr("Phonebook"));
    98     args << KCntActionAll;
   111     args << KCntActionAll;
    99     args << KCntFilterDisplayAll;
   112     args << KCntFilterDisplayAll;
   100     
   113 
   101     request->setArguments(args);
   114     request->setArguments(args);
   102     request->send();
   115     request->send();
   103     delete request;
   116     delete request;
       
   117 
       
   118     //unblock click signal after some delay.
       
   119     QTimer::singleShot(250,this,SLOT(unblockSignals()));
   104 }
   120 }
   105 
   121 
   106 void MsgUnifiedEditorAddress::handleOk(const QVariant& value)
   122 void MsgUnifiedEditorAddress::handleOk(const QVariant& value)
   107 {
   123 {
   108    CntServicesContactList contactList;
   124    CntServicesContactList contactList =
   109     contactList = qVariantValue<CntServicesContactList>(value);
   125            qVariantValue<CntServicesContactList>(value);
   110 
   126     int count = contactList.count();
   111     for(int i = 0; i < contactList.count(); i++ )
   127 
   112     {
   128     ConvergedMessageAddressList addrlist;
   113         mAddressMap.insert(contactList[i].mPhoneNumber, contactList[i].mDisplayName);
   129     for(int i = 0; i < count; i++ )
   114         if(!contactList[i].mDisplayName.isEmpty())
   130     {
   115         {
   131         ConvergedMessageAddress* address =
   116             mAddressEdit->setText(contactList[i].mDisplayName);
   132                 new ConvergedMessageAddress();
       
   133         if(!contactList[i].mPhoneNumber.isEmpty())
       
   134         {
       
   135             address->setAddress(contactList[i].mPhoneNumber);
   117         }
   136         }
   118         else
   137         else
   119         {
   138         {
   120             mAddressEdit->setText(contactList[i].mPhoneNumber);
   139             address->setAddress(contactList[i].mEmailAddress);
   121         }
   140         }
   122     }
   141         address->setAlias(contactList[i].mDisplayName);
       
   142         addrlist << address;
       
   143     }
       
   144     setAddresses(addrlist);
   123 }
   145 }
   124 
   146 
   125 void MsgUnifiedEditorAddress::handleError(int errorCode, const QString& errorMessage)
   147 void MsgUnifiedEditorAddress::handleError(int errorCode, const QString& errorMessage)
   126 {
   148 {
   127     Q_UNUSED(errorMessage)
   149     Q_UNUSED(errorMessage)
   128     Q_UNUSED(errorCode)
   150     Q_UNUSED(errorCode)
   129 }
   151 }
   130 
   152 
   131 ConvergedMessageAddressList MsgUnifiedEditorAddress::addresses()
   153 // ----------------------------------------------------------------------------
   132 {
   154 // MsgUnifiedEditorAddress::addresses
   133     #ifdef _DEBUG_TRACES_
   155 // @see header
   134     qCritical() << "MsgUnifiedEditorAddress::address start";
   156 // ----------------------------------------------------------------------------
       
   157 ConvergedMessageAddressList MsgUnifiedEditorAddress::addresses(
       
   158         bool removeDuplicates)
       
   159 {
       
   160 #ifdef _DEBUG_TRACES_
       
   161     qCritical() << "MsgUnifiedEditorAddress::addresses start";
   135 #endif
   162 #endif
   136     // sync-up map to account for user-actions on edit-field
   163     // sync-up map to account for user-actions on edit-field
   137     syncDeletionsToMap();
   164     syncDeletionsToMap();
   138     syncAdditionsToMap();
   165     syncAdditionsToMap();
   139 
   166 
   140     QStringList uniqueAddr;
       
   141     uniqueAddr = uniqueAddressList();
       
   142 
       
   143     ConvergedMessageAddressList addresses;
   167     ConvergedMessageAddressList addresses;
   144     foreach(QString addr, uniqueAddr)
   168     if(removeDuplicates)
   145     {
   169     {
   146         ConvergedMessageAddress* address = new ConvergedMessageAddress;
   170         QStringList uniqueAddr;
   147         address->setAddress(addr);
   171         uniqueAddr = uniqueAddressList();
   148         if(!mAddressMap.value(addr).isEmpty())
   172         foreach(QString addr, uniqueAddr)
   149         {
   173         {
       
   174             ConvergedMessageAddress* address = new ConvergedMessageAddress;
       
   175             address->setAddress(addr);
   150             address->setAlias(mAddressMap.value(addr));
   176             address->setAlias(mAddressMap.value(addr));
   151          }
   177             addresses.append(address);
   152         addresses.append(address);
   178         }
   153     }
   179     }
   154     #ifdef _DEBUG_TRACES_
   180     else
   155     qCritical() << "MsgUnifiedEditorAddress::address end";
   181     {
       
   182         QMap<QString, QString>::iterator i = mAddressMap.begin();
       
   183         while (i != mAddressMap.end())
       
   184         {
       
   185             ConvergedMessageAddress* address = new ConvergedMessageAddress;
       
   186             address->setAddress(i.key());
       
   187             address->setAlias(i.value());
       
   188             addresses.append(address);
       
   189             i++;
       
   190         }
       
   191     }
       
   192 #ifdef _DEBUG_TRACES_
       
   193     qCritical() << "MsgUnifiedEditorAddress::addresses end";
   156 #endif
   194 #endif
   157     return addresses;
   195     return addresses;
   158 }
   196 }
   159 
   197 
   160 int MsgUnifiedEditorAddress::addressCount()
   198 int MsgUnifiedEditorAddress::addressCount()
   162     return mAddressEdit->addresses().count();
   200     return mAddressEdit->addresses().count();
   163 }
   201 }
   164 
   202 
   165 void MsgUnifiedEditorAddress::setAddresses(ConvergedMessageAddressList addrlist)
   203 void MsgUnifiedEditorAddress::setAddresses(ConvergedMessageAddressList addrlist)
   166 {
   204 {
   167 	int count = addrlist.count();
   205     // avoid processing if no info available
       
   206     if(addrlist.count() == 0)
       
   207     {
       
   208         return;
       
   209     }
       
   210 
       
   211     // ensure flags are reset before starting the addr addition
       
   212     mAboutToExceedMaxSmsRecipients = false;
       
   213     mAboutToExceedMaxMmsRecipients = false;
       
   214     mExceedsMaxMmsRecipientsBy = 0;
       
   215 
       
   216     // first, we check if MMS max-recipient count will exceed
       
   217     int count = addrlist.count();
       
   218 	int futureCount = count + MsgUnifiedEditorMonitor::msgAddressCount();
       
   219 	if(futureCount > MsgUnifiedEditorMonitor::maxMmsRecipients())
       
   220 	{
       
   221 	    mAboutToExceedMaxMmsRecipients = true;
       
   222 	    mExceedsMaxMmsRecipientsBy =
       
   223 	            futureCount - MsgUnifiedEditorMonitor::maxMmsRecipients();
       
   224 	}
       
   225 	// else, check if SMS max-recipient count will exceed
       
   226 	else if(!mSkipMaxRecipientQuery)
       
   227 	{
       
   228 	    futureCount = count + addressCount();
       
   229 	    if( (addressCount() <= MsgUnifiedEditorMonitor::maxSmsRecipients()) &&
       
   230 	        (futureCount > MsgUnifiedEditorMonitor::maxSmsRecipients()) )
       
   231 	    {
       
   232 	        mAboutToExceedMaxSmsRecipients = true;
       
   233 	    }
       
   234 	}
       
   235 
       
   236 	int  invalidCount= 0;
       
   237     QString invalidContacts;
   168     for(int i = 0; i < count; i++ )
   238     for(int i = 0; i < count; i++ )
   169     {
   239         {
   170         mAddressMap.insert(addrlist[i]->address(), addrlist[i]->alias());
   240         bool isValid = false;
   171         if(!addrlist[i]->alias().isEmpty())
   241         isValid = checkValidAddress(addrlist.at(i)->address());
   172         {
   242         if(!isValid)
   173             mAddressEdit->setText(addrlist[i]->alias());
   243            {
       
   244             invalidCount ++;
       
   245             // append the comma till last but one contact.
       
   246             // add the invalid ocntacts to the " , " seperated string.
       
   247             if(invalidCount > 1)
       
   248                 {
       
   249                 invalidContacts.append(COMMA_SEPERATOR);
       
   250                 }
       
   251             invalidContacts.append(addrlist.at(i)->alias());
       
   252            }
       
   253        else
       
   254            {
       
   255            mAddressMap.insertMulti(addrlist[i]->address(), addrlist[i]->alias());
       
   256            if(!addrlist[i]->alias().isEmpty())
       
   257               {
       
   258               mAddressEdit->setText(addrlist[i]->alias());
       
   259               }
       
   260            else
       
   261               {
       
   262               mAddressEdit->setText(addrlist[i]->address(), false);
       
   263               }
       
   264            }
       
   265        }
       
   266     if(invalidCount)
       
   267         {
       
   268         QString invalidStr;
       
   269         (invalidCount == 1)?(invalidStr = QString(LOC_INVALID_RECIPIENT_NOT_ADDED)) :(invalidStr = QString(LOC_INVALID_RECIPIENTS_NOT_ADDED));
       
   270         // append line seperator
       
   271          invalidStr.append("<br>");
       
   272          invalidStr.append(invalidContacts);
       
   273          HbMessageBox::information(invalidStr);
       
   274         }
       
   275 
       
   276     // addition operation complete, reset flags
       
   277     mAboutToExceedMaxSmsRecipients = false;
       
   278     mAboutToExceedMaxMmsRecipients = false;
       
   279     mExceedsMaxMmsRecipientsBy = 0;
       
   280 }
       
   281 
       
   282 int MsgUnifiedEditorAddress::contactMatchDigits()
       
   283 {
       
   284     // Read the amount of digits to be used in contact matching
       
   285     // The key is owned by PhoneApp
       
   286     int matchDigitCount = 0;
       
   287     TRAP_IGNORE(
       
   288         CRepository* repository = CRepository::NewLC(KCRUidTelConfiguration);
       
   289         if ( repository->Get(KTelMatchDigits, matchDigitCount) == KErrNone )
       
   290         {
       
   291             // Min is 7
       
   292             matchDigitCount = Max(matchDigitCount, KDefaultGsmNumberMatchLength);
       
   293         }
       
   294         CleanupStack::PopAndDestroy(); // repository
       
   295     );
       
   296     return matchDigitCount;
       
   297 }
       
   298 
       
   299 void MsgUnifiedEditorAddress::onContentsChanged(const QString& text)
       
   300 {
       
   301     // Max MMS recipient count check
       
   302     if( mAboutToExceedMaxMmsRecipients ||
       
   303         (MsgUnifiedEditorMonitor::msgAddressCount() >= MsgUnifiedEditorMonitor::maxMmsRecipients()) )
       
   304     {
       
   305         if(mAboutToExceedMaxMmsRecipients)
       
   306         {// show discreet note only once
       
   307             --mExceedsMaxMmsRecipientsBy;
       
   308             if(!mExceedsMaxMmsRecipientsBy)
       
   309             {
       
   310                 HbNotificationDialog::launchDialog(
       
   311                         LOC_MMS_RECIPIENT_LIMIT_REACHED);
       
   312             }
       
   313             resetToPrevious();
   174         }
   314         }
   175         else
   315         else
   176         {
   316         {
   177             mAddressEdit->setText(addrlist[i]->address());
   317             // update monitor data
   178         }
   318             emit contentChanged();
   179     }
   319             if(MsgUnifiedEditorMonitor::msgAddressCount() > MsgUnifiedEditorMonitor::maxMmsRecipients())
   180 }
   320             {
   181 
   321                 HbNotificationDialog::launchDialog(
   182 int MsgUnifiedEditorAddress::contactMatchDigits()
   322                         LOC_MMS_RECIPIENT_LIMIT_REACHED);
   183     {
   323                 resetToPrevious();
   184     // Read the amount of digits to be used in contact matching
   324                 // reset monitor data
   185     // The key is owned by PhoneApp    
   325                 emit contentChanged();
   186     CRepository* repository = CRepository::NewLC(KCRUidTelConfiguration);
   326             }
   187     int matchDigitCount = 0;
   327             else
   188     if ( repository->Get(KTelMatchDigits, matchDigitCount) == KErrNone )
   328             {
   189         {
   329                 mPrevBuffer = text;
   190     // Min is 7
   330             }
   191     matchDigitCount = Max(matchDigitCount, KDefaultGsmNumberMatchLength);
   331         }
   192         }
   332         return;
   193     CleanupStack::PopAndDestroy(); // repository
   333     }
   194 
   334 
   195     return matchDigitCount;
   335     // Max SMS recipient count check
   196 
   336     if( !mSkipMaxRecipientQuery &&
   197     }
   337         (MsgUnifiedEditorMonitor::messageType() == ConvergedMessage::Sms) &&
   198    
   338         (mAddressEdit->addresses().count() > MsgUnifiedEditorMonitor::maxSmsRecipients()) )
   199 void MsgUnifiedEditorAddress::onContentsAdded(const QString& text)
   339     {
   200 {
   340         // when we show this dialog, we don't want the intermediate states
   201     if(!text.isEmpty())
   341         // to be signalled to us
   202     {
       
   203         disconnect(mAddressEdit, SIGNAL(contentsChanged(const QString&)),
   342         disconnect(mAddressEdit, SIGNAL(contentsChanged(const QString&)),
   204                 this, SLOT(onContentsAdded(const QString&)));
   343                 this, SLOT(onContentsChanged(const QString&)));
       
   344         QTimer::singleShot(50, this, SLOT(handleRecipientLimitReached()));
       
   345     }
       
   346     else
       
   347     {
       
   348         if(!mAboutToExceedMaxSmsRecipients)
       
   349         {// remember addresses before the block insertion started
       
   350             mPrevBuffer = text;
       
   351         }
   205         emit contentChanged();
   352         emit contentChanged();
   206         connect(mAddressEdit, SIGNAL(contentsChanged(const QString&)),
   353     }
   207                 this, SLOT(onContentsRemoved(const QString&)));
   354 }
   208     }
   355 
   209 }
   356 void MsgUnifiedEditorAddress::handleRecipientLimitReached()
   210 
   357 {
   211 void MsgUnifiedEditorAddress::onContentsRemoved(const QString& text)
   358     HbMessageBox* dlg = new HbMessageBox(HbMessageBox::MessageTypeQuestion);
   212 {
   359     dlg->setAttribute(Qt::WA_DeleteOnClose);
   213     if(text.isEmpty())
   360     dlg->setFocusPolicy(Qt::NoFocus);
   214     {
   361     dlg->setTimeout(HbPopup::NoTimeout);
   215         disconnect(mAddressEdit, SIGNAL(contentsChanged(const QString&)),
   362 
   216                 this, SLOT(onContentsRemoved(const QString&)));
   363     dlg->setText(LOC_SMS_RECIPIENT_LIMIT_REACHED);
   217         emit contentChanged();
   364     
   218         connect(mAddressEdit, SIGNAL(contentsChanged(const QString&)),
   365     dlg->clearActions();
   219                 this, SLOT(onContentsAdded(const QString&)));
   366     HbAction* okAction = new HbAction(LOC_DIALOG_OK,dlg);
   220     }
   367     dlg->addAction(okAction);
       
   368 
       
   369     HbAction* cancelAction = new HbAction(LOC_BUTTON_CANCEL,dlg);
       
   370     dlg->addAction(cancelAction);
       
   371 
       
   372     dlg->open(this,SLOT(onMaxRecipientsReached(HbAction*)));
       
   373     // reconnect to get back updates
       
   374     connect(mAddressEdit, SIGNAL(contentsChanged(const QString&)),
       
   375             this, SLOT(onContentsChanged(const QString&)));
   221 }
   376 }
   222 
   377 
   223 void MsgUnifiedEditorAddress::syncDeletionsToMap()
   378 void MsgUnifiedEditorAddress::syncDeletionsToMap()
   224 {
   379 {
   225     // get address list from edit-field
   380     // get address list from edit-field
   234         {// if none are present, then delete entry from map
   389         {// if none are present, then delete entry from map
   235             i = mAddressMap.erase(i);
   390             i = mAddressMap.erase(i);
   236         }
   391         }
   237         else
   392         else
   238         {
   393         {
       
   394             // ensure that the matched contact is removed from the
       
   395             // address's list
       
   396             int matchedIndex = addrList.indexOf(i.value());
       
   397             if(matchedIndex == -1)
       
   398             {
       
   399                 matchedIndex = addrList.indexOf(i.key());
       
   400             }
       
   401             if(matchedIndex != -1)
       
   402             {
       
   403                 addrList.removeAt(matchedIndex);
       
   404             }
       
   405             // now go to next index in map
   239             ++i;
   406             ++i;
   240         }
   407         }
   241     }
   408     }
   242 }
   409 }
   243 
   410 
   244 void MsgUnifiedEditorAddress::syncAdditionsToMap()
   411 void MsgUnifiedEditorAddress::syncAdditionsToMap()
   245 {
   412 {
   246     QStringList mapAddrList = mAddressMap.values();
       
   247 
       
   248     // remove already mapped addresses from edit-field
   413     // remove already mapped addresses from edit-field
   249     QStringList userInputAddrList(mAddressEdit->addresses());
   414     QStringList userInputAddrList(mAddressEdit->addresses());
       
   415     QStringList mapAddrList = mAddressMap.values();
       
   416     mapAddrList << mAddressMap.keys();
   250     foreach(QString addr, mapAddrList)
   417     foreach(QString addr, mapAddrList)
   251     {
   418     {
   252         userInputAddrList.removeAll(addr);
   419         userInputAddrList.removeOne(addr);
   253     }
   420     }
   254 
   421 
   255     // add the unmapped addresses to address-map
   422     // add the unmapped addresses to address-map
   256     foreach(QString addr, userInputAddrList)
   423     foreach(QString addr, userInputAddrList)
   257     {
   424     {
   258         mAddressMap.insertMulti(addr, addr);
   425         mAddressMap.insertMulti(addr, QString());
   259     }
   426     }
   260 }
   427 }
   261 
   428 
   262 QStringList MsgUnifiedEditorAddress::uniqueAddressList()
   429 QStringList MsgUnifiedEditorAddress::uniqueAddressList()
   263 {
   430 {
   265     QStringList mapAddrList = mAddressMap.keys();
   432     QStringList mapAddrList = mAddressMap.keys();
   266     for(int j = 0;j<mapAddrList.count()-1;j++)
   433     for(int j = 0;j<mapAddrList.count()-1;j++)
   267     {
   434     {
   268         for(int i =j+1;i<mapAddrList.count();i++)
   435         for(int i =j+1;i<mapAddrList.count();i++)
   269         {
   436         {
   270             if(0 == mapAddrList[j].right(matchDigitCount).compare(mapAddrList[i].right(matchDigitCount)))     
   437             if(0 == mapAddrList[j].right(matchDigitCount).compare(mapAddrList[i].right(matchDigitCount)))
   271             {
   438             {
   272                mapAddrList.removeAt(i);
   439                mapAddrList.removeAt(i);
   273                i--;
   440                i--;
   274             }
   441             }
   275         }
   442         }
   276     }
   443     }
   277     return mapAddrList;
   444     return mapAddrList;
   278 }
   445 }
       
   446 
       
   447 // ----------------------------------------------------------------------------
       
   448 // MsgUnifiedEditorAddress::skipMaxRecipientQuery
       
   449 // @see header
       
   450 // ----------------------------------------------------------------------------
       
   451 void MsgUnifiedEditorAddress::skipMaxRecipientQuery(bool skip)
       
   452 {
       
   453     mSkipMaxRecipientQuery = skip;
       
   454 }
       
   455 
       
   456 void MsgUnifiedEditorAddress::setFocus()
       
   457 {
       
   458     mAddressEdit->setFocus(Qt::MouseFocusReason);
       
   459 }
       
   460 
       
   461 // ----------------------------------------------------------------------------
       
   462 // MsgUnifiedEditorAddress::resetToPrevious
       
   463 // @see header
       
   464 // ----------------------------------------------------------------------------
       
   465 void MsgUnifiedEditorAddress::resetToPrevious()
       
   466 {
       
   467     // when we do this reset operation, we don't want the intermediate states
       
   468     // to be signalled to us
       
   469     disconnect(mAddressEdit, SIGNAL(contentsChanged(const QString&)),
       
   470             this, SLOT(onContentsChanged(const QString&)));
       
   471 
       
   472     mAddressEdit->clearContent();
       
   473     QStringList list = mPrevBuffer.split(REPLACEMENT_STR,
       
   474             QString::SkipEmptyParts);
       
   475     int count = list.count();
       
   476     QStringList valList = mAddressMap.values();
       
   477     for(int i=0; i<count; i++)
       
   478     {
       
   479         QString addr = list.at(i);
       
   480         if(valList.contains(addr))
       
   481         {
       
   482             mAddressEdit->setText(addr);
       
   483         }
       
   484         else
       
   485         {
       
   486             mAddressEdit->setText(addr, false);
       
   487         }
       
   488     }
       
   489     syncDeletionsToMap();
       
   490     connect(mAddressEdit, SIGNAL(contentsChanged(const QString&)),
       
   491             this, SLOT(onContentsChanged(const QString&)));
       
   492 }
       
   493 
       
   494 // ----------------------------------------------------------------------------
       
   495 // MsgUnifiedEditorAddress::onMaxRecipientsReached
       
   496 // @see header
       
   497 // ----------------------------------------------------------------------------
       
   498 void MsgUnifiedEditorAddress::onMaxRecipientsReached(HbAction* action)
       
   499 {
       
   500     HbMessageBox *dlg = qobject_cast<HbMessageBox*> (sender());
       
   501     if (action == dlg->actions().at(0)) {
       
   502         // accept new content, update prev-buffer
       
   503         emit contentChanged();
       
   504         mPrevBuffer = mAddressEdit->content();
       
   505     }
       
   506     else {
       
   507         // reject the new content, keep the old
       
   508         resetToPrevious();
       
   509     }
       
   510 }
       
   511 
       
   512 // ----------------------------------------------------------------------------
       
   513 // MsgUnifiedEditorAddress::validateContacts
       
   514 // @see header
       
   515 // ----------------------------------------------------------------------------
       
   516 bool MsgUnifiedEditorAddress::validateContacts()
       
   517 {
       
   518     UniEditorGenUtils* genUtils = new UniEditorGenUtils;
       
   519 
       
   520     // sync-up map to account for user-actions on address-field
       
   521     syncDeletionsToMap();
       
   522     syncAdditionsToMap();
       
   523 
       
   524     // get the list of contacts in address-field
       
   525     QStringList fieldAddresses(mAddressEdit->addresses());
       
   526 
       
   527     bool isValid = true;
       
   528     foreach(QString addr, fieldAddresses)
       
   529     {
       
   530         // run address validation only if address is unmapped
       
   531         // (i.e. user-inserted)
       
   532         if(mAddressMap.contains(addr))
       
   533         {
       
   534         isValid = checkValidAddress(addr);
       
   535             if(!isValid)
       
   536             {
       
   537                 mAddressEdit->highlightInvalidString(addr);
       
   538                 QString invalidAddrStr =
       
   539                         QString(LOC_INVALID_RECIPIENT).arg(addr);
       
   540                 HbMessageBox* dlg = new HbMessageBox(invalidAddrStr,
       
   541                         HbMessageBox::MessageTypeInformation);
       
   542                 dlg->setDismissPolicy(HbPopup::TapInside);
       
   543                 dlg->setTimeout(HbPopup::NoTimeout);
       
   544                 dlg->setAttribute(Qt::WA_DeleteOnClose, true);
       
   545                 dlg->open(this, SLOT(handleInvalidContactDialog(HbAction*)));
       
   546                 break;
       
   547             }
       
   548         }
       
   549     }
       
   550 
       
   551     return isValid;
       
   552 }
       
   553 // ----------------------------------------------------------------------------
       
   554 // MsgUnifiedEditorAddress::checkValidAddress
       
   555 // @see header
       
   556 // ----------------------------------------------------------------------------
       
   557 bool MsgUnifiedEditorAddress::checkValidAddress(const QString& addr)
       
   558     {
       
   559     bool isValid = false;
       
   560     // 1. perform number validation
       
   561     isValid = CommonPhoneParser::IsValidPhoneNumber(
       
   562             *XQConversions::qStringToS60Desc(addr),
       
   563             CommonPhoneParser::ESMSNumber );
       
   564 
       
   565     // 2. if number validity fails, then perform email addr validation
       
   566     UniEditorGenUtils* genUtils = new UniEditorGenUtils;
       
   567     if(!isValid)
       
   568         { // additional check for MMS only
       
   569         isValid = genUtils->IsValidEmailAddress(
       
   570                     *XQConversions::qStringToS60Desc(addr) );
       
   571         }
       
   572     delete genUtils;
       
   573     return isValid;
       
   574     }
       
   575 
       
   576 void MsgUnifiedEditorAddress::handleInvalidContactDialog(
       
   577         HbAction* act)
       
   578 {
       
   579     Q_UNUSED(act);
       
   580     QTimer::singleShot(250, this, SLOT(setFocus()));
       
   581 }
       
   582 
       
   583 void MsgUnifiedEditorAddress::unblockSignals()
       
   584 {
       
   585     mLaunchBtn->blockSignals(false);
       
   586 }
       
   587 
   279 Q_IMPLEMENT_USER_METATYPE(CntServicesContact)
   588 Q_IMPLEMENT_USER_METATYPE(CntServicesContact)
   280 Q_IMPLEMENT_USER_METATYPE_NO_OPERATORS(CntServicesContactList)
   589 Q_IMPLEMENT_USER_METATYPE_NO_OPERATORS(CntServicesContactList)
   281 
   590 
   282 //EOF
   591 //EOF