/* 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 TQt, and distribute the resulting executable, without including the source code for TQt 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( TDEListView *parent, KPluginInfo *protocol, const TQString &address, const IMContext &context ) : TDEListViewItem( 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( TQPainter *p, const TQColorGroup &cg, int column, int width, int alignment ) { if ( mPreferred ) { TQFont font = p->font(); font.setBold( true ); p->setFont( font ); } TDEListViewItem::paintCell( p, cg, column, width, alignment ); } void IMAddressLVI::setAddress( const TQString &address ) { // irc uses 0xE120 to seperate the nick and the server group. TQString serverOrGroup = address.section( TQChar( 0xE120 ), 1 ); if ( serverOrGroup.isEmpty() ) setText( 1, address ); else { TQString nickname = address.section( TQChar( 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; } TQString IMAddressLVI::address() const { return mAddress; } void IMAddressLVI::activate() { // show editor } /*===========================================================================*/ IMEditorWidget::IMEditorWidget( TQWidget *parent, const TQString &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, TQT_SIGNAL( clicked() ), TQT_SLOT( slotAdd() ) ); connect( mWidget->btnEdit, TQT_SIGNAL( clicked() ), TQT_SLOT( slotEdit() ) ); connect( mWidget->btnDelete, TQT_SIGNAL( clicked() ), TQT_SLOT( slotDelete() ) ); connect( mWidget->btnSetStandard, TQT_SIGNAL( clicked()), TQT_SLOT( slotSetStandard() ) ); connect( mWidget->lvAddresses, TQT_SIGNAL( selectionChanged() ), TQT_SLOT( slotUpdateButtons() ) ); connect( mWidget->lvAddresses, TQT_SIGNAL( doubleClicked( TQListViewItem*, const TQPoint&, int ) ), TQT_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 ", TQString( TQChar( 0xE120 ) ), true ); mProtocols = KPluginInfo::fromServices( TDETrader::self()->query( TQString::fromLatin1( "KABC/IMProtocol" ) ) ); // order the protocols by putting them in a qmap, then sorting the set of keys and recreating the list TQMap protocolMap; TQValueList::ConstIterator it; TQValueList sorted; for ( it = mProtocols.begin(); it != mProtocols.end(); ++it ) protocolMap.insert( (*it)->name(), (*it) ); TQStringList keys = protocolMap.keys(); keys.sort(); TQStringList::ConstIterator keyIt = keys.begin(); TQStringList::ConstIterator end = keys.end(); for ( ; keyIt != end; ++keyIt ) sorted.append( protocolMap[*keyIt] ); mProtocols = sorted; } TQValueList 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 TQStringList customs = addr->customs(); TQStringList::ConstIterator it; bool isSet = false; for ( it = customs.begin(); it != customs.end(); ++it ) { TQString app, name, value; splitField( *it, app, name, value ); if ( app.startsWith( TQString::fromLatin1( "messaging/" ) ) ) { if ( name == TQString::fromLatin1( "All" ) ) { KPluginInfo *protocol = protocolFromString( app ); if ( protocol ) { TQStringList addresses = TQStringList::split( TQChar( 0xE000 ), value ); TQStringList::iterator end = addresses.end(); for ( TQStringList::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 TQValueList::ConstIterator protocolIt; for ( protocolIt = mChangedProtocols.begin(); protocolIt != mChangedProtocols.end(); ++protocolIt ) { TQStringList lst; TQListViewItemIterator addressIt( mWidget->lvAddresses ); while ( addressIt.current() ) { IMAddressLVI* currentAddress = static_cast( *addressIt ); if ( currentAddress->protocol() == *protocolIt ) lst.append( currentAddress->address() ); ++addressIt; } TQString addrBookField = (*protocolIt)->property( "X-TDE-InstantMessagingKABCField" ).toString(); if ( !lst.isEmpty() ) addr->insertCustom( addrBookField, TQString::fromLatin1( "All" ), lst.join( TQChar( 0xE000 ) ) ); else addr->removeCustom( addrBookField, TQString::fromLatin1( "All" ) ); } } void IMEditorWidget::setReadOnly( bool readOnly ) { mReadOnly = readOnly; slotUpdateButtons(); } void IMEditorWidget::slotSetStandard() { TQListViewItemIterator it( mWidget->lvAddresses, TQListViewItemIterator::Selected ); // Just set the first one selected as standard if ( IMAddressLVI *current = static_cast( it.current() ) ) { TQListViewItemIterator 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; TQListViewItemIterator it( mWidget->lvAddresses, TQListViewItemIterator::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, TQT_SIGNAL( inValidState( bool ) ), &addDialog, TQT_SLOT( enableButtonOK( bool ) ) ); addDialog.setMainWidget( addressWid ); if ( addDialog.exec() == TQDialog::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() { if( mReadOnly ) return; TQListViewItemIterator it( mWidget->lvAddresses, TQListViewItemIterator::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, TQT_SIGNAL( inValidState( bool ) ), &editDialog, TQT_SLOT( enableButtonOK( bool ) ) ); editDialog.setMainWidget( addressWid ); if ( editDialog.exec() == TQDialog::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; { TQListViewItemIterator it( mWidget->lvAddresses, TQListViewItemIterator::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; TQListViewItemIterator 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 ); } TQString IMEditorWidget::preferred() const { TQString retval( mPreferred ); return retval.replace( TQChar( 0xE120 ), " on " ); } KPluginInfo * IMEditorWidget::protocolFromString( const TQString &fieldValue ) const { TQValueList::ConstIterator it; KPluginInfo * protocol = 0; for ( it = mProtocols.begin(); it != mProtocols.end(); ++it ) { if ( (*it)->property( "X-TDE-InstantMessagingKABCField" ).toString() == fieldValue ) { protocol = *it; break; } } return protocol; } void IMEditorWidget::splitField( const TQString &str, TQString &app, TQString &name, TQString &value ) { int colon = str.find( ':' ); if ( colon != -1 ) { TQString 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"