24 #include "addresslineedit.h"
26 #include <QtGui/QApplication>
27 #include <QtGui/QKeyEvent>
28 #include <QtGui/QMouseEvent>
29 #include <QtCore/QObject>
30 #include <QtCore/QRegExp>
32 #include <kcompletionbox.h>
36 #include <kstandarddirs.h>
37 #include <kstandardshortcut.h>
39 #include "stdaddressbook.h"
49 class AddressLineEdit::Private
54 mCompletionInitialized( false ),
61 QStringList addresses();
62 QStringList removeMailDupes(
const QStringList &adrs );
64 void slotCompletion() { mParent->doCompletion(
false ); }
65 void slotPopupCompletion(
const QString &completion );
68 QString mPreviousAddresses;
70 bool mCompletionInitialized;
73 static bool sAddressesDirty;
74 static bool initialized;
76 bool AddressLineEdit::Private::initialized =
false;
77 K_GLOBAL_STATIC( KCompletion, sCompletion )
81 if ( !Private::initialized ) {
82 Private::initialized =
true;
83 sCompletion->setOrder( KCompletion::Sorted );
84 sCompletion->setIgnoreCase(
true );
87 if ( mUseCompletion && !mCompletionInitialized ) {
88 mParent->setCompletionObject( sCompletion,
false );
89 mParent->connect( mParent, SIGNAL(completion(QString)),
90 mParent, SLOT(slotCompletion()) );
92 KCompletionBox *box = mParent->completionBox();
93 mParent->connect( box, SIGNAL(currentTextChanged(QString)),
94 mParent, SLOT(slotPopupCompletion(QString)) );
95 mParent->connect( box, SIGNAL(userCancelled(QString)),
96 SLOT(userCancelled(QString)) );
98 mCompletionInitialized =
true;
106 QStringList AddressLineEdit::Private::addresses()
108 QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
111 QLatin1String space(
" " );
112 QRegExp needQuotes( QLatin1String(
"[^ 0-9A-Za-z\\x0080-\\xFFFF]" ) );
113 QLatin1String endQuote(
"\" " );
118 for ( it = addressBook->
begin(); it != addressBook->
end(); ++it ) {
119 QStringList emails = (*it).emails();
121 QString n = (*it).prefix() + space +
122 (*it).givenName() + space +
123 (*it).additionalName() + space +
124 (*it).familyName() + space +
129 QStringList::ConstIterator mit;
131 for ( mit = emails.constBegin(); mit != emails.constEnd(); ++mit ) {
133 if ( !email.isEmpty() ) {
134 if ( n.isEmpty() || ( email.indexOf( QLatin1Char(
'<' ) ) != -1 ) ) {
137 if ( n.indexOf( needQuotes ) != -1 ) {
138 addr = QLatin1Char(
'"' ) + n + endQuote;
144 if ( !addr.isEmpty() && ( email.indexOf( QLatin1Char(
'<' ) ) == -1 ) &&
145 ( email.indexOf( QLatin1Char(
'>' ) ) == -1 ) &&
146 ( email.indexOf( QLatin1Char(
',' ) ) == -1 ) ) {
147 addr += QLatin1Char(
'<' ) + email + QLatin1Char(
'>' );
151 addr = addr.trimmed();
152 result.append( addr );
159 QApplication::restoreOverrideCursor();
164 QStringList AddressLineEdit::Private::removeMailDupes(
const QStringList &addrs )
166 QStringList src( addrs );
170 for ( QStringList::Iterator it = src.begin(); it != src.end(); ) {
172 it = src.erase( it );
183 void AddressLineEdit::Private::slotPopupCompletion(
const QString &completion )
185 mParent->setText( mPreviousAddresses + completion );
186 mParent->cursorAtEnd();
189 bool AddressLineEdit::Private::sAddressesDirty =
false;
192 : KLineEdit( parent ), d( new Private( this ) )
194 d->mUseCompletion = useCompletion;
200 if ( d->mUseCompletion ) {
201 d->sAddressesDirty =
true;
216 if ( d->mUseCompletion ) {
217 completionBox()->setFont( font );
226 if ( KStandardShortcut::shortcut( KStandardShortcut::SubstringCompletion ).
227 contains( event->key() |
event->modifiers() ) ) {
230 }
else if ( KStandardShortcut::shortcut( KStandardShortcut::TextCompletion ).
231 contains( event->key() |
event->modifiers() ) ) {
232 int len = text().length();
234 if ( len == cursorPosition() ) {
247 if ( d->mUseCompletion && ( event->button() == Qt::MidButton ) ) {
248 d->mSmartPaste =
true;
250 d->mSmartPaste =
false;
259 if ( !d->mSmartPaste ) {
264 QString newText = oldText.trimmed();
265 if ( newText.isEmpty() ) {
271 newText.replace( QRegExp( QLatin1String(
"\r?\n" ) ), QLatin1String(
", " ) );
272 if ( newText.startsWith( QLatin1String(
"mailto:" ) ) ) {
275 }
else if ( newText.indexOf( QLatin1String(
" at " ) ) != -1 ) {
277 newText.replace( QLatin1String(
" at " ), QLatin1String(
"@" ) );
278 newText.replace( QLatin1String(
" dot " ), QLatin1String(
"." ) );
279 }
else if ( newText.indexOf( QLatin1String(
"(at)" ) ) != -1 ) {
280 newText.replace( QRegExp( QLatin1String(
"\\s*\\(at\\)\\s*" ) ), QLatin1String(
"@" ) );
283 QString contents = text();
286 int pos = cursorPosition();
287 if ( !selectedText().isEmpty() ) {
289 if ( pos > end_sel ) {
290 pos -= ( end_sel - start_sel );
291 }
else if ( pos > start_sel ) {
294 contents = contents.left( start_sel ) + contents.right( end_sel + 1 );
297 int eot = contents.length();
298 while ( ( eot > 0 ) && contents[ eot - 1 ].isSpace() ) {
304 }
else if ( pos >= eot ) {
305 if ( contents[ eot - 1 ] == QLatin1Char(
',' ) ) {
308 contents.truncate( eot );
309 contents += QLatin1String(
", " );
313 contents = contents.left( pos ) + newText + contents.mid( pos );
315 setCursorPosition( pos + newText.length() );
320 if ( d->mUseCompletion ) {
321 d->mSmartPaste =
true;
325 d->mSmartPaste =
false;
331 setCursorPosition( text().length() );
337 d->mUseCompletion = enable;
343 if ( !d->mUseCompletion ) {
350 int n = s.lastIndexOf( QLatin1Char(
',' ) );
355 int len = s.length();
358 while ( n < len && s[ n ].isSpace() ) {
362 prevAddr = s.left( n );
363 s = s.mid( n, 255 ).trimmed();
366 if ( d->sAddressesDirty ) {
371 QStringList completions = sCompletion->substringCompletion( s );
372 if ( completions.count() > 1 ) {
373 d->mPreviousAddresses = prevAddr;
374 setCompletedItems( completions );
375 }
else if ( completions.count() == 1 ) {
376 setText( prevAddr + completions.first() );
383 KGlobalSettings::Completion mode = completionMode();
386 case KGlobalSettings::CompletionPopupAuto:
392 case KGlobalSettings::CompletionPopup:
394 d->mPreviousAddresses = prevAddr;
395 QStringList items = sCompletion->allMatches( s );
396 items += sCompletion->allMatches( QLatin1String(
"\"" ) + s );
397 items += sCompletion->substringCompletion( QLatin1Char(
'<' ) + s );
398 int beforeDollarCompletionCount = items.count();
400 if ( s.indexOf( QLatin1Char(
' ' ) ) == -1 ) {
401 items += sCompletion->allMatches( QLatin1String(
"$$" ) + s );
404 if ( !items.isEmpty() ) {
405 if ( items.count() > beforeDollarCompletionCount ) {
407 for ( QStringList::Iterator it = items.begin();
408 it != items.end(); ++it ) {
409 int pos = (*it).indexOf( QLatin1Char(
'$' ), 2 );
413 (*it) = (*it).mid( pos + 1 );
417 items = d->removeMailDupes( items );
423 bool autoSuggest = ( mode != KGlobalSettings::CompletionPopupAuto );
424 setCompletedItems( items, autoSuggest );
426 if ( !autoSuggest ) {
427 int index = items.first().indexOf( s );
428 QString newText = prevAddr + items.first().mid( index );
431 setUserSelection(
false );
432 setCompletedText( newText,
true );
439 case KGlobalSettings::CompletionShell:
441 QString match = sCompletion->makeCompletion( s );
442 if ( !match.isNull() && match != s ) {
443 setText( prevAddr + match );
449 case KGlobalSettings::CompletionMan:
450 case KGlobalSettings::CompletionAuto:
452 if ( !s.isEmpty() ) {
453 QString match = sCompletion->makeCompletion( s );
454 if ( !match.isNull() && match != s ) {
455 setCompletedText( prevAddr + match );
461 case KGlobalSettings::CompletionNone:
470 sCompletion->clear();
471 d->sAddressesDirty =
false;
473 const QStringList addrs = d->addresses();
474 for ( QStringList::ConstIterator it = addrs.begin(); it != addrs.end(); ++it ) {
481 sCompletion->addItem( addr );
483 int pos = addr.indexOf( QLatin1Char(
'<' ) );
486 int pos2 = addr.indexOf( QLatin1Char(
'>' ), pos );
488 sCompletion->addItem( addr.mid( pos, pos2 - pos ) );
496 const KUrl::List uriList = KUrl::List::fromMimeData( event->mimeData() );
497 if ( !uriList.isEmpty() ) {
499 KUrl::List::ConstIterator it = uriList.begin();
500 for ( ; it != uriList.end(); ++it ) {
501 if ( !ct.isEmpty() ) {
502 ct.append( QLatin1String(
", " ) );
506 if ( (*it).protocol() == QLatin1String(
"mailto" ) ) {
507 ct.append( (*it).path() );
509 ct.append( (*it).url() );
515 if ( d->mUseCompletion ) {
516 d->mSmartPaste =
true;
520 d->mSmartPaste =
false;
524 #include "addresslineedit.moc"