Bug 131796

Summary: show only default address in 'Select recipient' dialog
Product: [Unmaintained] kmail Reporter: Christian Schaarschmidt <schaarsc>
Component: composerAssignee: Bruno Bigras <bigras.bruno>
Status: RESOLVED FIXED    
Severity: wishlist CC: bigras.bruno
Priority: NOR    
Version: 1.9.1   
Target Milestone: ---   
Platform: unspecified   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:
Attachments: recipientspicker tree patch

Description Christian Schaarschmidt 2006-08-03 19:12:20 UTC
Version:           1.9.1 (using KDE 3.5.3, Debian Package 4:3.5.3-1 (testing/unstable))
Compiler:          Target: i486-linux-gnu
OS:                Linux (i686) release 2.6.16.5

the 'select recipient' dialog shows all adresses for contacts in kaddressbook. I suggest to show default addresses only, the rest is hidden and can be shown on demand

e.g.
  Anna <anna@home>
+ Mike <mike@default>
  Zorro <zorro@work>

when I press the '+' I can see the rest as well
  Anna <anna@home>
- Mike <mike@default>
    |- <mike@work>
    |- <mike@home>
  Zorro <zorro@work>
Comment 1 Christian Schaarschmidt 2006-12-03 17:08:00 UTC
Created attachment 18767 [details]
recipientspicker tree patch

changes:
- use tree to show emails. node=preferredEmail, leave=alternativeEmail
- reorder comboBox dropdown list items
- insert seperator in list if necessary
- fix double entries for emails in recentEmails list
- fix recent emails collection wont show current typeLabel
Comment 2 Christian Schaarschmidt 2007-01-05 18:11:24 UTC
SVN commit 620313 by schaarsc:

- use tree to show emails. node=preferredEmail, leaf=alternativeEmail
- re-order comboBox dropdown list items
- insert seperator in dropdown list
- fix double entries for emails in recentEmails list
- fix recent emails collection wont show current typeLabel 

GUI:
CCBUG: 131796


 M  +153 -34   branches/work/kdepim-3.5.5+/kmail/recipientspicker.cpp  
 M  +25 -1     branches/work/kdepim-3.5.5+/kmail/recipientspicker.h  


--- branches/work/kdepim-3.5.5+/kmail/recipientspicker.cpp #620312:620313
@@ -45,6 +45,28 @@
 {
 }
 
+RecipientItem::RecipientItem( RecipientItem *preferredEmailItem )
+  : mDistributionList( 0 )
+{
+  preferredEmailItem->addAlternativeEmailItem( this );
+}
+
+bool RecipientItem::isDistributionList() const
+{
+  return mDistributionList != 0;
+}
+
+bool RecipientItem::operator==( const Recipient &recipient ) const
+{
+  QString name, email;
+  KABC::Addressee::parseEmailAddress( recipient.email(), name, email );
+
+  if( isDistributionList() )
+    return mDistributionList->name() == email;
+  else
+    return mEmail == email;
+}
+
 void RecipientItem::setDistributionList( KABC::DistributionList *list )
 {
   mDistributionList = list;
@@ -52,6 +74,17 @@
   mIcon = KGlobal::iconLoader()->loadIcon( "kdmconfig", KIcon::Small );
 
   mKey = "D" + list->name();
+
+  KABC::DistributionList::Entry::List entries = mDistributionList->entries();
+  KABC::DistributionList::Entry::List::ConstIterator it;
+  for( it = entries.begin(); it != entries.end(); ++it ) {
+    RecipientItem *item = new RecipientItem( this );
+    if ( (*it).email.isEmpty() ) 
+      item->setAddressee( (*it).addressee, (*it).addressee.preferredEmail() );
+    else 
+      item->setAddressee( (*it).addressee, (*it).email );
+  }
+    
 }
 
 void RecipientItem::setAddressee( const KABC::Addressee &a,
@@ -66,7 +99,7 @@
   else
     mIcon = KGlobal::iconLoader()->loadIcon( "personal", KIcon::Small );
 
-  mKey = "A" + a.preferredEmail();
+  mKey = "A" + email; 
 }
 
 QPixmap RecipientItem::icon() const
@@ -140,17 +173,37 @@
   return mType;
 }
 
+void RecipientItem::addAlternativeEmailItem( RecipientItem *altRecipientItem )
+{
+  mAlternativeEmailList.append( altRecipientItem );
+}
 
+const RecipientItem::List RecipientItem::alternativeEmailList() const
+{
+  return mAlternativeEmailList;
+}
+
+
 RecipientViewItem::RecipientViewItem( RecipientItem *item, KListView *listView )
   : KListViewItem( listView ), mRecipientItem( item )
 {
-  setText( 0, item->recipientType() );
-  setText( 1, item->name() );
-  setText( 2, item->email() );
+  setText( 0, item->name() );
+  setText( 1, item->email() );
+  setText( 2, " " + item->recipientType() );
 
-  setPixmap( 1, item->icon() );
+  setPixmap( 0, item->icon() );
 }
 
