/* IM address editor widget for KAddressBook Copyright (c) 2004 Will Stephenson This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 General Public License for more details. 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. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "imaddresswidget.h" #include "imeditorbase.h" #include "imeditorwidget.h" IMAddressLVI::IMAddressLVI( KListView *parent, KPluginInfo *protocol, const QString &address, const IMContext &context ) : KListViewItem( parent ) { setProtocol( protocol ); setAddress( address ); setContext( context ); mPreferred = false; } void IMAddressLVI::setPreferred( bool preferred ) { mPreferred = preferred; } bool IMAddressLVI::preferred() const { return mPreferred; } void IMAddressLVI::paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int alignment ) { if ( mPreferred ) { QFont font = p->font(); font.setBold( true ); p->setFont( font ); } KListViewItem::paintCell( p, cg, column, width, alignment ); } void IMAddressLVI::setAddress( const QString &address ) { // irc uses 0xE120 to seperate the nick and the server group. QString serverOrGroup = address.section( QChar( 0xE120 ), 1 ); if ( serverOrGroup.isEmpty() ) setText( 1, address ); else { QString nickname = address.section( QChar( 0xE120 ), 0, 0 ); setText( 1, i18n( " on ","%1 on %2" ) .arg( nickname ).arg( serverOrGroup ) ); } mAddress = address; } void IMAddressLVI::setContext( const IMContext &context ) { mContext = context; // set context /* switch ( context ) { case Home: setText( 2, i18n( "Home" ) ); break; case Work: setText( 2, i18n( "Work" ) ); break; case Any: setText( 2, i18n( "Any" ) ); break; } */ } void IMAddressLVI::setProtocol( KPluginInfo *protocol ) { mProtocol = protocol; setPixmap( 0, SmallIcon( mProtocol->icon() ) ); setText( 0, mProtocol->name() ); } KPluginInfo * IMAddressLVI::protocol() const { return mProtocol; } IMContext IMAddressLVI::context() const { return mContext; } QString IMAddressLVI::address() const { return mAddress; } void IMAddressLVI::activate() { // show editor } /*===========================================================================*/ IMEditorWidget::IMEditorWidget( QWidget *parent, const QString &preferredIM, const char *name ) : KDialogBase( parent, name, false, i18n( "Edit Instant Messenging Address" ), Help | Ok | Cancel, Ok, false ), mReadOnly( false ) { mWidget = new IMEditorBase( this ); setMainWidget( mWidget ); connect( mWidget->btnAdd, SIGNAL( clicked() ), SLOT( slotAdd() ) ); connect( mWidget->btnEdit, SIGNAL( clicked() ), SLOT( slotEdit() ) ); connect( mWidget->btnDelete, SIGNAL( clicked() ), SLOT( slotDelete() ) ); connect( mWidget->btnSetStandard, SIGNAL( clicked()), SLOT( slotSetStandard() ) ); connect( mWidget->lvAddresses, SIGNAL( selectionChanged() ), SLOT( slotUpdateButtons() ) ); connect( mWidget->lvAddresses, SIGNAL( doubleClicked( QListViewItem*, const QPoint&, int ) ), SLOT( slotEdit() ) ); setHelp( "managing-contacts-im-addresses" ); mWidget->btnEdit->setEnabled( false ); mWidget->btnDelete->setEnabled( false ); mWidget->btnSetStandard->setEnabled( false ); // Disabled pending implementation //mWidget->btnUp->setEnabled( false ); //mWidget->btnDown->setEnabled( false ); mPreferred = preferredIM; mPreferred = mPreferred.replace( " on ", QString( QChar( 0xE120 ) ), true ); mProtocols = KPluginInfo::fromServices( KTrader::self()->query( QString::fromLatin1( "KABC/IMProtocol" ) ) ); // order the protocols by putting them in a qmap, then sorting the set of keys and recreating the list QMap protocolMap; QValueList::ConstIterator it; QValueList sorted; for ( it = mProtocols.begin(); it != mProtocols.end(); ++it ) protocolMap.insert( (*it)->name(), (*it) ); QStringList keys = protocolMap.keys(); keys.sort(); QStringList::ConstIterator keyIt = keys.begin(); QStringList::ConstIterator end = keys.end(); for ( ; keyIt != end; ++keyIt ) sorted.append( protocolMap[*keyIt] ); mProtocols = sorted; } QValueList IMEditorWidget::availableProtocols() const { return mProtocols; } void IMEditorWidget::loadContact( KABC::Addressee *addr ) { if ( mWidget->lvAddresses ) mWidget->lvAddresses->clear(); // see README for details of how Evolution stores IM addresses (differently) const QStringList customs = addr->customs(); QStringList::ConstIterator it; bool isSet = false; for ( it = customs.begin(); it != customs.end(); ++it ) { QString app, name, value; splitField( *it, app, name, value ); if ( app.startsWith( QString::fromLatin1( "messaging/" ) ) ) { if ( name == QString::fromLatin1( "All" ) ) { KPluginInfo *protocol = protocolFromString( app ); if ( protocol ) { QStringList addresses = QStringList::split( QChar( 0xE000 ), value ); QStringList::iterator end = addresses.end(); for ( QStringList::ConstIterator it = addresses.begin(); it != end; ++it ) { IMAddressLVI *imaddresslvi = new IMAddressLVI( mWidget->lvAddresses, protocol, *it, Any/*, false*/ ); if ( !isSet && (*it).stripWhiteSpace().lower() == mPreferred.stripWhiteSpace().lower() ) { imaddresslvi->setPreferred( true ); isSet = true; //Only set one item to be preferred } } } else kdDebug( 5720 ) << k_funcinfo << " no protocol found for: " << app << endl; } } } if ( mWidget->lvAddresses->firstChild() ) mWidget->lvAddresses->firstChild()->setSelected( true ); } void IMEditorWidget::storeContact( KABC::Addressee *addr ) { // for each changed protocol, write a new custom field containing the current set of // addresses QValueList::ConstIterator protocolIt; for ( protocolIt = mChangedProtocols.begin(); protocolIt != mChangedProtocols.end(); ++protocolIt ) { QStringList lst; QListViewItemIterator addressIt( mWidget->lvAddresses ); while ( addressIt.current() ) { IMAddressLVI* currentAddress = static_cast( *addressIt ); if ( currentAddress->protocol() == *protocolIt ) lst.append( currentAddress->address() ); ++addressIt; } QString addrBookField = (*protocolIt)->property( "X-KDE-InstantMessagingKABCField" ).toString(); if ( !lst.isEmpty() ) addr->insertCustom( addrBookField, QString::fromLatin1( "All" ), lst.join( QChar( 0xE000 ) ) ); else addr->removeCustom( addrBookField, QString::fromLatin1( "All" ) ); } } void IMEditorWidget::setReadOnly( bool readOnly ) { mReadOnly = readOnly; slotUpdateButtons(); } void IMEditorWidget::slotSetStandard() { QListViewItemIterator it( mWidget->lvAddresses, QListViewItemIterator::Selected ); // Just set the first one selected as standard if ( IMAddressLVI *current = static_cast( it.current() ) ) { QListViewItemIterator it2( mWidget->lvAddresses ); while ( it2.current() ) { IMAddressLVI *item = static_cast( it2.current() ); if ( item->preferred() ) { if ( current == item ) return; //Selected is already preferred else { item->setPreferred( false ); mWidget->lvAddresses->repaintItem( item ); break; } } ++it2; } mPreferred = current->address(); current->setPreferred( true ); setModified( true ); mWidget->lvAddresses->repaintItem( current ); } } void IMEditorWidget::slotUpdateButtons() { int num_selected = 0; QListViewItemIterator it( mWidget->lvAddresses, QListViewItemIterator::Selected ); while ( it.current() ) { ++num_selected; if ( num_selected > 1 ) break; //no need to count above 2. ++it; } if ( !mReadOnly && num_selected == 1 ) { mWidget->btnAdd->setEnabled( true ); mWidget->btnEdit->setEnabled( true ); mWidget->btnDelete->setEnabled( true ); IMAddressLVI *current = static_cast( it.current() ); // Disable "set standard" if already standard mWidget->btnSetStandard->setEnabled( !current || !current->preferred() ); } else if ( !mReadOnly && num_selected > 1 ) { mWidget->btnAdd->setEnabled( true ); mWidget->btnEdit->setEnabled( false ); mWidget->btnDelete->setEnabled( true ); mWidget->btnSetStandard->setEnabled( false ); } else { mWidget->btnAdd->setEnabled( !mReadOnly ); mWidget->btnSetStandard->setEnabled( false ); mWidget->btnEdit->setEnabled( false ); mWidget->btnDelete->setEnabled( false ); } } void IMEditorWidget::setModified( bool modified ) { mModified = modified; } bool IMEditorWidget::isModified() const { return mModified; } void IMEditorWidget::slotAdd() { KDialogBase addDialog( this, "addaddress", true, i18n( "Instant messaging", "Add Address" ), KDialogBase::Ok | KDialogBase::Cancel ); IMAddressWidget *addressWid = new IMAddressWidget( &addDialog, mProtocols ); addDialog.enableButtonOK( false ); connect( addressWid, SIGNAL( inValidState( bool ) ), &addDialog, SLOT( enableButtonOK( bool ) ) ); addDialog.setMainWidget( addressWid ); if ( addDialog.exec() == QDialog::Accepted ) { // add the new item IMAddressLVI *imaddresslvi = new IMAddressLVI( mWidget->lvAddresses, addressWid->protocol(), addressWid->address() /*, addressWid->context() */ ); // If it's a new address, set is as preferred. if ( mPreferred.isEmpty() ) { imaddresslvi->setPreferred( true ); mPreferred = addressWid->address(); } if ( mChangedProtocols.find( addressWid->protocol() ) == mChangedProtocols.end() ) mChangedProtocols.append( addressWid->protocol() ); mWidget->lvAddresses->sort(); setModified( true ); } } void IMEditorWidget::slotEdit() { QListViewItemIterator it( mWidget->lvAddresses, QListViewItemIterator::Selected ); // Just edit the first one selected. if ( IMAddressLVI *current = static_cast( it.current() ) ) { KDialogBase editDialog( this, "editaddress", true, i18n( "Instant messaging", "Edit Address" ), KDialogBase::Ok | KDialogBase::Cancel ); IMAddressWidget *addressWid = new IMAddressWidget( &editDialog, mProtocols, current->protocol(), current->address(), current->context() ) ; connect( addressWid, SIGNAL( inValidState( bool ) ), &editDialog, SLOT( enableButtonOK( bool ) ) ); editDialog.setMainWidget( addressWid ); if ( editDialog.exec() == QDialog::Accepted ) { bool modified = false; if ( addressWid->address() != current->address() ) { modified = true; current->setAddress( addressWid->address() ); } if ( addressWid->context() != current->context() ) { modified = true; current->setContext( addressWid->context() ); } // the entry for the protocol of the current address has changed if ( mChangedProtocols.find( current->protocol() ) == mChangedProtocols.end() ) { mChangedProtocols.append( current->protocol() ); } // update protocol - has another protocol gained an address? if ( current->protocol() != addressWid->protocol() ) { modified = true; // this proto is losing an entry current->setProtocol( addressWid->protocol() ); if ( mChangedProtocols.find( current->protocol() ) == mChangedProtocols.end() ) mChangedProtocols.append( current->protocol() ); } if ( modified ) setModified(true); } } } void IMEditorWidget::slotDelete() { int num_selected = 0; { QListViewItemIterator it( mWidget->lvAddresses, QListViewItemIterator::Selected ); while ( it.current() ) { num_selected++; ++it; } } if ( num_selected == 0 ) return; if ( KMessageBox::warningContinueCancel( this, i18n( "Do you really want to delete the selected address?", "Do you really want to delete the %n selected addresses?", num_selected ), i18n( "Confirm Delete" ), KStdGuiItem::del() ) != KMessageBox::Continue ) return; QListViewItemIterator it( mWidget->lvAddresses ); bool deletedPreferred = false; while( it.current() ) { if ( it.current()->isSelected() ) { IMAddressLVI * current = static_cast( *it ); if ( mChangedProtocols.find( current->protocol() ) == mChangedProtocols.end() ) mChangedProtocols.append( current->protocol() ); if ( current->preferred() ) deletedPreferred = true; delete current; } else ++it; } if ( deletedPreferred ) { IMAddressLVI *first = static_cast( mWidget->lvAddresses->firstChild() ); if ( first ) { first->setPreferred( true ); mPreferred = first->address(); } else mPreferred = ""; } setModified( true ); } QString IMEditorWidget::preferred() const { QString retval( mPreferred ); return retval.replace( QChar( 0xE120 ), " on " ); } KPluginInfo * IMEditorWidget::protocolFromString( const QString &fieldValue ) const { QValueList::ConstIterator it; KPluginInfo * protocol = 0; for ( it = mProtocols.begin(); it != mProtocols.end(); ++it ) { if ( (*it)->property( "X-KDE-InstantMessagingKABCField" ).toString() == fieldValue ) { protocol = *it; break; } } return protocol; } void IMEditorWidget::splitField( const QString &str, QString &app, QString &name, QString &value ) { int colon = str.find( ':' ); if ( colon != -1 ) { QString tmp = str.left( colon ); value = str.mid( colon + 1 ); int dash = tmp.find( '-' ); if ( dash != -1 ) { app = tmp.left( dash ); name = tmp.mid( dash + 1 ); } } } #include "imeditorwidget.moc"