summaryrefslogtreecommitdiffstats
path: root/libkdepim/addresseelineedit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libkdepim/addresseelineedit.cpp')
-rw-r--r--libkdepim/addresseelineedit.cpp354
1 files changed, 250 insertions, 104 deletions
diff --git a/libkdepim/addresseelineedit.cpp b/libkdepim/addresseelineedit.cpp
index 7031a83eb..5e3d0cf39 100644
--- a/libkdepim/addresseelineedit.cpp
+++ b/libkdepim/addresseelineedit.cpp
@@ -70,12 +70,23 @@ KPIM::LdapSearch* AddresseeLineEdit::s_LDAPSearch = 0L;
TQString* AddresseeLineEdit::s_LDAPText = 0L;
AddresseeLineEdit* AddresseeLineEdit::s_LDAPLineEdit = 0L;
+// The weights associated with the completion sources in s_completionSources.
+// Both are maintained by addCompletionSource(), don't attempt to modifiy those yourself.
+TQMap<TQString,int>* s_completionSourceWeights = 0;
+
+// maps LDAP client indices to completion source indices
+// the assumption that they are always the first n indices in s_completion
+// does not hold when clients are added later on
+TQMap<int, int>* AddresseeLineEdit::s_ldapClientToCompletionSourceMap = 0;
+
static KStaticDeleter<KMailCompletion> completionDeleter;
static KStaticDeleter<KPIM::CompletionItemsMap> completionItemsDeleter;
static KStaticDeleter<TQTimer> ldapTimerDeleter;
static KStaticDeleter<KPIM::LdapSearch> ldapSearchDeleter;
static KStaticDeleter<TQString> ldapTextDeleter;
static KStaticDeleter<TQStringList> completionSourcesDeleter;
+static KStaticDeleter<TQMap<TQString,int> > completionSourceWeightsDeleter;
+static KStaticDeleter<TQMap<int, int> > ldapClientToCompletionSourceMapDeleter;
// needs to be unique, but the actual name doesn't matter much
static TQCString newLineEditDCOPObjectName()
@@ -100,7 +111,8 @@ static bool itemIsHeader( const TQListBoxItem* item )
AddresseeLineEdit::AddresseeLineEdit( TQWidget* parent, bool useCompletion,
const char *name )
- : ClickLineEdit( parent, TQString::null, name ), DCOPObject( newLineEditDCOPObjectName() )
+ : ClickLineEdit( parent, TQString::null, name ), DCOPObject( newLineEditDCOPObjectName() ),
+ m_useSemiColonAsSeparator( false ), m_allowDistLists( true )
{
m_useCompletion = useCompletion;
m_completionInitialized = false;
@@ -114,6 +126,18 @@ AddresseeLineEdit::AddresseeLineEdit( TQWidget* parent, bool useCompletion,
s_addressesDirty = true;
}
+void AddresseeLineEdit::updateLDAPWeights()
+{
+ /* Add completion sources for all ldap server, 0 to n. Added first so
+ * that they map to the ldapclient::clientNumber() */
+ s_LDAPSearch->updateCompletionWeights();
+ TQValueList< LdapClient* > clients = s_LDAPSearch->clients();
+ int clientIndex = 0;
+ for ( TQValueList<LdapClient*>::iterator it = clients.begin(); it != clients.end(); ++it, ++clientIndex ) {
+ const int sourceIndex = addCompletionSource( "LDAP server: " + (*it)->server().host(), (*it)->completionWeight() );
+ s_ldapClientToCompletionSourceMap->insert( clientIndex, sourceIndex );
+ }
+}
void AddresseeLineEdit::init()
{
@@ -124,8 +148,9 @@ void AddresseeLineEdit::init()
completionItemsDeleter.setObject( s_completionItemMap, new KPIM::CompletionItemsMap() );
completionSourcesDeleter.setObject( s_completionSources, new TQStringList() );
+ completionSourceWeightsDeleter.setObject( s_completionSourceWeights, new TQMap<TQString,int> );
+ ldapClientToCompletionSourceMapDeleter.setObject( s_ldapClientToCompletionSourceMap, new TQMap<int,int> );
}
-
// connect( s_completion, TQT_SIGNAL( match( const TQString& ) ),
// this, TQT_SLOT( slotMatched( const TQString& ) ) );
@@ -134,14 +159,10 @@ void AddresseeLineEdit::init()
ldapTimerDeleter.setObject( s_LDAPTimer, new TQTimer( 0, "ldapTimerDeleter" ) );
ldapSearchDeleter.setObject( s_LDAPSearch, new KPIM::LdapSearch );
ldapTextDeleter.setObject( s_LDAPText, new TQString );
-
- /* Add completion sources for all ldap server, 0 to n. Added first so
- * that they map to the ldapclient::clientNumber() */
- TQValueList< LdapClient* > clients = s_LDAPSearch->clients();
- for ( TQValueList<LdapClient*>::iterator it = clients.begin(); it != clients.end(); ++it ) {
- addCompletionSource( "LDAP server: " + (*it)->server().host() );
- }
}
+
+ updateLDAPWeights();
+
if ( !m_completionInitialized ) {
setCompletionObject( s_completion, false );
connect( this, TQT_SIGNAL( completion( const TQString& ) ),
@@ -187,6 +208,11 @@ void AddresseeLineEdit::allowSemiColonAsSeparator( bool useSemiColonAsSeparator
m_useSemiColonAsSeparator = useSemiColonAsSeparator;
}
+void AddresseeLineEdit::allowDistributionLists( bool allowDistLists )
+{
+ m_allowDistLists = allowDistLists;
+}
+
void AddresseeLineEdit::keyPressEvent( TQKeyEvent *e )
{
bool accept = false;
@@ -206,9 +232,15 @@ void AddresseeLineEdit::keyPressEvent( TQKeyEvent *e )
}
}
+ const TQString oldContent = text();
if ( !accept )
KLineEdit::keyPressEvent( e );
+ // if the text didn't change (eg. because a cursor navigation key was pressed)
+ // we don't need to trigger a new search
+ if ( oldContent == text() )
+ return;
+
if ( e->isAccepted() ) {
updateSearchString();
TQString searchString( m_searchString );
@@ -264,24 +296,25 @@ void AddresseeLineEdit::insert( const TQString &t )
TQString contents = text();
int start_sel = 0;
- int end_sel = 0;
int pos = cursorPosition( );
- if ( getSelection( &start_sel, &end_sel ) ) {
+
+ if ( hasSelectedText() ) {
// Cut away the selection.
- if ( pos > end_sel )
- pos -= (end_sel - start_sel);
- else if ( pos > start_sel )
- pos = start_sel;
- contents = contents.left( start_sel ) + contents.right( end_sel + 1 );
+ start_sel = selectionStart();
+ pos = start_sel;
+ contents = contents.left( start_sel ) + contents.mid( start_sel + selectedText().length() );
}
int eot = contents.length();
- while ((eot > 0) && contents[ eot - 1 ].isSpace() ) eot--;
- if ( eot == 0 )
+ while ( ( eot > 0 ) && contents[ eot - 1 ].isSpace() ) {
+ eot--;
+ }
+ if ( eot == 0 ) {
contents = TQString::null;
- else if ( pos >= eot ) {
- if ( contents[ eot - 1 ] == ',' )
+ } else if ( pos >= eot ) {
+ if ( contents[ eot - 1 ] == ',' ) {
eot--;
+ }
contents.truncate( eot );
contents += ", ";
pos = eot + 2;
@@ -324,35 +357,45 @@ void AddresseeLineEdit::mouseReleaseEvent( TQMouseEvent *e )
void AddresseeLineEdit::dropEvent( TQDropEvent *e )
{
KURL::List uriList;
- if ( !isReadOnly()
- && KURLDrag::canDecode(e) && KURLDrag::decode( e, uriList ) ) {
- TQString contents = text();
- // remove trailing white space and comma
- int eot = contents.length();
- while ( ( eot > 0 ) && contents[ eot - 1 ].isSpace() )
- eot--;
- if ( eot == 0 )
- contents = TQString::null;
- else if ( contents[ eot - 1 ] == ',' ) {
- eot--;
- contents.truncate( eot );
- }
- bool mailtoURL = false;
- // append the mailto URLs
- for ( KURL::List::Iterator it = uriList.begin();
- it != uriList.end(); ++it ) {
- if ( !contents.isEmpty() )
- contents.append( ", " );
- KURL u( *it );
- if ( u.protocol() == "mailto" ) {
- mailtoURL = true;
- contents.append( (*it).path() );
+ if ( !isReadOnly() ) {
+ if ( KURLDrag::canDecode(e) && KURLDrag::decode( e, uriList ) ) {
+ TQString contents = text();
+ // remove trailing white space and comma
+ int eot = contents.length();
+ while ( ( eot > 0 ) && contents[ eot - 1 ].isSpace() )
+ eot--;
+ if ( eot == 0 )
+ contents = TQString::null;
+ else if ( contents[ eot - 1 ] == ',' ) {
+ eot--;
+ contents.truncate( eot );
+ }
+ bool mailtoURL = false;
+ // append the mailto URLs
+ for ( KURL::List::Iterator it = uriList.begin();
+ it != uriList.end(); ++it ) {
+ if ( !contents.isEmpty() )
+ contents.append( ", " );
+ KURL u( *it );
+ if ( u.protocol() == "mailto" ) {
+ mailtoURL = true;
+ contents.append( (*it).path() );
+ }
+ }
+ if ( mailtoURL ) {
+ setText( contents );
+ setEdited( true );
+ return;
+ }
+ } else {
+ // Let's see if this drop contains a comma separated list of emails
+ TQString dropData = TQString::fromUtf8( e->encodedData( "text/plain" ) );
+ TQStringList addrs = splitEmailAddrList( dropData );
+ if ( addrs.count() > 0 ) {
+ setText( normalizeAddressesAndDecodeIDNs( dropData ) );
+ setEdited( true );
+ return;
}
- }
- if ( mailtoURL ) {
- setText( contents );
- setEdited( true );
- return;
}
}
@@ -526,21 +569,19 @@ void AddresseeLineEdit::loadContacts()
TQString uid = (*it).uid();
TQMap<TQString, TQString>::const_iterator wit = uidToResourceMap.find( uid );
const TQString subresourceLabel = resabc->subresourceLabel( *wit );
- int idx = s_completionSources->findIndex( subresourceLabel );
- if ( idx == -1 ) {
- s_completionSources->append( subresourceLabel );
- idx = s_completionSources->size() -1;
- }
- int weight = ( wit != uidToResourceMap.end() ) ? resabc->subresourceCompletionWeight( *wit ) : 80;
+ const int weight = ( wit != uidToResourceMap.end() ) ? resabc->subresourceCompletionWeight( *wit ) : 80;
+ const int idx = addCompletionSource( subresourceLabel, weight );
+
//kdDebug(5300) << (*it).fullEmail() << " subres=" << *wit << " weight=" << weight << endl;
addContact( *it, weight, idx );
}
} else { // KABC non-imap resource
int weight = config.readNumEntry( resource->identifier(), 60 );
- s_completionSources->append( resource->resourceName() );
+ int sourceIndex = addCompletionSource( resource->resourceName(), weight );
KABC::Resource::Iterator it;
- for ( it = resource->begin(); it != resource->end(); ++it )
- addContact( *it, weight, s_completionSources->size()-1 );
+ for ( it = resource->begin(); it != resource->end(); ++it ) {
+ addContact( *it, weight, sourceIndex );
+ }
}
}
@@ -577,12 +618,14 @@ void AddresseeLineEdit::addContact( const KABC::Addressee& addr, int weight, int
if ( KPIM::DistributionList::isDistributionList( addr ) ) {
//kdDebug(5300) << "AddresseeLineEdit::addContact() distribution list \"" << addr.formattedName() << "\" weight=" << weight << endl;
- //for CompletionAuto
- addCompletionItem( addr.formattedName(), weight, source );
+ if ( m_allowDistLists ) {
+ //for CompletionAuto
+ addCompletionItem( addr.formattedName(), weight, source );
- //for CompletionShell, CompletionPopup
- TQStringList sl( addr.formattedName() );
- addCompletionItem( addr.formattedName(), weight, source, &sl );
+ //for CompletionShell, CompletionPopup
+ TQStringList sl( addr.formattedName() );
+ addCompletionItem( addr.formattedName(), weight, source, &sl );
+ }
return;
}
@@ -730,6 +773,11 @@ void AddresseeLineEdit::addCompletionItem( const TQString& string, int weight, i
void AddresseeLineEdit::slotStartLDAPLookup()
{
+ KGlobalSettings::Completion mode = completionMode();
+
+ if ( mode == KGlobalSettings::CompletionNone )
+ return;
+
if ( !s_LDAPSearch->isAvailable() ) {
return;
}
@@ -765,7 +813,7 @@ void AddresseeLineEdit::startLoadingLDAPEntries()
void AddresseeLineEdit::slotLDAPSearchData( const KPIM::LdapResultList& adrs )
{
- if ( s_LDAPLineEdit != this )
+ if ( adrs.isEmpty() || s_LDAPLineEdit != this )
return;
for ( KPIM::LdapResultList::ConstIterator it = adrs.begin(); it != adrs.end(); ++it ) {
@@ -773,14 +821,20 @@ void AddresseeLineEdit::slotLDAPSearchData( const KPIM::LdapResultList& adrs )
addr.setNameFromString( (*it).name );
addr.setEmails( (*it).email );
- addContact( addr, (*it).completionWeight, (*it ).clientNumber );
+ if ( !s_ldapClientToCompletionSourceMap->contains( (*it).clientNumber ) )
+ updateLDAPWeights(); // we got results from a new source, so update the completion sources
+
+ addContact( addr, (*it).completionWeight, (*s_ldapClientToCompletionSourceMap)[ (*it ).clientNumber ] );
}
if ( (hasFocus() || completionBox()->hasFocus() )
&& completionMode() != KGlobalSettings::CompletionNone
- && completionMode() != KGlobalSettings::CompletionShell) {
+ && completionMode() != KGlobalSettings::CompletionShell ) {
setText( m_previousAddresses + m_searchString );
- doCompletion( m_lastSearchMode );
+ // only complete again if the user didn't change the selection while we were waiting
+ // otherwise the completion box will be closed
+ if ( m_searchString.stripWhiteSpace() != completionBox()->currentText().stripWhiteSpace() )
+ doCompletion( m_lastSearchMode );
}
}
@@ -881,6 +935,10 @@ void AddresseeLineEdit::slotEditCompletionOrder()
init(); // for s_LDAPSearch
CompletionOrderEditor editor( s_LDAPSearch, this );
editor.exec();
+ if ( m_useCompletion ) {
+ updateLDAPWeights();
+ s_addressesDirty = true;
+ }
}
void KPIM::AddresseeLineEdit::slotIMAPCompletionOrderChanged()
@@ -902,15 +960,23 @@ void AddresseeLineEdit::updateSearchString()
int n = -1;
bool inQuote = false;
- for ( uint i = 0; i < m_searchString.length(); ++i ) {
- if ( m_searchString[ i ] == '"' )
+ uint searchStringLength = m_searchString.length();
+ for ( uint i = 0; i < searchStringLength; ++i ) {
+ if ( m_searchString[ i ] == '"' ) {
inQuote = !inQuote;
- if ( m_searchString[ i ] == '\\' && (i + 1) < m_searchString.length() && m_searchString[ i + 1 ] == '"' )
+ }
+ if ( m_searchString[ i ] == '\\' &&
+ (i + 1) < searchStringLength && m_searchString[ i + 1 ] == '"' ) {
++i;
- if ( inQuote )
+ }
+ if ( inQuote ) {
continue;
- if ( m_searchString[ i ] == ',' || ( m_useSemiColonAsSeparator && m_searchString[ i ] == ';' ) )
+ }
+ if ( i < searchStringLength &&
+ ( m_searchString[ i ] == ',' ||
+ ( m_useSemiColonAsSeparator && m_searchString[ i ] == ';' ) ) ) {
n = i;
+ }
}
if ( n >= 0 ) {
@@ -924,9 +990,7 @@ void AddresseeLineEdit::updateSearchString()
m_previousAddresses = m_searchString.left( n );
m_searchString = m_searchString.mid( n ).stripWhiteSpace();
- }
- else
- {
+ } else {
m_previousAddresses = TQString::null;
}
}
@@ -954,18 +1018,30 @@ KCompletion::CompOrder KPIM::AddresseeLineEdit::completionOrder()
return KCompletion::Sorted;
}
-int KPIM::AddresseeLineEdit::addCompletionSource( const TQString &source )
+int KPIM::AddresseeLineEdit::addCompletionSource( const TQString &source, int weight )
{
- s_completionSources->append( source );
- return s_completionSources->size()-1;
+ TQMap<TQString,int>::iterator it = s_completionSourceWeights->find( source );
+ if ( it == s_completionSourceWeights->end() )
+ s_completionSourceWeights->insert( source, weight );
+ else
+ (*s_completionSourceWeights)[source] = weight;
+
+ int sourceIndex = s_completionSources->findIndex( source );
+ if ( sourceIndex == -1 ) {
+ s_completionSources->append( source );
+ return s_completionSources->size() - 1;
+ }
+ else
+ return sourceIndex;
}
bool KPIM::AddresseeLineEdit::eventFilter(TQObject *obj, TQEvent *e)
{
if ( obj == completionBox() ) {
- if ( e->type() == TQEvent::MouseButtonPress
- || e->type() == TQEvent::MouseMove
- || e->type() == TQEvent::MouseButtonRelease ) {
+ if ( e->type() == TQEvent::MouseButtonPress ||
+ e->type() == TQEvent::MouseMove ||
+ e->type() == TQEvent::MouseButtonRelease ||
+ e->type() == TQEvent::MouseButtonDblClick ) {
TQMouseEvent* me = static_cast<TQMouseEvent*>( e );
// find list box item at the event position
TQListBoxItem *item = completionBox()->itemAt( me->pos() );
@@ -1003,26 +1079,35 @@ bool KPIM::AddresseeLineEdit::eventFilter(TQObject *obj, TQEvent *e)
}
}
if ( ( obj == this ) &&
- ( e->type() == TQEvent::KeyPress ) &&
- completionBox()->isVisible() ) {
+ ( e->type() == TQEvent::KeyPress || e->type() == TQEvent::KeyRelease ) &&
+ completionBox()->isVisible() ) {
TQKeyEvent *ke = static_cast<TQKeyEvent*>( e );
- unsigned int currentIndex = completionBox()->currentItem();
+ int currentIndex = completionBox()->currentItem();
+ if ( currentIndex < 0 ) {
+ return true;
+ }
+
if ( ke->key() == Key_Up ) {
//kdDebug() << "EVENTFILTER: Key_Up currentIndex=" << currentIndex << endl;
// figure out if the item we would be moving to is one we want
// to ignore. If so, go one further
- TQListBoxItem *itemAbove = completionBox()->item( currentIndex - 1 );
+ TQListBoxItem *itemAbove = completionBox()->item( currentIndex );
if ( itemAbove && itemIsHeader(itemAbove) ) {
// there is a header above us, check if there is even further up
// and if so go one up, so it'll be selected
- if ( currentIndex > 1 && completionBox()->item( currentIndex - 2 ) ) {
+ if ( currentIndex > 0 && completionBox()->item( currentIndex - 1 ) ) {
//kdDebug() << "EVENTFILTER: Key_Up -> skipping " << currentIndex - 1 << endl;
completionBox()->setCurrentItem( itemAbove->prev() );
- completionBox()->setSelected( currentIndex - 2, true );
- } else if ( currentIndex == 1 ) {
+ completionBox()->setSelected( currentIndex - 1, true );
+ } else if ( currentIndex == 0 ) {
// nothing to skip to, let's stay where we are, but make sure the
// first header becomes visible, if we are the first real entry
completionBox()->ensureVisible( 0, 0 );
+ //Kolab issue 2941: be sure to add email even if it's the only element.
+ if ( itemIsHeader( completionBox()->item( currentIndex ) ) ) {
+ currentIndex++;
+ }
+ completionBox()->setCurrentItem( itemAbove );
completionBox()->setSelected( currentIndex, true );
}
return true;
@@ -1030,14 +1115,15 @@ bool KPIM::AddresseeLineEdit::eventFilter(TQObject *obj, TQEvent *e)
} else if ( ke->key() == Key_Down ) {
// same strategy for downwards
//kdDebug() << "EVENTFILTER: Key_Down. currentIndex=" << currentIndex << endl;
- TQListBoxItem *itemBelow = completionBox()->item( currentIndex + 1 );
+ TQListBoxItem *itemBelow = completionBox()->item( currentIndex );
if ( itemBelow && itemIsHeader( itemBelow ) ) {
- if ( completionBox()->item( currentIndex + 2 ) ) {
+ if ( completionBox()->item( currentIndex + 1 ) ) {
//kdDebug() << "EVENTFILTER: Key_Down -> skipping " << currentIndex+1 << endl;
completionBox()->setCurrentItem( itemBelow->next() );
- completionBox()->setSelected( currentIndex + 2, true );
+ completionBox()->setSelected( currentIndex + 1, true );
} else {
// nothing to skip to, let's stay where we are
+ completionBox()->setCurrentItem( itemBelow );
completionBox()->setSelected( currentIndex, true );
}
return true;
@@ -1052,11 +1138,14 @@ bool KPIM::AddresseeLineEdit::eventFilter(TQObject *obj, TQEvent *e)
TQListBoxItem *item = completionBox()->item( currentIndex );
if ( item && itemIsHeader(item) ) {
completionBox()->setSelected( currentIndex, true );
- }
- } else if ( ke->key() == Key_Tab || ke->key() == Key_Backtab ) {
- /// first, find the header of teh current section
+ }
+ } else if ( e->type() == TQEvent::KeyRelease &&
+ ( ke->key() == Key_Tab || ke->key() == Key_Backtab ) ) {
+ //kdDebug() << "EVENTFILTER: Key_Tab. currentIndex=" << currentIndex << endl;
+ /// first, find the header of the current section
TQListBoxItem *myHeader = 0;
- int i = currentIndex;
+ const int iterationstep = ke->key() == Key_Tab ? 1 : -1;
+ int i = QMIN( QMAX( currentIndex - iterationstep, 0 ), completionBox()->count() - 1 );
while ( i>=0 ) {
if ( itemIsHeader( completionBox()->item(i) ) ) {
myHeader = completionBox()->item( i );
@@ -1066,22 +1155,31 @@ bool KPIM::AddresseeLineEdit::eventFilter(TQObject *obj, TQEvent *e)
}
Q_ASSERT( myHeader ); // we should always be able to find a header
- // find the next header (searching backwards, for Key_Backtab
+ // find the next header (searching backwards, for Key_Backtab)
TQListBoxItem *nextHeader = 0;
- const int iterationstep = ke->key() == Key_Tab ? 1 : -1;
// when iterating forward, start at the currentindex, when backwards,
// one up from our header, or at the end
- uint j = ke->key() == Key_Tab ? currentIndex : i==0 ? completionBox()->count()-1 : (i-1) % completionBox()->count();
+ uint j;
+ if ( ke->key() == Key_Tab ) {
+ j = currentIndex;
+ } else {
+ i = completionBox()->index( myHeader );
+ if ( i == 0 ) {
+ j = completionBox()->count() - 1;
+ } else {
+ j = ( i - 1 ) % completionBox()->count();
+ }
+ }
while ( ( nextHeader = completionBox()->item( j ) ) && nextHeader != myHeader ) {
if ( itemIsHeader(nextHeader) ) {
- break;
+ break;
}
j = (j + iterationstep) % completionBox()->count();
}
if ( nextHeader && nextHeader != myHeader ) {
TQListBoxItem *item = completionBox()->item( j + 1 );
if ( item && !itemIsHeader(item) ) {
- completionBox()->setSelected( j+1, true );
+ completionBox()->setSelected( item, true );
completionBox()->setCurrentItem( item );
completionBox()->ensureCurrentVisible();
}
@@ -1092,20 +1190,49 @@ bool KPIM::AddresseeLineEdit::eventFilter(TQObject *obj, TQEvent *e)
return ClickLineEdit::eventFilter( obj, e );
}
+class SourceWithWeight {
+ public:
+ int weight; // the weight of the source
+ TQString sourceName; // the name of the source, e.g. "LDAP Server"
+ int index; // index into s_completionSources
+
+ bool operator< ( const SourceWithWeight &other ) {
+ if ( weight > other.weight )
+ return true;
+ if ( weight < other.weight )
+ return false;
+ return sourceName < other.sourceName;
+ }
+};
+
const TQStringList KPIM::AddresseeLineEdit::getAdjustedCompletionItems( bool fullSearch )
{
TQStringList items = fullSearch ?
s_completion->allMatches( m_searchString )
: s_completion->substringCompletion( m_searchString );
+ // For weighted mode, the algorithm is the following:
+ // In the first loop, we add each item to its section (there is one section per completion source)
+ // We also add spaces in front of the items.
+ // The sections are appended to the items list.
+ // In the second loop, we then walk through the sections and add all the items in there to the
+ // sorted item list, which is the final result.
+ //
+ // The algo for non-weighted mode is different.
+
int lastSourceIndex = -1;
unsigned int i = 0;
+
+ // Maps indices of the items list, which are section headers/source items,
+ // to a TQStringList which are the items of that section/source.
TQMap<int, TQStringList> sections;
TQStringList sortedItems;
for ( TQStringList::Iterator it = items.begin(); it != items.end(); ++it, ++i ) {
CompletionItemsMap::const_iterator cit = s_completionItemMap->find(*it);
- if ( cit == s_completionItemMap->end() )continue;
+ if ( cit == s_completionItemMap->end() )
+ continue;
int idx = (*cit).second;
+
if ( s_completion->order() == KCompletion::Weighted ) {
if ( lastSourceIndex == -1 || lastSourceIndex != idx ) {
const TQString sourceLabel( (*s_completionSources)[idx] );
@@ -1124,11 +1251,30 @@ const TQStringList KPIM::AddresseeLineEdit::getAdjustedCompletionItems( bool ful
sortedItems.append( *it );
}
}
+
if ( s_completion->order() == KCompletion::Weighted ) {
- for ( TQMap<int, TQStringList>::Iterator it( sections.begin() ), end( sections.end() ); it != end; ++it ) {
- sortedItems.append( (*s_completionSources)[it.key()] );
- for ( TQStringList::Iterator sit( (*it).begin() ), send( (*it).end() ); sit != send; ++sit ) {
- sortedItems.append( *sit );
+
+ // Sort the sections
+ TQValueList<SourceWithWeight> sourcesAndWeights;
+ for ( uint i = 0; i < s_completionSources->size(); i++ ) {
+ SourceWithWeight sww;
+ sww.sourceName = (*s_completionSources)[i];
+ sww.weight = (*s_completionSourceWeights)[sww.sourceName];
+ sww.index = i;
+ sourcesAndWeights.append( sww );
+ }
+ qHeapSort( sourcesAndWeights );
+
+ // Add the sections and their items to the final sortedItems result list
+ for( uint i = 0; i < sourcesAndWeights.size(); i++ ) {
+ TQStringList sectionItems = sections[sourcesAndWeights[i].index];
+ if ( !sectionItems.isEmpty() ) {
+ sortedItems.append( sourcesAndWeights[i].sourceName );
+ TQStringList sectionItems = sections[sourcesAndWeights[i].index];
+ for ( TQStringList::Iterator sit( sectionItems.begin() ), send( sectionItems.end() );
+ sit != send; ++sit ) {
+ sortedItems.append( *sit );
+ }
}
}
} else {