+RecipientViewItem::RecipientViewItem( RecipientItem *item, RecipientViewItem *viewItem )
+  : KListViewItem( viewItem ), mRecipientItem( item )
+{
+  setText( 0, item->name() );
+  setText( 1, item->email() );
+  setText( 2, " " + item->recipientType() );
+
+  setPixmap( 0, item->icon() );
+}
+
 RecipientItem *RecipientViewItem::recipientItem() const
 {
   return mRecipientItem;
@@ -204,6 +257,19 @@
   mItems.append( item );
 
   mKeyMap.insert( item->key(), item );
+
+  RecipientItem::List altList = item->alternativeEmailList();
+  RecipientItem::List::ConstIterator altIt;
+  for( altIt = altList.begin(); altIt != altList.end(); ++altIt ) {
+    if( item->isDistributionList() ){
+      //add them here to make sure they get deleted, 
+      //but invalidate key to make sure they don't replace original item
+      mKeyMap.insert( "X" + (*altIt)->key(), *altIt );
+    }else{
+      mKeyMap.insert( (*altIt)->key(), *altIt );
+    }
+  }
+    
 }
 
 RecipientItem::List RecipientsCollection::items() const
@@ -216,9 +282,15 @@
   return mKeyMap.find( item->key() ) != mKeyMap.end();
 }
 
+RecipientItem* RecipientsCollection::equivalentItem( RecipientItem *item ) const
+{
+  return mKeyMap[ item->key() ];
+}
+
 void RecipientsCollection::clear()
 {
   mKeyMap.clear();
+  mItems.clear();
 }
 
 void RecipientsCollection::deleteAll()
@@ -244,6 +316,8 @@
 }
 
 
+const QString RecipientsPicker::mSeperatorString = " ---- ";
+
 RecipientsPicker::RecipientsPicker( QWidget *parent )
   : QDialog( parent, "RecipientsPicker" ),
   mDistributionListManager( 0 )
@@ -282,13 +356,16 @@
   searchLayout->addWidget( label );
 
   mRecipientList = new KListView( this );
+  mRecipientList->setRootIsDecorated( true );
   mRecipientList->setSelectionMode( QListView::Extended );
   mRecipientList->setAllColumnsShowFocus( true );
   mRecipientList->setFullWidth( true );
   topLayout->addWidget( mRecipientList );
-  mRecipientList->addColumn( i18n("->") );
   mRecipientList->addColumn( i18n("Name") );
   mRecipientList->addColumn( i18n("Email") );
+  mRecipientList->addColumn( i18n("->") );
+  mRecipientList->setColumnWidth( 0, 250 );
+  mRecipientList->setColumnWidth( 1, 250 );
   connect( mRecipientList, SIGNAL( doubleClicked( QListViewItem *,
     const QPoint &, int ) ), SLOT( slotPicked() ) );
   connect( mRecipientList, SIGNAL( returnPressed( QListViewItem * ) ),
@@ -365,15 +442,23 @@
   mAllRecipients->setTitle( i18n("All") );
   insertCollection( mAllRecipients );
 
-  insertAddressBook( mAddressBook );
+  mSelectedRecipients = new RecipientsCollection;
+  mSelectedRecipients->setTitle( i18n("Selected Recipients") );
+  insertCollection( mSelectedRecipients );
 
+  /* we want recentAddresses at this position in the ComboBox, but need a 
+   * filled mAddressBook to find duplicates. 
+   * Solution: add empty RecipientsCollection and fill later.
+   */
+  RecipientsCollection* recentAddresses = new RecipientsCollection;
+  recentAddresses->setTitle( i18n("Recent Addresses") );
+  insertCollection( recentAddresses );
+
   insertDistributionLists();
 
-  insertRecentAddresses();
+  insertAddressBook( mAddressBook );
 
-  mSelectedRecipients = new RecipientsCollection;
-  mSelectedRecipients->setTitle( i18n("Selected Recipients") );
-  insertCollection( mSelectedRecipients );
+  fillRecentAddresses( recentAddresses );
 }
 
 void RecipientsPicker::insertAddressBook( KABC::AddressBook *addressbook )
