[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kdepim/KDE/4.14] libkdepim/addressline: Split code
From: Montel Laurent <montel () kde ! org>
Date: 2015-02-12 21:20:05
Message-ID: E1YM1B7-0003WP-VN () scm ! kde ! org
[Download RAW message or body]
Git commit 1565bda3b6c7ef20bd252d8098c9f0358b2f77d0 by Montel Laurent.
Committed on 12/02/2015 at 21:18.
Pushed by mlaurent into branch 'KDE/4.14'.
Split code
M +1 -956 libkdepim/addressline/addresseelineedit.cpp
C +16 -626 libkdepim/addressline/addresseelineedit_p.cpp [from: \
libkdepim/addressline/addresseelineedit.cpp - 060% similarity]
http://commits.kde.org/kdepim/1565bda3b6c7ef20bd252d8098c9f0358b2f77d0
diff --git a/libkdepim/addressline/addresseelineedit.cpp \
b/libkdepim/addressline/addresseelineedit.cpp index f46deaa..df64db2 100644
--- a/libkdepim/addressline/addresseelineedit.cpp
+++ b/libkdepim/addressline/addresseelineedit.cpp
@@ -71,965 +71,10 @@
#include <QMenu>
#include <QTimer>
#include <QtDBus/QDBusConnection>
+#include "addresseelineedit_p.cpp"
using namespace KPIM;
-namespace KPIM {
-typedef QMap< QString, QPair<int,int> > CompletionItemsMap;
-}
-
-class AddresseeLineEditStatic
-{
-public:
-
- AddresseeLineEditStatic()
- : completion( new KMailCompletion ),
- ldapTimer( 0 ),
- ldapSearch( 0 ),
- ldapLineEdit( 0 ),
- akonadiSession( new Akonadi::Session("contactsCompletionSession") ),
- balooCompletionSource( 0 )
- {
- }
-
- ~AddresseeLineEditStatic()
- {
- delete completion;
- delete ldapTimer;
- delete ldapSearch;
- }
-
- void slotEditCompletionOrder()
- {
- CompletionOrderEditor editor( ldapSearch, 0 );
- if( editor.exec() ) {
- updateLDAPWeights();
- updateCollectionWeights();
- }
- }
-
- void updateCollectionWeights()
- {
- akonadiCollectionToCompletionSourceMap.clear();
- }
-
- void updateLDAPWeights()
- {
- /* Add completion sources for all ldap server, 0 to n. Added first so
- * that they map to the LdapClient::clientNumber() */
- ldapSearch->updateCompletionWeights();
- int clientIndex = 0;
- foreach ( const KLDAP::LdapClient *client, ldapSearch->clients() ) {
- const int sourceIndex =
- addCompletionSource( i18n( "LDAP server: %1" \
,client->server().host()),
- client->completionWeight() );
-
- ldapClientToCompletionSourceMap.insert( clientIndex, sourceIndex );
-
- ++clientIndex;
- }
- }
-
- int addCompletionSource( const QString &source, int weight )
- {
- QMap<QString,int>::iterator it = completionSourceWeights.find( source );
- if ( it == completionSourceWeights.end() ) {
- completionSourceWeights.insert( source, weight );
- } else {
- completionSourceWeights[source] = weight;
- }
-
- const int sourceIndex = completionSources.indexOf( source );
- if ( sourceIndex == -1 ) {
- completionSources.append( source );
- return completionSources.size() - 1;
- } else {
- return sourceIndex;
- }
- }
-
- void removeCompletionSource( const QString &source )
- {
- QMap<QString,int>::iterator it = completionSourceWeights.find( source );
- if ( it != completionSourceWeights.end() ) {
- completionSourceWeights.remove(source);
- completion->clear();
- }
- }
-
- KMailCompletion *completion;
- KPIM::CompletionItemsMap completionItemMap;
- QStringList completionSources;
- QTimer *ldapTimer;
- KLDAP::LdapClientSearch *ldapSearch;
- QString ldapText;
- AddresseeLineEdit *ldapLineEdit;
- // The weights associated with the completion sources in \
s_static->completionSources.
- // Both are maintained by addCompletionSource(), don't attempt to modifiy those \
yourself.
- QMap<QString, int> completionSourceWeights;
- // maps LDAP client indices to completion source indices
- // the assumption that they are always the first n indices in \
s_static->completion
- // does not hold when clients are added later on
- QMap<int, int> ldapClientToCompletionSourceMap;
- // holds the cached mapping from akonadi collection id to the completion source \
index
- QMap<Akonadi::Collection::Id, int> akonadiCollectionToCompletionSourceMap;
- // a list of akonadi items (contacts) that have not had their collection fetched \
yet
- Akonadi::Item::List akonadiPendingItems;
- Akonadi::Session *akonadiSession;
- QVector<QWeakPointer<Akonadi::Job> > akonadiJobsInFlight;
- int balooCompletionSource;
-};
-
-K_GLOBAL_STATIC( AddresseeLineEditStatic, s_static )
-
-// needs to be unique, but the actual name doesn't matter much
-static QString newLineEditObjectName()
-{
- static int s_count = 0;
- QString name( QLatin1String("KPIM::AddresseeLineEdit") );
- if ( s_count++ ) {
- name += QLatin1Char('-');
- name += QString::number( s_count );
- }
- return name;
-}
-
-static const QString s_completionItemIndentString = QLatin1String(" ");
-
-static bool itemIsHeader( const QListWidgetItem *item )
-{
- return item && !item->text().startsWith( s_completionItemIndentString );
-}
-
-class SourceWithWeight
-{
-public:
- int weight; // the weight of the source
- QString sourceName; // the name of the source, e.g. "LDAP Server"
- int index; // index into s_static->completionSources
-
- bool operator< ( const SourceWithWeight &other ) const
- {
- if ( weight > other.weight ) {
- return true;
- }
-
- if ( weight < other.weight ) {
- return false;
- }
-
- return sourceName < other.sourceName;
- }
-};
-
-class AddresseeLineEdit::Private
-{
-public:
- Private( AddresseeLineEdit *qq, bool enableCompletion )
- : q( qq ),
- m_useCompletion( enableCompletion ),
- m_completionInitialized( false ),
- m_smartPaste( false ),
- m_addressBookConnected( false ),
- m_lastSearchMode( false ),
- m_searchExtended( false ),
- m_useSemicolonAsSeparator( false ),
- m_showOU(false),
- m_enableBalooSearch(true)
- {
- m_delayedQueryTimer.setSingleShot(true);
- connect( &m_delayedQueryTimer, SIGNAL(timeout()), q, \
SLOT(slotTriggerDelayedQueries()) );
- }
- QStringList cleanupEmailList(const QStringList &inputList);
- void loadBalooBlackList();
- void alternateColor();
- void init();
- void startLoadingLDAPEntries();
- void stopLDAPLookup();
- void setCompletedItems( const QStringList &items, bool autoSuggest );
- void addCompletionItem( const QString &string, int weight, int source,
- const QStringList *keyWords = 0 );
- const QStringList adjustedCompletionItems( bool fullSearch );
- void updateSearchString();
- void startSearches();
- void akonadiPerformSearch();
- void akonadiHandlePending();
- void doCompletion( bool ctrlT );
-
- void slotCompletion();
- void slotPopupCompletion( const QString & );
- void slotReturnPressed( const QString & );
- void slotStartLDAPLookup();
- void slotLDAPSearchData( const KLDAP::LdapResult::List & );
- void slotEditCompletionOrder();
- void slotUserCancelled( const QString & );
- void slotAkonadiHandleItems( const Akonadi::Item::List &items );
- void slotAkonadiSearchResult( KJob * );
- void slotAkonadiCollectionsReceived( const Akonadi::Collection::List & );
- void searchInBaloo();
- void slotTriggerDelayedQueries();
- void slotShowOUChanged( bool );
- void slotConfigureBalooBlackList();
-
- AddresseeLineEdit *q;
- QStringList m_balooBlackList;
- QStringList m_domainExcludeList;
- QString m_previousAddresses;
- QString m_searchString;
- bool m_useCompletion;
- bool m_completionInitialized;
- bool m_smartPaste;
- bool m_addressBookConnected;
- bool m_lastSearchMode;
- bool m_searchExtended; //has \" been added?
- bool m_useSemicolonAsSeparator;
- bool m_showOU;
- bool m_enableBalooSearch;
- QTimer m_delayedQueryTimer;
- QColor m_alternateColor;
-};
-
-void AddresseeLineEdit::Private::init()
-{
- if ( !s_static.exists() ) {
- s_static->completion->setOrder( KCompletion::Weighted );
- s_static->completion->setIgnoreCase( true );
- }
-
- if ( m_useCompletion ) {
- if ( !s_static->ldapTimer ) {
- s_static->ldapTimer = new QTimer;
- s_static->ldapSearch = new KLDAP::LdapClientSearch;
-
- /* The reasoning behind this filter is:
- * If it's a person, or a distlist, show it, even if it doesn't have an \
email address.
- * If it's not a person, or a distlist, only show it if it has an email \
attribute.
- * This allows both resource accounts with an email address which are \
not a person and
- * person entries without an email address to show up, while still not \
showing things
- * like structural entries in the ldap tree.
- */
-
- #if 0
- s_static->ldapSearch->setFilter(QString::fromLatin1("&(|(objectclass=person)(objectclass=groupOfNames)(mail=*))"
- \
"(|(cn=%1*)(mail=%1*)(mail=*@%1*)(givenName=%1*)(sn=%1*))"));
- #endif
- //Fix bug 323272 "Exchange doesn't like any queries beginning with *."
- s_static->ldapSearch->setFilter(QString::fromLatin1( \
"&(|(objectclass=person)(objectclass=groupOfNames)(mail=*))"
- "(|(cn=%1*)(mail=%1*)(givenName=%1*)(sn=%1*))" ));
-
- }
-
- s_static->balooCompletionSource = q->addCompletionSource( i18nc( \
"@title:group", "Contacts found in your data"), -1 );
-
- s_static->updateLDAPWeights();
-
- if ( !m_completionInitialized ) {
- q->setCompletionObject( s_static->completion, false );
- q->connect( q, SIGNAL(completion(QString)),
- q, SLOT(slotCompletion()) );
- q->connect( q, SIGNAL(returnPressed(QString)),
- q, SLOT(slotReturnPressed(QString)) );
-
- KCompletionBox *box = q->completionBox();
- q->connect( box, SIGNAL(activated(QString)),
- q, SLOT(slotPopupCompletion(QString)) );
- q->connect( box, SIGNAL(userCancelled(QString)),
- q, SLOT(slotUserCancelled(QString)) );
-
- q->connect( s_static->ldapTimer, SIGNAL(timeout()), \
SLOT(slotStartLDAPLookup()) );
- q->connect( s_static->ldapSearch, \
SIGNAL(searchData(KLDAP::LdapResult::List)),
- SLOT(slotLDAPSearchData(KLDAP::LdapResult::List)) );
-
- m_completionInitialized = true;
- }
-
- KConfigGroup group( KGlobal::config(), "AddressLineEdit" );
- m_showOU = group.readEntry( "ShowOU", false );
- loadBalooBlackList();
- }
-}
-
-void AddresseeLineEdit::Private::startLoadingLDAPEntries()
-{
- QString text( s_static->ldapText );
-
- // TODO cache last?
- QString prevAddr;
- const int index = text.lastIndexOf( QLatin1Char( ',' ) );
- if ( index >= 0 ) {
- prevAddr = text.left( index + 1 ) + QLatin1Char( ' ' );
- text = text.mid( index + 1, 255 ).trimmed();
- }
-
- if ( text.isEmpty() ) {
- return;
- }
-
- s_static->ldapSearch->startSearch( text );
-}
-
-void AddresseeLineEdit::Private::stopLDAPLookup()
-{
- s_static->ldapSearch->cancelSearch();
- s_static->ldapLineEdit = 0;
-}
-
-QStringList AddresseeLineEdit::cleanupEmailList(const QStringList &inputList)
-{
- return d->cleanupEmailList(inputList);
-}
-
-QStringList AddresseeLineEdit::Private::cleanupEmailList(const QStringList \
&inputList)
-{
- KPIM::BalooCompletionEmail completionEmail;
- completionEmail.setEmailList(inputList);
- completionEmail.setBlackList(m_balooBlackList);
- completionEmail.setExcludeDomain(m_domainExcludeList);
- const QStringList listEmail = completionEmail.cleanupEmailList();
- return listEmail;
-}
-
-void AddresseeLineEdit::Private::searchInBaloo()
-{
- const QString trimmedString = m_searchString.trimmed();
- Baloo::PIM::ContactCompleter com(trimmedString, 20);
- const QStringList listEmail = cleanupEmailList(com.complete());
- Q_FOREACH (const QString& email, listEmail) {
- addCompletionItem(email, 1, s_static->balooCompletionSource);
- }
- doCompletion( m_lastSearchMode );
- // if ( q->hasFocus() || q->completionBox()->hasFocus() ) {
- //}
-}
-
-void AddresseeLineEdit::Private::alternateColor()
-{
- const KColorScheme colorScheme( QPalette::Active, KColorScheme::View );
- m_alternateColor = \
colorScheme.background(KColorScheme::AlternateBackground).color();
-}
-
-void AddresseeLineEdit::Private::setCompletedItems( const QStringList &items, bool \
autoSuggest )
-{
- KCompletionBox *completionBox = q->completionBox();
-
- if ( !items.isEmpty() &&
- !( items.count() == 1 && m_searchString == items.first() ) ) {
-
- completionBox->clear();
- const int numberOfItems( items.count() );
- for ( int i = 0; i< numberOfItems; ++i )
- {
- QListWidgetItem *item =new QListWidgetItem(items.at( i ), \
completionBox);
- if ( !items.at( i ).startsWith( s_completionItemIndentString ) ) {
- if (!m_alternateColor.isValid()) {
- alternateColor();
- }
- item->setBackgroundColor(m_alternateColor);
- }
- completionBox->addItem( item );
- }
- if ( !completionBox->isVisible() ) {
- if ( !m_searchString.isEmpty() ) {
- completionBox->setCancelledText( m_searchString );
- }
- completionBox->popup();
- // we have to install the event filter after popup(), since that
- // calls show(), and that's where KCompletionBox installs its filter.
- // We want to be first, though, so do it now.
- if ( s_static->completion->order() == KCompletion::Weighted ) {
- qApp->installEventFilter( q );
- }
- }
-
- QListWidgetItem *item = completionBox->item( 1 );
- if ( item ) {
- completionBox->blockSignals( true );
- completionBox->setCurrentItem( item );
- item->setSelected( true );
- completionBox->blockSignals( false );
- }
-
- if ( autoSuggest ) {
- const int index = items.first().indexOf( m_searchString );
- const QString newText = items.first().mid( index );
- q->setUserSelection( false );
- q->setCompletedText( newText, true );
- }
- } else {
- if ( completionBox && completionBox->isVisible() ) {
- completionBox->hide();
- completionBox->setItems( QStringList() );
- }
- }
-}
-
-void AddresseeLineEdit::Private::addCompletionItem( const QString &string, int \
weight,
- int completionItemSource,
- const QStringList *keyWords )
-{
- // Check if there is an exact match for item already, and use the
- // maximum weight if so. Since there's no way to get the information
- // from KCompletion, we have to keep our own QMap.
- // We also update the source since the item should always be shown from the \
source with the highest weight
-
- CompletionItemsMap::iterator it = s_static->completionItemMap.find( string );
- if ( it != s_static->completionItemMap.end() ) {
- weight = qMax( ( *it ).first, weight );
- ( *it ).first = weight;
- ( *it ).second = completionItemSource;
- } else {
- s_static->completionItemMap.insert( string, qMakePair( weight, \
completionItemSource ) );
- }
-
- s_static->completion->addItem(string, weight);
- if (keyWords && !keyWords->isEmpty())
- s_static->completion->addItemWithKeys(string, weight, keyWords); // see \
kmailcompletion.cpp
-}
-
-const QStringList KPIM::AddresseeLineEdit::Private::adjustedCompletionItems( bool \
fullSearch )
-{
- QStringList items = fullSearch ?
- s_static->completion->allMatches( m_searchString ) :
- s_static->completion->substringCompletion( m_searchString );
-
- //force items to be sorted by email
- items.sort();
-
- // 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 QStringList which are the items of that section/source.
- QMap<int, QStringList> sections;
- QStringList sortedItems;
- for ( QStringList::Iterator it = items.begin(); it != items.end(); ++it, ++i ) {
- CompletionItemsMap::const_iterator cit = \
s_static->completionItemMap.constFind( *it );
- if ( cit == s_static->completionItemMap.constEnd() ) {
- continue;
- }
-
- const int index = (*cit).second;
-
- if ( s_static->completion->order() == KCompletion::Weighted ) {
- if ( lastSourceIndex == -1 || lastSourceIndex != index ) {
- const QString sourceLabel( s_static->completionSources.at( index ) \
);
- if ( sections.find( index ) == sections.end() ) {
- it = items.insert( it, sourceLabel );
- ++it; //skip new item
- }
- lastSourceIndex = index;
- }
-
- (*it) = (*it).prepend( s_completionItemIndentString );
- // remove preferred email sort <blank> added in addContact()
- (*it).replace( QLatin1String( " <" ), QLatin1String( " <" ) );
- }
- sections[ index ].append( *it );
-
- if ( s_static->completion->order() == KCompletion::Sorted ) {
- sortedItems.append( *it );
- }
- }
-
- if ( s_static->completion->order() == KCompletion::Weighted ) {
-
- // Sort the sections
- QList<SourceWithWeight> sourcesAndWeights;
- const int numberOfCompletionSources(s_static->completionSources.size());
- for ( int i = 0; i < numberOfCompletionSources; ++i ) {
- SourceWithWeight sww;
- sww.sourceName = s_static->completionSources.at(i);
- sww.weight = s_static->completionSourceWeights[sww.sourceName];
- sww.index = i;
- sourcesAndWeights.append( sww );
- }
-
- qSort( sourcesAndWeights.begin(), sourcesAndWeights.end() );
- // Add the sections and their items to the final sortedItems result list
- const int numberOfSources(sourcesAndWeights.size());
- for ( int i = 0; i < numberOfSources; ++i ) {
- const SourceWithWeight source = sourcesAndWeights.at(i);
- const QStringList sectionItems = sections[source.index];
- if ( !sectionItems.isEmpty() ) {
- sortedItems.append( source.sourceName );
- foreach ( const QString &itemInSection, sectionItems ) {
- sortedItems.append( itemInSection );
- }
- }
- }
- } else {
- sortedItems.sort();
- }
-
- return sortedItems;
-}
-
-void AddresseeLineEdit::Private::updateSearchString()
-{
- m_searchString = q->text();
-
- int n = -1;
- bool inQuote = false;
- const int searchStringLength = m_searchString.length();
- for ( int i = 0; i < searchStringLength; ++i ) {
- const QChar searchChar = m_searchString.at( i );
- if ( searchChar == QLatin1Char( '"' ) ) {
- inQuote = !inQuote;
- }
-
- if ( searchChar == QLatin1Char('\\') &&
- ( i + 1 ) < searchStringLength && m_searchString.at( i + 1 ) == \
QLatin1Char( '"' ) ) {
- ++i;
- }
-
- if ( inQuote ) {
- continue;
- }
-
- if ( i < searchStringLength &&
- ( searchChar == QLatin1Char(',') ||
- ( m_useSemicolonAsSeparator && searchChar == QLatin1Char(';') ) ) ) {
- n = i;
- }
- }
-
- if ( n >= 0 ) {
- ++n; // Go past the ","
-
- const int len = m_searchString.length();
-
- // Increment past any whitespace...
- while ( n < len && m_searchString.at( n ).isSpace() ) {
- ++n;
- }
-
- m_previousAddresses = m_searchString.left( n );
- m_searchString = m_searchString.mid( n ).trimmed();
- } else {
- m_previousAddresses.clear();
- }
-}
-
-void AddresseeLineEdit::Private::slotTriggerDelayedQueries()
-{
- if (m_searchString.isEmpty() || m_searchString.trimmed().size() <= 2)
- return;
-
- if (m_enableBalooSearch) {
- searchInBaloo();
- }
-
- // We send a contactsearch job through akonadi.
- // This not only searches baloo but also servers if remote search is enabled
- akonadiPerformSearch();
-}
-
-void AddresseeLineEdit::Private::startSearches()
-{
- if (!m_delayedQueryTimer.isActive())
- m_delayedQueryTimer.start(50);
-}
-
-void AddresseeLineEdit::Private::akonadiPerformSearch()
-{
- kDebug() << "searching akonadi with:" << m_searchString;
-
- // first, kill all job still in flight, they are no longer current
- Q_FOREACH( QWeakPointer<Akonadi::Job> job, s_static->akonadiJobsInFlight ) {
- if ( !job.isNull() ) {
- job.data()->kill();
- }
- }
- s_static->akonadiJobsInFlight.clear();
-
- // now start new jobs
- Akonadi::ContactSearchJob *contactJob = new Akonadi::ContactSearchJob( \
s_static->akonadiSession );
- contactJob->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent \
);
- contactJob->setQuery( Akonadi::ContactSearchJob::NameOrEmail, m_searchString,
- Akonadi::ContactSearchJob::ContainsWordBoundaryMatch );
- q->connect( contactJob, SIGNAL(itemsReceived(Akonadi::Item::List)),
- q, SLOT(slotAkonadiHandleItems(Akonadi::Item::List)) );
- q->connect( contactJob, SIGNAL(result(KJob*)),
- q, SLOT(slotAkonadiSearchResult(KJob*)) );
-
- Akonadi::ContactGroupSearchJob *groupJob = new Akonadi::ContactGroupSearchJob( \
s_static->akonadiSession );
- groupJob->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
- groupJob->setQuery( Akonadi::ContactGroupSearchJob::Name, m_searchString,
- Akonadi::ContactGroupSearchJob::ContainsMatch );
- q->connect( contactJob, SIGNAL(itemsReceived(Akonadi::Item::List)),
- q, SLOT(slotAkonadiHandleItems(Akonadi::Item::List)) );
- q->connect( groupJob, SIGNAL(result(KJob*)),
- q, SLOT(slotAkonadiSearchResult(KJob*)) );
-
- s_static->akonadiJobsInFlight.append( contactJob );
- s_static->akonadiJobsInFlight.append( groupJob );
- akonadiHandlePending();
-}
-
-void AddresseeLineEdit::Private::akonadiHandlePending()
-{
- kDebug() << "Pending items: " << s_static->akonadiPendingItems.size();
- Akonadi::Item::List::iterator it = s_static->akonadiPendingItems.begin();
- while ( it != s_static->akonadiPendingItems.end() ) {
- const Akonadi::Item item = *it;
-
- const int sourceIndex =
- s_static->akonadiCollectionToCompletionSourceMap.value( \
item.parentCollection().id(), -1 );
- if ( sourceIndex >= 0 ) {
- kDebug() << "identified collection: " << \
s_static->completionSources[sourceIndex];
- q->addItem( item, 1, sourceIndex );
-
- // remove from the pending
- it = s_static->akonadiPendingItems.erase( it );
- } else {
- ++it;
- }
- }
-}
-
-void AddresseeLineEdit::Private::doCompletion( bool ctrlT )
-{
- m_lastSearchMode = ctrlT;
-
- const KGlobalSettings::Completion mode = q->completionMode();
-
- if ( mode == KGlobalSettings::CompletionNone ) {
- return;
- }
-
- s_static->completion->setOrder( KCompletion::Weighted );
-
- // cursor at end of string - or Ctrl+T pressed for substring completion?
- if ( ctrlT ) {
- const QStringList completions = adjustedCompletionItems( false );
-
- if ( completions.count() > 1 ) {
- ; //m_previousAddresses = prevAddr;
- } else if ( completions.count() == 1 ) {
- q->setText( m_previousAddresses + completions.first().trimmed() );
- }
-
- // Make sure the completion popup is closed if no matching items were found
- setCompletedItems( completions, true );
-
- q->cursorAtEnd();
- q->setCompletionMode( mode ); //set back to previous mode
- return;
- }
-
- switch ( mode ) {
- case KGlobalSettings::CompletionPopupAuto:
- {
- if ( m_searchString.isEmpty() ) {
- break;
- }
- //else: fall-through to the CompletionPopup case
- }
-
- case KGlobalSettings::CompletionPopup:
- {
- const QStringList items = adjustedCompletionItems( false );
- setCompletedItems( items, false );
- }
- break;
-
- case KGlobalSettings::CompletionShell:
- {
- const QString match = s_static->completion->makeCompletion( m_searchString \
);
- if ( !match.isNull() && match != m_searchString ) {
- q->setText( m_previousAddresses + match );
- q->setModified( true );
- q->cursorAtEnd();
- }
- }
- break;
-
- case KGlobalSettings::CompletionMan: // Short-Auto in fact
- case KGlobalSettings::CompletionAuto:
- {
- //force autoSuggest in KLineEdit::keyPressed or setCompletedText will have \
no effect
- q->setCompletionMode( q->completionMode() );
-
- if ( !m_searchString.isEmpty() ) {
-
- //if only our \" is left, remove it since user has not typed it either
- if ( m_searchExtended && m_searchString == QLatin1String( "\"" ) ) {
- m_searchExtended = false;
- m_searchString.clear();
- q->setText( m_previousAddresses );
- break;
- }
-
- QString match = s_static->completion->makeCompletion( m_searchString );
-
- if ( !match.isEmpty() ) {
- if ( match != m_searchString ) {
- QString adds = m_previousAddresses + match;
- q->setCompletedText( adds );
- }
- } else {
- if ( !m_searchString.startsWith( QLatin1Char( '\"' ) ) ) {
- //try with quoted text, if user has not type one already
- match = s_static->completion->makeCompletion( QLatin1String( \
"\"" ) + m_searchString );
- if ( !match.isEmpty() && match != m_searchString ) {
- m_searchString = QLatin1String( "\"" ) + m_searchString;
- m_searchExtended = true;
- q->setText( m_previousAddresses + m_searchString );
- q->setCompletedText( m_previousAddresses + match );
- }
- } else if ( m_searchExtended ) {
- //our added \" does not work anymore, remove it
- m_searchString = m_searchString.mid( 1 );
- m_searchExtended = false;
- q->setText( m_previousAddresses + m_searchString );
- //now try again
- match = s_static->completion->makeCompletion( m_searchString );
- if ( !match.isEmpty() && match != m_searchString ) {
- const QString adds = m_previousAddresses + match;
- q->setCompletedText( adds );
- }
- }
- }
- }
- }
- break;
-
- case KGlobalSettings::CompletionNone:
- default: // fall through
- break;
- }
-}
-
-void AddresseeLineEdit::Private::slotCompletion()
-{
- // Called by KLineEdit's keyPressEvent for CompletionModes
- // Auto,Popup -> new text, update search string.
- // not called for CompletionShell, this is been taken care of
- // in AddresseeLineEdit::keyPressEvent
-
- updateSearchString();
- if ( q->completionBox() ) {
- q->completionBox()->setCancelledText( m_searchString );
- }
-
- startSearches();
- doCompletion( false );
-}
-
-void AddresseeLineEdit::Private::slotPopupCompletion( const QString &completion )
-{
- QString c = completion.trimmed();
- if ( c.endsWith( QLatin1Char( ')' ) ) ) {
- c = completion.mid( 0, completion.lastIndexOf( QLatin1String( " (" )) \
).trimmed();
- }
- q->setText( m_previousAddresses + c );
- q->cursorAtEnd();
- updateSearchString();
- q->emitTextCompleted();
-}
-
-void AddresseeLineEdit::Private::slotReturnPressed( const QString & )
-{
- if ( !q->completionBox()->selectedItems().isEmpty() ) {
- slotPopupCompletion( q->completionBox()->selectedItems().first()->text() );
- }
-}
-
-void AddresseeLineEdit::Private::slotStartLDAPLookup()
-{
- if ( Solid::Networking::status() == Solid::Networking::Unconnected ) {
- return;
- }
-
- const KGlobalSettings::Completion mode = q->completionMode();
-
- if ( mode == KGlobalSettings::CompletionNone ) {
- return;
- }
-
- if ( !s_static->ldapSearch->isAvailable() ) {
- return;
- }
-
- if ( s_static->ldapLineEdit != q ) {
- return;
- }
-
- startLoadingLDAPEntries();
-}
-
-void AddresseeLineEdit::Private::slotLDAPSearchData( const KLDAP::LdapResult::List \
&results )
-{
- if ( results.isEmpty() || s_static->ldapLineEdit != q ) {
- return;
- }
-
- foreach ( const KLDAP::LdapResult &result, results ) {
- KABC::Addressee contact;
- contact.setNameFromString( result.name );
- contact.setEmails( result.email );
- QString ou;
-
- if ( m_showOU ) {
- const int depth = result.dn.depth();
- for ( int i = 0; i < depth; ++i ) {
- const QString rdnStr = result.dn.rdnString( i );
- if ( rdnStr.startsWith( QLatin1String( "ou=" ), Qt::CaseInsensitive \
) ) {
- ou = rdnStr.mid( 3 );
- break;
- }
- }
- }
-
- if ( !s_static->ldapClientToCompletionSourceMap.contains( \
result.clientNumber ) ) {
- s_static->updateLDAPWeights(); // we got results from a new source, so \
update the completion sources
- }
-
- q->addContact( contact, result.completionWeight,
- s_static->ldapClientToCompletionSourceMap[ \
result.clientNumber ], ou );
- }
-
- if ( ( q->hasFocus() || q->completionBox()->hasFocus() ) &&
- q->completionMode() != KGlobalSettings::CompletionNone &&
- q->completionMode() != KGlobalSettings::CompletionShell ) {
- q->setText( m_previousAddresses + m_searchString );
- // only complete again if the user didn't change the selection while
- // we were waiting; otherwise the completion box will be closed
- const QListWidgetItem *current = q->completionBox()->currentItem();
- if ( !current || m_searchString.trimmed() != current->text().trimmed() ) {
- doCompletion( m_lastSearchMode );
- }
- }
-}
-
-void AddresseeLineEdit::Private::slotEditCompletionOrder()
-{
- init(); // for s_static->ldapSearch
- if(m_useCompletion){
- s_static->slotEditCompletionOrder();
- }
-}
-
-void AddresseeLineEdit::Private::slotUserCancelled( const QString &cancelText )
-{
- if ( s_static->ldapSearch && s_static->ldapLineEdit == q ) {
- stopLDAPLookup();
- }
-
- q->userCancelled( m_previousAddresses + cancelText ); // in KLineEdit
-}
-
-void AddresseeLineEdit::Private::slotAkonadiHandleItems( const Akonadi::Item::List \
&items )
-{
- /* We have to fetch the collections of the items, so that
- the source name can be correctly labeled.*/
- foreach ( const Akonadi::Item &item, items ) {
-
- // check the local cache of collections
- const int sourceIndex =
- s_static->akonadiCollectionToCompletionSourceMap.value( \
item.parentCollection().id(), -1 );
- if ( sourceIndex == -1 ) {
- kDebug() << "Fetching New collection: " << item.parentCollection().id();
- // the collection isn't there, start the fetch job.
- Akonadi::CollectionFetchJob *collectionJob =
- new Akonadi::CollectionFetchJob( item.parentCollection(),
- \
Akonadi::CollectionFetchJob::Base,
- s_static->akonadiSession );
- connect( collectionJob, \
SIGNAL(collectionsReceived(Akonadi::Collection::List)),
- q, \
SLOT(slotAkonadiCollectionsReceived(Akonadi::Collection::List)) );
- /* we don't want to start multiple fetch jobs for the same collection,
- so insert the collection with an index value of -2 */
- s_static->akonadiCollectionToCompletionSourceMap.insert( \
item.parentCollection().id(), -2 );
- s_static->akonadiPendingItems.append( item );
- } else if ( sourceIndex == -2 ) {
- /* fetch job already started, don't need to start another one,
- so just append the item as pending */
- s_static->akonadiPendingItems.append( item );
- } else {
- q->addItem( item, 1, sourceIndex );
- }
- }
-
- if ( !items.isEmpty() ) {
- const QListWidgetItem *current = q->completionBox()->currentItem();
- if ( !current || m_searchString.trimmed() != current->text().trimmed() ) {
- doCompletion( m_lastSearchMode );
- }
- }
-}
-
-void AddresseeLineEdit::Private::slotAkonadiSearchResult( KJob *job )
-{
- if ( job->error() ) {
- kWarning() << "Akonadi search job failed: " << job->errorString();
- } else {
- Akonadi::ItemSearchJob *searchJob = \
static_cast<Akonadi::ItemSearchJob*>(job);
- kDebug() << "Found" << searchJob->items().size() << "items";
- }
- const int index = s_static->akonadiJobsInFlight.indexOf( \
qobject_cast<Akonadi::Job*>( job ) );
- if( index != -1 )
- s_static->akonadiJobsInFlight.remove( index );
-}
-
-void AddresseeLineEdit::Private::slotAkonadiCollectionsReceived(
- const Akonadi::Collection::List &collections )
-{
- KSharedConfig::Ptr config = KSharedConfig::openConfig( \
QLatin1String("kpimcompletionorder") );
- KConfigGroup group( config, "CompletionWeights" );
- foreach ( const Akonadi::Collection &collection, collections ) {
- if ( collection.isValid() ) {
- const QString sourceString = collection.displayName();
- const int weight = group.readEntry( QString::number(collection.id()), 1 \
);
- const int index = q->addCompletionSource( sourceString, weight );
- kDebug() << "\treceived: " << sourceString << "index: " << index;
- s_static->akonadiCollectionToCompletionSourceMap.insert( \
collection.id(), index );
- }
- }
-
- // now that we have added the new collections, recheck our list of pending \
contacts
- akonadiHandlePending();
- // do completion
- const QListWidgetItem *current = q->completionBox()->currentItem();
- if ( !current || m_searchString.trimmed() != current->text().trimmed() ) {
- doCompletion( m_lastSearchMode );
- }
-}
-
-void AddresseeLineEdit::Private::slotShowOUChanged(bool checked)
-{
- if ( checked != m_showOU ) {
- KConfigGroup group( KGlobal::config(), "AddressLineEdit" );
- group.writeEntry( "ShowOU", checked );
- m_showOU = checked;
- }
-}
-
-void AddresseeLineEdit::Private::slotConfigureBalooBlackList()
-{
- QPointer<KPIM::BlackListBalooEmailCompletionDialog> dlg = new \
KPIM::BlackListBalooEmailCompletionDialog(q);
- dlg->setEmailBlackList(m_balooBlackList);
- if (dlg->exec()) {
- loadBalooBlackList();
- }
- delete dlg;
-}
-
-void AddresseeLineEdit::Private::loadBalooBlackList()
-{
- KSharedConfig::Ptr config = KSharedConfig::openConfig( \
QLatin1String("kpimbalooblacklist") );
- KConfigGroup group( config, "AddressLineEdit" );
- m_balooBlackList = group.readEntry( "BalooBackList", QStringList() );
- m_domainExcludeList = group.readEntry("ExcludeDomain", QStringList());
-}
AddresseeLineEdit::AddresseeLineEdit( QWidget *parent, bool enableCompletion )
: KLineEdit( parent ), d( new Private( this, enableCompletion ) )
diff --git a/libkdepim/addressline/addresseelineedit.cpp \
b/libkdepim/addressline/addresseelineedit_p.cpp similarity index 60%
copy from libkdepim/addressline/addresseelineedit.cpp
copy to libkdepim/addressline/addresseelineedit_p.cpp
index f46deaa..bb1b2ee 100644
--- a/libkdepim/addressline/addresseelineedit.cpp
+++ b/libkdepim/addressline/addresseelineedit_p.cpp
@@ -1,83 +1,31 @@
/*
- This file is part of libkdepim.
-
- Copyright (c) 2002 Helge Deller <deller@gmx.de>
- Copyright (c) 2002 Lubos Lunak <llunak@suse.cz>
- Copyright (c) 2001,2003 Carsten Pfeiffer <pfeiffer@kde.org>
- Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
- Copyright (c) 2004 Daniel Molkentin <danimo@klaralvdalens-datakonsult.se>
- Copyright (c) 2004 Karl-Heinz Zimmer <khz@klaralvdalens-datakonsult.se>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
+ Copyright (c) 2015 Montel Laurent <montel@kde.org>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License, version 2, as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
+ General Public License for more details.
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "addresseelineedit.h"
-#include "ldap/ldapclientsearch.h"
#include "completionordereditor.h"
-#include "addressline/blacklistbaloocompletion/blacklistbalooemailcompletiondialog.h"
#include "kmailcompletion.h"
-#include "baloocompletionemail.h"
-
-#include <Akonadi/Contact/ContactSearchJob>
-#include <Akonadi/Contact/ContactGroupSearchJob>
-#include <Akonadi/CollectionFetchJob>
-#include <Akonadi/EntityDisplayAttribute>
-#include <Akonadi/ItemFetchScope>
-#include <Akonadi/RecursiveItemFetchJob>
-#include <Akonadi/Session>
-#include <Akonadi/Job>
-
-#include <baloo/pim/contactcompleter.h>
-
-#include <KPIMUtils/Email>
-#include <KColorScheme>
-
-#include <KLDAP/LdapServer>
-
-#include <KMime/Util>
-
-#include <KConfigGroup>
-#include <KCompletionBox>
-#include <KDebug>
-#include <KLocale>
-#include <KStandardDirs>
-#include <KStandardShortcut>
-#include <KUrl>
-
-#include <solid/networking.h>
-
-#include <QApplication>
-#include <QCursor>
-#include <QObject>
-#include <QRegExp>
-#include <QEvent>
-#include <QClipboard>
-#include <QKeyEvent>
-#include <QDropEvent>
-#include <QMouseEvent>
-#include <QMenu>
-#include <QTimer>
-#include <QtDBus/QDBusConnection>
-
-using namespace KPIM;
+
+#include <QMap>
+
namespace KPIM {
typedef QMap< QString, QPair<int,int> > CompletionItemsMap;
}
+namespace KPIM {
class AddresseeLineEditStatic
{
public:
@@ -1030,562 +978,4 @@ void AddresseeLineEdit::Private::loadBalooBlackList()
m_balooBlackList = group.readEntry( "BalooBackList", QStringList() );
m_domainExcludeList = group.readEntry("ExcludeDomain", QStringList());
}
-
-AddresseeLineEdit::AddresseeLineEdit( QWidget *parent, bool enableCompletion )
- : KLineEdit( parent ), d( new Private( this, enableCompletion ) )
-{
- setObjectName( newLineEditObjectName() );
- setClickMessage( QString() );
-
- d->init();
-}
-
-AddresseeLineEdit::~AddresseeLineEdit()
-{
- if ( s_static->ldapSearch && s_static->ldapLineEdit == this ) {
- d->stopLDAPLookup();
- }
- delete d;
-}
-
-void AddresseeLineEdit::setFont( const QFont &font )
-{
- KLineEdit::setFont( font );
-
- if ( d->m_useCompletion ) {
- completionBox()->setFont( font );
- }
-}
-
-void AddresseeLineEdit::setEnableBalooSearch(bool enable)
-{
- d->m_enableBalooSearch = enable;
-}
-
-void AddresseeLineEdit::allowSemicolonAsSeparator( bool useSemicolonAsSeparator )
-{
- d->m_useSemicolonAsSeparator = useSemicolonAsSeparator;
-}
-
-void AddresseeLineEdit::keyPressEvent( QKeyEvent *event )
-{
- bool accept = false;
-
- const int key = event->key() | event->modifiers();
-
- if ( KStandardShortcut::shortcut( KStandardShortcut::SubstringCompletion \
).contains( key ) ) {
- //TODO: add LDAP substring lookup, when it becomes available in \
KPIM::LDAPSearch
- d->updateSearchString();
- d->startSearches();
- d->doCompletion( true );
- accept = true;
- } else if ( KStandardShortcut::shortcut( KStandardShortcut::TextCompletion \
).contains( key ) ) {
- const int len = text().length();
-
- if ( len == cursorPosition() ) { // at End?
- d->updateSearchString();
- d->startSearches();
- d->doCompletion( true );
- accept = true;
- }
- }
-
- const QString oldContent = text();
- if ( !accept ) {
- KLineEdit::keyPressEvent( event );
- }
-
- // 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 ( event->isAccepted() ) {
- d->updateSearchString();
-
- QString searchString( d->m_searchString );
- //LDAP does not know about our string manipulation, remove it
- if ( d->m_searchExtended ) {
- searchString = d->m_searchString.mid( 1 );
- }
-
- if ( d->m_useCompletion && s_static->ldapTimer ) {
- if ( s_static->ldapText != searchString || s_static->ldapLineEdit != \
this ) {
- d->stopLDAPLookup();
- }
-
- s_static->ldapText = searchString;
- s_static->ldapLineEdit = this;
- s_static->ldapTimer->setSingleShot( true );
- s_static->ldapTimer->start( 500 );
- }
- }
-}
-
-void AddresseeLineEdit::insert( const QString &t )
-{
- if ( !d->m_smartPaste ) {
- KLineEdit::insert( t );
- return;
- }
-
- QString newText = t.trimmed();
- if ( newText.isEmpty() ) {
- return;
- }
-
- // remove newlines in the to-be-pasted string
- QStringList lines = newText.split( QRegExp( QLatin1String( "\r?\n" ) ), \
QString::SkipEmptyParts );
- QStringList::iterator end( lines.end() );
- for ( QStringList::iterator it = lines.begin(); it != end; ++it ) {
- // remove trailing commas and whitespace
- (*it).remove( QRegExp( QLatin1String( ",?\\s*$" ) ) );
- }
- newText = lines.join( QLatin1String( ", " ) );
-
- if ( newText.startsWith( QLatin1String( "mailto:" ) ) ) {
- const KUrl url( newText );
- newText = url.path();
- } else if ( newText.indexOf( QLatin1String( " at " ) ) != -1 ) {
- // Anti-spam stuff
- newText.replace( QLatin1String( " at " ), QLatin1String( "@" ) );
- newText.replace( QLatin1String( " dot " ), QLatin1String( "." ) );
- } else if ( newText.indexOf( QLatin1String( "(at)" ) ) != -1 ) {
- newText.replace( QRegExp( QLatin1String( "\\s*\\(at\\)\\s*" ) ), \
QLatin1String( "@" ) );
- }
-
- QString contents = text();
- int start_sel = 0;
- int pos = cursorPosition();
-
- if ( hasSelectedText() ) {
- // Cut away the selection.
- 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.at( eot - 1 ).isSpace() ) {
- --eot;
- }
- if ( eot == 0 ) {
- contents.clear();
- } else if ( pos >= eot ) {
- if ( contents.at( eot - 1 ) == QLatin1Char( ',' ) ) {
- --eot;
- }
- contents.truncate( eot );
- contents += QLatin1String( ", " );
- pos = eot + 2;
- }
-
- contents = contents.left( pos ) + newText + contents.mid( pos );
- setText( contents );
- setModified( true );
- setCursorPosition( pos + newText.length() );
-}
-
-void AddresseeLineEdit::setText( const QString & text )
-{
- const int cursorPos = cursorPosition();
- KLineEdit::setText( text.trimmed() );
- setCursorPosition( cursorPos );
-}
-
-void AddresseeLineEdit::paste()
-{
- if ( d->m_useCompletion ) {
- d->m_smartPaste = true;
- }
-
- KLineEdit::paste();
- d->m_smartPaste = false;
-}
-
-void AddresseeLineEdit::mouseReleaseEvent( QMouseEvent *event )
-{
- // reimplemented from QLineEdit::mouseReleaseEvent()
-#ifndef QT_NO_CLIPBOARD
- if ( d->m_useCompletion &&
- QApplication::clipboard()->supportsSelection() &&
- !isReadOnly() &&
- event->button() == Qt::MidButton ) {
- d->m_smartPaste = true;
- }
-#endif
-
- KLineEdit::mouseReleaseEvent( event );
- d->m_smartPaste = false;
-}
-
-#ifndef QT_NO_DRAGANDDROP
-void AddresseeLineEdit::dropEvent( QDropEvent *event )
-{
- if ( !isReadOnly() ) {
- const KUrl::List uriList = KUrl::List::fromMimeData( event->mimeData() );
- if ( !uriList.isEmpty() ) {
- QString contents = text();
- // remove trailing white space and comma
- int eot = contents.length();
- while ( ( eot > 0 ) && contents.at( eot - 1 ).isSpace() ) {
- --eot;
- }
- if ( eot == 0 ) {
- contents.clear();
- } else if ( contents.at( eot - 1 ) == QLatin1Char(',') ) {
- --eot;
- contents.truncate( eot );
- }
- bool mailtoURL = false;
- // append the mailto URLs
- foreach ( const KUrl &url, uriList ) {
- if ( url.protocol() == QLatin1String( "mailto" ) ) {
- mailtoURL = true;
- QString address;
- address = KUrl::fromPercentEncoding( url.path().toLatin1() );
- address = KMime::decodeRFC2047String( address.toLatin1() );
- if ( !contents.isEmpty() ) {
- contents.append( QLatin1String( ", " ) );
- }
- contents.append( address );
- }
- }
- if ( mailtoURL ) {
- setText( contents );
- setModified( true );
- return;
- }
- } else {
- // Let's see if this drop contains a comma separated list of emails
- const QString dropData = QString::fromUtf8( event->encodedData( \
"text/plain" ) );
- const QStringList addrs = KPIMUtils::splitAddressList( dropData );
- if ( !addrs.isEmpty() ) {
- setText( KPIMUtils::normalizeAddressesAndDecodeIdn( dropData ) );
- setModified( true );
- return;
- }
- }
- }
-
- if ( d->m_useCompletion ) {
- d->m_smartPaste = true;
- }
-
- QLineEdit::dropEvent( event );
- d->m_smartPaste = false;
-}
-#endif // QT_NO_DRAGANDDROP
-
-void AddresseeLineEdit::cursorAtEnd()
-{
- setCursorPosition( text().length() );
-}
-
-void AddresseeLineEdit::enableCompletion( bool enable )
-{
- d->m_useCompletion = enable;
}
-
-void AddresseeLineEdit::addItem( const Akonadi::Item &item, int weight, int source )
-{
- //Let Akonadi results always have a higher weight than baloo results
- if ( item.hasPayload<KABC::Addressee>() ) {
- addContact( item.payload<KABC::Addressee>(), weight + 1, source );
- } else if ( item.hasPayload<KABC::ContactGroup>() ) {
- addContactGroup( item.payload<KABC::ContactGroup>(), weight + 1, source );
- }
-}
-
-void AddresseeLineEdit::addContactGroup( const KABC::ContactGroup &group, int \
weight, int source )
-{
- d->addCompletionItem( group.name(), weight, source );
-}
-
-void AddresseeLineEdit::addContact( const KABC::Addressee &addr, int weight, int \
source, QString append )
-{
- const QStringList emails = addr.emails();
- QStringList::ConstIterator it;
- int isPrefEmail = 1; //first in list is preferredEmail
- QStringList::ConstIterator end( emails.constEnd() );
- for ( it = emails.constBegin(); it != end; ++it ) {
- //TODO: highlight preferredEmail
- const QString email( (*it) );
- const QString givenName = addr.givenName();
- const QString familyName= addr.familyName();
- const QString nickName = addr.nickName();
- QString fullEmail = addr.fullEmail( email );
-
- QString appendix;
-
- if ( !append.isEmpty() ) {
- appendix = QLatin1String( " (%1)" );
- append = append.replace( QLatin1String("("), QLatin1String("[") );
- append = append.replace( QLatin1String(")"), QLatin1String("]") );
- appendix = appendix.arg( append );
- }
-
- // Prepare "givenName" + ' ' + "familyName"
- QString fullName = givenName;
- if (!familyName.isEmpty()) {
- if (!fullName.isEmpty())
- fullName += QLatin1Char(' ');
- fullName += familyName;
- }
-
- // Finally, we can add the completion items
- if (!fullName.isEmpty()) {
- const QString address = KPIMUtils::normalizedAddress(fullName, email, \
QString());
- if (fullEmail != address) {
- // This happens when fullEmail contains a middle name, while our own \
fullName+email only has "first last".
- // Let's offer both, the fullEmail with 3 parts, looks a tad formal.
- d->addCompletionItem(address + appendix, weight + isPrefEmail, \
source);
- }
- }
-
- QStringList keyWords;
- if (!nickName.isEmpty()) {
- keyWords.append(nickName);
- }
-
- d->addCompletionItem( fullEmail + appendix, weight + isPrefEmail, source, \
&keyWords );
-
- isPrefEmail = 0;
- }
-}
-
-#ifndef QT_NO_CONTEXTMENU
-void AddresseeLineEdit::contextMenuEvent( QContextMenuEvent *event )
-{
- QMenu *menu = createStandardContextMenu();
- if ( menu ) { // can be 0 on platforms with only a touch interface
- menu->exec( event->globalPos() );
- delete menu;
- }
-}
-
-QMenu *AddresseeLineEdit::createStandardContextMenu()
-{
- // disable modes not supported by KMailCompletion
- setCompletionModeDisabled( KGlobalSettings::CompletionMan );
- setCompletionModeDisabled( KGlobalSettings::CompletionPopupAuto );
-
- QMenu *menu = KLineEdit::createStandardContextMenu();
- if ( !menu ) {
- return 0;
- }
-
- if ( d->m_useCompletion ) {
- menu->addAction( i18n( "Configure Completion Order..." ),
- this, SLOT(slotEditCompletionOrder()) );
-
- QAction *showOU = new QAction(i18n( "Show Organization Unit for LDAP \
results" ),menu);
- showOU->setCheckable(true);
-
- showOU->setChecked( d->m_showOU );
- connect(showOU, SIGNAL(triggered(bool)), this, \
SLOT(slotShowOUChanged(bool)));
- menu->addAction(showOU);
- }
-
- //Add i18n in kf5
- QAction *configureBalooBlackList = new QAction(QLatin1String( "Configure Email \
Blacklist" ),menu);
- connect(configureBalooBlackList, SIGNAL(triggered(bool)), this, \
SLOT(slotConfigureBalooBlackList()));
- menu->addAction(configureBalooBlackList);
-
- return menu;
-}
-#endif
-
-void KPIM::AddresseeLineEdit::removeCompletionSource(const QString &source)
-{
- s_static->removeCompletionSource(source);
-}
-
-int KPIM::AddresseeLineEdit::addCompletionSource( const QString &source, int weight \
)
-{
- return s_static->addCompletionSource(source,weight);
-}
-
-bool KPIM::AddresseeLineEdit::eventFilter( QObject *object, QEvent *event )
-{
- if ( d->m_completionInitialized &&
- ( object == completionBox() ||
- completionBox()->findChild<QWidget*>( object->objectName() ) == object ) \
) {
- if ( event->type() == QEvent::MouseButtonPress ||
- event->type() == QEvent::MouseMove ||
- event->type() == QEvent::MouseButtonRelease ||
- event->type() == QEvent::MouseButtonDblClick ) {
-
- const QMouseEvent* mouseEvent = static_cast<QMouseEvent*>( event );
- // find list box item at the event position
- QListWidgetItem *item = completionBox()->itemAt( mouseEvent->pos() );
- if ( !item ) {
- // In the case of a mouse move outside of the box we don't want
- // the parent to fuzzy select a header by mistake.
- bool eat = event->type() == QEvent::MouseMove;
- return eat;
- }
- // avoid selection of headers on button press, or move or release while
- // a button is pressed
- const Qt::MouseButtons buttons = mouseEvent->buttons();
- if ( event->type() == QEvent::MouseButtonPress ||
- event->type() == QEvent::MouseButtonDblClick ||
- buttons & Qt::LeftButton || buttons & Qt::MidButton ||
- buttons & Qt::RightButton ) {
- if ( itemIsHeader( item ) ) {
- return true; // eat the event, we don't want anything to happen
- } else {
- // if we are not on one of the group heading, make sure the item
- // below or above is selected, not the heading, inadvertedly, \
due
- // to fuzzy auto-selection from QListBox
- completionBox()->setCurrentItem( item );
- item->setSelected( true );
- if ( event->type() == QEvent::MouseMove ) {
- return true; // avoid fuzzy selection behavior
- }
- }
- }
- }
- }
-
- if ( ( object == this ) &&
- ( event->type() == QEvent::ShortcutOverride ) ) {
- QKeyEvent *keyEvent = static_cast<QKeyEvent*>( event );
- if ( keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down ||
- keyEvent->key() == Qt::Key_Tab ) {
- keyEvent->accept();
- return true;
- }
- }
-
- if ( ( object == this ) &&
- ( event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease \
) &&
- completionBox()->isVisible() ) {
- const QKeyEvent *keyEvent = static_cast<QKeyEvent*>( event );
- int currentIndex = completionBox()->currentRow();
- if ( currentIndex < 0 ) {
- return true;
- }
- if ( keyEvent->key() == Qt::Key_Up ) {
- //kDebug() <<"EVENTFILTER: Qt::Key_Up currentIndex=" << currentIndex;
- // figure out if the item we would be moving to is one we want
- // to ignore. If so, go one further
- const QListWidgetItem *itemAbove = completionBox()->item( currentIndex \
);
- if ( itemAbove && itemIsHeader( itemAbove ) ) {
- // there is a header above is, check if there is even further up
- // and if so go one up, so it'll be selected
- if ( currentIndex > 0 && completionBox()->item( currentIndex - 1 ) ) \
{
- //kDebug() <<"EVENTFILTER: Qt::Key_Up -> skipping" << \
currentIndex - 1;
- completionBox()->setCurrentRow( currentIndex - 1 );
- completionBox()->item( currentIndex - 1 )->setSelected( 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()->scrollToItem( completionBox()->item( 0 ) );
- QListWidgetItem *item = completionBox()->item( currentIndex );
- if ( item ) {
- if ( itemIsHeader( item ) ) {
- currentIndex++;
- item = completionBox()->item( currentIndex );
- }
- completionBox()->setCurrentItem( item );
- item->setSelected( true );
- }
- }
-
- return true;
- }
- } else if ( keyEvent->key() == Qt::Key_Down ) {
- // same strategy for downwards
- //kDebug() <<"EVENTFILTER: Qt::Key_Down. currentIndex=" << currentIndex;
- const QListWidgetItem *itemBelow = completionBox()->item( currentIndex \
);
- if ( itemBelow && itemIsHeader( itemBelow ) ) {
- if ( completionBox()->item( currentIndex + 1 ) ) {
- //kDebug() <<"EVENTFILTER: Qt::Key_Down -> skipping" << \
currentIndex+1;
- completionBox()->setCurrentRow( currentIndex + 1 );
- completionBox()->item( currentIndex + 1 )->setSelected( true );
- } else {
- // nothing to skip to, let's stay where we are
- QListWidgetItem *item = completionBox()->item( currentIndex );
- if ( item ) {
- completionBox()->setCurrentItem( item );
- item->setSelected( true );
- }
- }
-
- return true;
- }
- // special case of the initial selection, which is unfortunately a \
header.
- // Setting it to selected tricks KCompletionBox into not treating is \
special
- // and selecting making it current, instead of the one below.
- QListWidgetItem *item = completionBox()->item( currentIndex );
- if ( item && itemIsHeader( item ) ) {
- completionBox()->setCurrentItem( item );
- item->setSelected( true );
- }
- } else if ( event->type() == QEvent::KeyRelease &&
- ( keyEvent->key() == Qt::Key_Tab || keyEvent->key() == \
Qt::Key_Backtab ) ) {
- /// first, find the header of the current section
- QListWidgetItem *myHeader = 0;
- int myHeaderIndex = -1;
- const int iterationStep = keyEvent->key() == Qt::Key_Tab ? 1 : -1;
- int index = qMin( qMax( currentIndex - iterationStep, 0 ), \
completionBox()->count() - 1 );
- while ( index >= 0 ) {
- if ( itemIsHeader( completionBox()->item( index ) ) ) {
- myHeader = completionBox()->item( index );
- myHeaderIndex = index;
- break;
- }
-
- index--;
- }
- Q_ASSERT( myHeader ); // we should always be able to find a header
-
- // find the next header (searching backwards, for Qt::Key_Backtab)
- QListWidgetItem *nextHeader = 0;
-
- // when iterating forward, start at the currentindex, when backwards,
- // one up from our header, or at the end
- uint j;
- if ( keyEvent->key() == Qt::Key_Tab ) {
- j = currentIndex;
- } else {
- index = myHeaderIndex;
- if ( index == 0 ) {
- j = completionBox()->count() - 1;
- } else {
- j = ( index - 1 ) % completionBox()->count();
- }
- }
- while ( ( nextHeader = completionBox()->item( j ) ) && nextHeader != \
myHeader ) {
- if ( itemIsHeader( nextHeader ) ) {
- break;
- }
- j = ( j + iterationStep ) % completionBox()->count();
- }
-
- if ( nextHeader && nextHeader != myHeader ) {
- QListWidgetItem *item = completionBox()->item( j + 1 );
- if ( item && !itemIsHeader( item ) ) {
- completionBox()->setCurrentItem( item );
- item->setSelected( true );
- }
- }
-
- return true;
- }
- }
-
- return KLineEdit::eventFilter( object, event );
-}
-
-void AddresseeLineEdit::emitTextCompleted()
-{
- emit textCompleted();
-}
-
-
-
-
-#include "moc_addresseelineedit.cpp"
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic