You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepim/kaddressbook/editors/imeditorwidget.cpp

492 lines
15 KiB

/*
IM address editor widget for KAddressBook
Copyright (c) 2004 Will Stephenson <lists@stevello.free-online.co.uk>
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 <qlistview.h>
#include <qstringlist.h>
#include <qvbox.h>
#include <qlayout.h>
#include <qfont.h>
#include <qpainter.h>
#include <kdialogbase.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kplugininfo.h>
#include <kpushbutton.h>
#include <ktrader.h>
#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( "<nickname> on <server>","%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<QString, KPluginInfo *> protocolMap;
QValueList<KPluginInfo *>::ConstIterator it;
QValueList<KPluginInfo *> 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<KPluginInfo *> 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<KPluginInfo *>::ConstIterator protocolIt;
for ( protocolIt = mChangedProtocols.begin(); protocolIt != mChangedProtocols.end(); ++protocolIt ) {
QStringList lst;
QListViewItemIterator addressIt( mWidget->lvAddresses );
while ( addressIt.current() ) {
IMAddressLVI* currentAddress = static_cast<IMAddressLVI*>( *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<IMAddressLVI*>( it.current() ) ) {
QListViewItemIterator it2( mWidget->lvAddresses );
while ( it2.current() ) {
IMAddressLVI *item = static_cast<IMAddressLVI*>( 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<IMAddressLVI*>( 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<IMAddressLVI*>( 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<IMAddressLVI*>( *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<IMAddressLVI*>( 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<KPluginInfo *>::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"