@@ -393,16 +478,23 @@
   KABC::AddressBook::Iterator it;
   for( it = addressbook->begin(); it != addressbook->end(); ++it ) {
     QStringList emails = (*it).emails();
-    QStringList::ConstIterator it3;
-    for( it3 = emails.begin(); it3 != emails.end(); ++it3 ) {
-      RecipientItem *item = new RecipientItem;
-      item->setAddressee( *it, *it3 );
-      mAllRecipients->addItem( item );
+    QStringList::ConstIterator emailIt;
+    emailIt = emails.begin();
 
+    //preferredEmail is first in list
+    RecipientItem *preferredEmailItem = new RecipientItem;
+    preferredEmailItem->setAddressee( *it, *emailIt );
+
+    for( emailIt++; emailIt != emails.end(); ++emailIt ) {
+      RecipientItem *item = new RecipientItem( preferredEmailItem );
+      item->setAddressee( *it, *emailIt );
+    }
+    mAllRecipients->addItem( preferredEmailItem ); //add to all emails collection, including children
+
       QMap<KABC::Resource *,RecipientsCollection *>::ConstIterator collIt;
       collIt = collectionMap.find( it->resource() );
       if ( collIt != collectionMap.end() ) {
-        (*collIt)->addItem( item );
+        (*collIt)->addItem( preferredEmailItem ); //add to resource collection
       }
 
       QStringList categories = (*it).categories();
@@ -418,16 +510,29 @@
         } else {
           collection = *catMapIt;
         }
-        collection->addItem( item );
+        collection->addItem( preferredEmailItem ); //add to categories collection 
       }
-    }
   }
 
+  /* add seperator if there are address books. 
+   * this helps organizing long list in the comboBox.
+   */
+  if ( collectionMap.size() >= 1 ) {
+    RecipientsCollection* seperator = new RecipientsCollection;
+    seperator->setTitle( mSeperatorString + i18n( "Address Books" ) + mSeperatorString );
+    insertCollection( seperator );
+  }
   QMap<KABC::Resource *,RecipientsCollection *>::ConstIterator it2;
   for( it2 = collectionMap.begin(); it2 != collectionMap.end(); ++it2 ) {
     insertCollection( *it2 );
   }
 
+  // add seperator if there are categories.
+  if ( categoryMap.size() >= 1 ) {
+    RecipientsCollection* seperator = new RecipientsCollection;
+    seperator->setTitle( mSeperatorString + i18n( "Categories" ) + mSeperatorString );
+    insertCollection( seperator );
+  }
   QMap<QString, RecipientsCollection *>::ConstIterator it3;
   for( it3 = categoryMap.begin(); it3 != categoryMap.end(); ++it3 ) {
     insertCollection( *it3 );
@@ -461,10 +566,9 @@
   insertCollection( collection );
 }
 
-void RecipientsPicker::insertRecentAddresses()
+void RecipientsPicker::fillRecentAddresses( RecipientsCollection *collection )
 {
-  RecipientsCollection *collection = new RecipientsCollection;
-  collection->setTitle( i18n("Recent Addresses") );
+  Q_ASSERT( collection != 0 );
 
   KConfig config( "kmailrc" );
   KABC::Addressee::List recents =
@@ -476,11 +580,13 @@
     item->setAddressee( *it, (*it).preferredEmail() );
     if ( !mAllRecipients->hasEquivalentItem( item ) ) {
       mAllRecipients->addItem( item );
+      collection->addItem( item );
+    } else {
+      collection->addItem( mAllRecipients->equivalentItem( item ) );
+      delete item;
     }
-    collection->addItem( item );
   }
 
-  insertCollection( collection );
 }
 
 void RecipientsPicker::insertCollection( RecipientsCollection *coll )
@@ -496,10 +602,9 @@
 
 void RecipientsPicker::updateRecipient( const Recipient &recipient )
 {
-  RecipientItem::List allRecipients = mAllRecipients->items();
-  RecipientItem::List::ConstIterator itAll;
-  for( itAll = allRecipients.begin(); itAll != allRecipients.end(); ++itAll ) {
-    if ( (*itAll)->recipient() == recipient.email() ) {
+  RecipientsCollection::ConstIterator itAll;
+  for( itAll = mAllRecipients->begin(); itAll != mAllRecipients->end(); ++itAll ) {
+    if ( *(*itAll) == recipient ) {
       (*itAll)->setRecipientType( recipient.typeLabel() );
     }
   }
@@ -508,9 +613,8 @@
 
 void RecipientsPicker::setRecipients( const Recipient::List &recipients )
 {
-  RecipientItem::List allRecipients = mAllRecipients->items();
-  RecipientItem::List::ConstIterator itAll;
-  for( itAll = allRecipients.begin(); itAll != allRecipients.end(); ++itAll ) {
+  RecipientsCollection::ConstIterator itAll;
+  for( itAll = mAllRecipients->begin(); itAll != mAllRecipients->end(); ++itAll ) {
     (*itAll)->setRecipientType( QString::null );
   }
 
@@ -519,8 +623,8 @@
   Recipient::List::ConstIterator it;
   for( it = recipients.begin(); it != recipients.end(); ++it ) {
     RecipientItem *item = 0;
-    for( itAll = allRecipients.begin(); itAll != allRecipients.end(); ++itAll ) {
-      if ( (*itAll)->recipient() == (*it).email() ) {
+    for( itAll = mAllRecipients->begin(); itAll != mAllRecipients->end(); ++itAll ) {
+      if ( *(*itAll) == (*it) ) {
         (*itAll)->setRecipientType( (*it).typeLabel() );
         item = *itAll;
       }
@@ -567,12 +671,27 @@
 {
   mRecipientList->clear();
 
+  //skip seperator, pick first item below
+  const QString currentText = mCollectionCombo->currentText();
+  if ( currentText.startsWith( mSeperatorString ) ) {
+    mCollectionCombo->blockSignals( true );
+    mCollectionCombo->setCurrentItem( mCollectionCombo->currentItem() + 1 );
+    mCollectionCombo->blockSignals( false );
+  }
+
   RecipientsCollection *coll = mCollectionMap[ mCollectionCombo->currentItem() ];
 
   RecipientItem::List items = coll->items();
   RecipientItem::List::ConstIterator it;
   for( it = items.begin(); it != items.end(); ++it ) {
-    new RecipientViewItem( *it, mRecipientList );
+    RecipientViewItem *stdItem = new RecipientViewItem( *it, mRecipientList );
+    RecipientItem::List altList = (*it)->alternativeEmailList();
+    RecipientItem::List::ConstIterator altIt;
+    for( altIt = altList.begin(); altIt != altList.end(); ++altIt ) {
+      new RecipientViewItem( *altIt, stdItem );
+      if ( ! (*altIt)->recipientType().isEmpty() && ! (*it)->isDistributionList() )
+        stdItem->setOpen( true );
+    }
   }
 
   mSearchLine->updateSearch();
--- branches/work/kdepim-3.5.5+/kmail/recipientspicker.h #620312:620313
@@ -45,6 +45,7 @@
     typedef QValueList<RecipientItem *> List;
 
     RecipientItem();
+    RecipientItem( RecipientItem *);
 
     void setDistributionList( KABC::DistributionList * );
     void setAddressee( const KABC::Addressee &, const QString &email );
@@ -62,6 +63,11 @@
 
     QString toolTip() const;
 
+    void addAlternativeEmailItem( RecipientItem * );
+    const List alternativeEmailList() const;
+    bool isDistributionList() const;
+    bool operator==( const Recipient& ) const;
+
   private:
     KABC::Addressee mAddressee;
     QString mEmail;
@@ -71,12 +77,15 @@
     QPixmap mIcon;
 
     QString mKey;
+
+    List mAlternativeEmailList;
 };
 
 class RecipientViewItem : public KListViewItem
 {
   public:
     RecipientViewItem( RecipientItem *, KListView * );
+    RecipientViewItem( RecipientItem *, RecipientViewItem * );
 
     RecipientItem *recipientItem() const;
 
@@ -99,6 +108,14 @@
 class RecipientsCollection
 {
   public:
+    typedef QMapConstIterator<QString, RecipientItem*> ConstIterator;
+    /**
+     * @return iterator to iterate over <b>all</b> items
+     * @see items()
+     */
+    ConstIterator begin(){return mKeyMap.begin();}
+    ConstIterator end()  {return mKeyMap.end();}
+
     RecipientsCollection();
     ~RecipientsCollection();
 
@@ -107,9 +124,14 @@
 
     void addItem( RecipientItem * );
 
+    /**
+     * @return top level items
+     * @see begin()
+     */
     RecipientItem::List items() const;
 
     bool hasEquivalentItem( RecipientItem * ) const;
+    RecipientItem* equivalentItem( RecipientItem * ) const;
 
     void clear();
 
@@ -154,7 +176,7 @@
   protected:
     void initCollections();
     void insertDistributionLists();
-    void insertRecentAddresses();
+    void fillRecentAddresses( RecipientsCollection* coll );
     void insertCollection( RecipientsCollection *coll );
 
     void keyPressEvent( QKeyEvent *ev );
@@ -195,6 +217,8 @@
     KABC::DistributionListManager *mDistributionListManager;
 
     Recipient::Type mDefaultType;
+
+    static const QString mSeperatorString;
 };
 
 #endif
Comment 3 Bruno Bigras 2009-08-05 23:35:18 UTC
SVN commit 1007527 by bbigras:

Show only default addresses in 'Select recipient' dialog. Based on a
commit from Christian Schaarschmidt on the 3.5.5+ branch.
BUG: 131796

 M  +127 -38   recipientspicker.cpp  
 M  +13 -0     recipientspicker.h  


WebSVN link: http://websvn.kde.org/?view=rev&revision=1007527