diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | bcb704366cb5e333a626c18c308c7e0448a8e69f (patch) | |
tree | f0d6ab7d78ecdd9207cf46536376b44b91a1ca71 /kopete/protocols/oscar/aim | |
download | tdenetwork-bcb704366cb5e333a626c18c308c7e0448a8e69f.tar.gz tdenetwork-bcb704366cb5e333a626c18c308c7e0448a8e69f.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdenetwork@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kopete/protocols/oscar/aim')
24 files changed, 4134 insertions, 0 deletions
diff --git a/kopete/protocols/oscar/aim/Makefile.am b/kopete/protocols/oscar/aim/Makefile.am new file mode 100644 index 00000000..91d12552 --- /dev/null +++ b/kopete/protocols/oscar/aim/Makefile.am @@ -0,0 +1,18 @@ +SUBDIRS = ui +METASOURCES = AUTO +AM_CPPFLAGS = -I$(srcdir)/../ \ + -I$(srcdir)/ui/ \ + -I$(top_builddir)/kopete/protocols/oscar/aim/ui \ + -I$(srcdir)/../liboscar \ + $(KOPETE_INCLUDES) $(all_includes) + +kde_module_LTLIBRARIES = kopete_aim.la + +kopete_aim_la_SOURCES = aimprotocol.cpp aimaccount.cpp aimcontact.cpp aimuserinfo.cpp aimjoinchat.cpp aimchatsession.cpp + +kopete_aim_la_LDFLAGS = -no-undefined -module $(KDE_PLUGIN) $(all_libraries) +kopete_aim_la_LIBADD = ../libkopete_oscar.la ui/libkopeteaimui.la \ + $(top_builddir)/kopete/libkopete/libkopete.la + +service_DATA = kopete_aim.desktop aim.protocol +servicedir = $(kde_servicesdir) diff --git a/kopete/protocols/oscar/aim/aim.protocol b/kopete/protocols/oscar/aim/aim.protocol new file mode 100644 index 00000000..ae9f6c69 --- /dev/null +++ b/kopete/protocols/oscar/aim/aim.protocol @@ -0,0 +1,13 @@ +[Protocol] +exec=kopete "%u" +protocol=aim +input=none +output=none +helper=true +listing=false +reading=false +writing=false +makedir=false +deleting=false +URIMode=rawuri +Icon=aim_icon diff --git a/kopete/protocols/oscar/aim/aimaccount.cpp b/kopete/protocols/oscar/aim/aimaccount.cpp new file mode 100644 index 00000000..c6228040 --- /dev/null +++ b/kopete/protocols/oscar/aim/aimaccount.cpp @@ -0,0 +1,924 @@ +/* + aimaccount.cpp - Oscar Protocol Plugin, AIM part + + Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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. * + * * + ************************************************************************* +*/ + +#include <qdom.h> +#include <qfile.h> + +#include <kdebug.h> +#include <kconfig.h> +#include <kdialogbase.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <kmessagebox.h> +#include <kmdcodec.h> + +#include "kopeteawayaction.h" +#include "kopetepassword.h" +#include "kopetestdaction.h" +#include "kopeteuiglobal.h" +#include "kopetecontactlist.h" +#include "kopetemetacontact.h" +#include "kopeteprotocol.h" +#include "kopetechatsessionmanager.h" +#include "kopeteview.h" +#include <kopeteuiglobal.h> + +#include "aimprotocol.h" +#include "aimaccount.h" +#include "aimchatsession.h" +#include "aimcontact.h" +#include "aimuserinfo.h" +#include "aimjoinchat.h" +#include "oscarmyselfcontact.h" +#include "oscarvisibilitydialog.h" + +#include "oscarutils.h" +#include "client.h" +#include "ssimanager.h" + + +const DWORD AIM_ONLINE = 0x0; +const DWORD AIM_AWAY = 0x1; + +namespace Kopete { class MetaContact; } + +AIMMyselfContact::AIMMyselfContact( AIMAccount *acct ) +: OscarMyselfContact( acct ) +{ + m_acct = acct; +} + +void AIMMyselfContact::userInfoUpdated() +{ + if ( ( details().userClass() & 32 ) == 0 ) + setOnlineStatus( static_cast<AIMProtocol*>( protocol() )->statusOnline ); //we're online + else + setOnlineStatus( static_cast<AIMProtocol*>( protocol() )->statusAway ); //we're away +} + +void AIMMyselfContact::setOwnProfile( const QString& newProfile ) +{ + m_profileString = newProfile; + if ( m_acct->isConnected() ) + m_acct->engine()->updateProfile( newProfile ); +} + +QString AIMMyselfContact::userProfile() +{ + return m_profileString; +} + +Kopete::ChatSession* AIMMyselfContact::manager( Kopete::Contact::CanCreateFlags canCreate, + Oscar::WORD exchange, const QString& room ) +{ + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << endl; + Kopete::ContactPtrList chatMembers; + chatMembers.append( this ); + Kopete::ChatSession* genericManager = 0L; + genericManager = Kopete::ChatSessionManager::self()->findChatSession( account()->myself(), chatMembers, protocol() ); + AIMChatSession* session = dynamic_cast<AIMChatSession*>( genericManager ); + + if ( !session && canCreate == Contact::CanCreate ) + { + session = new AIMChatSession( this, chatMembers, account()->protocol(), exchange, room ); + session->setEngine( m_acct->engine() ); + + connect( session, SIGNAL( messageSent( Kopete::Message&, Kopete::ChatSession* ) ), + this, SLOT( sendMessage( Kopete::Message&, Kopete::ChatSession* ) ) ); + m_chatRoomSessions.append( session ); + } + return session; +} + +void AIMMyselfContact::chatSessionDestroyed( Kopete::ChatSession* session ) +{ + m_chatRoomSessions.remove( session ); +} + +void AIMMyselfContact::sendMessage( Kopete::Message& message, Kopete::ChatSession* session ) +{ + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "sending a message" << endl; + //TODO: remove duplication - factor into a message utils class or something + Oscar::Message msg; + QString s; + + if (message.plainBody().isEmpty()) // no text, do nothing + return; + //okay, now we need to change the message.escapedBody from real HTML to aimhtml. + //looking right now for docs on that "format". + //looks like everything except for alignment codes comes in the format of spans + + //font-style:italic -> <i> + //font-weight:600 -> <b> (anything > 400 should be <b>, 400 is not bold) + //text-decoration:underline -> <u> + //font-family: -> <font face=""> + //font-size:xxpt -> <font ptsize=xx> + + s=message.escapedBody(); + s.replace ( QRegExp( QString::fromLatin1("<span style=\"([^\"]*)\">([^<]*)</span>")), + QString::fromLatin1("<style>\\1;\"\\2</style>")); + + s.replace ( QRegExp( QString::fromLatin1("<style>([^\"]*)font-style:italic;([^\"]*)\"([^<]*)</style>")), + QString::fromLatin1("<i><style>\\1\\2\"\\3</style></i>")); + + s.replace ( QRegExp( QString::fromLatin1("<style>([^\"]*)font-weight:600;([^\"]*)\"([^<]*)</style>")), + QString::fromLatin1("<b><style>\\1\\2\"\\3</style></b>")); + + s.replace ( QRegExp( QString::fromLatin1("<style>([^\"]*)text-decoration:underline;([^\"]*)\"([^<]*)</style>")), + QString::fromLatin1("<u><style>\\1\\2\"\\3</style></u>")); + + s.replace ( QRegExp( QString::fromLatin1("<style>([^\"]*)font-family:([^;]*);([^\"]*)\"([^<]*)</style>")), + QString::fromLatin1("<font face=\"\\2\"><style>\\1\\3\"\\4</style></font>")); + + s.replace ( QRegExp( QString::fromLatin1("<style>([^\"]*)font-size:([^p]*)pt;([^\"]*)\"([^<]*)</style>")), + QString::fromLatin1("<font ptsize=\"\\2\"><style>\\1\\3\"\\4</style></font>")); + + s.replace ( QRegExp( QString::fromLatin1("<style>([^\"]*)color:([^;]*);([^\"]*)\"([^<]*)</style>")), + QString::fromLatin1("<font color=\"\\2\"><style>\\1\\3\"\\4</style></font>")); + + s.replace ( QRegExp( QString::fromLatin1("<style>([^\"]*)\"([^<]*)</style>")), + QString::fromLatin1("\\2")); + + //okay now change the <font ptsize="xx"> to <font size="xx"> + + //0-9 are size 1 + s.replace ( QRegExp ( QString::fromLatin1("<font ptsize=\"\\d\">")), + QString::fromLatin1("<font size=\"1\">")); + //10-11 are size 2 + s.replace ( QRegExp ( QString::fromLatin1("<font ptsize=\"1[01]\">")), + QString::fromLatin1("<font size=\"2\">")); + //12-13 are size 3 + s.replace ( QRegExp ( QString::fromLatin1("<font ptsize=\"1[23]\">")), + QString::fromLatin1("<font size=\"3\">")); + //14-16 are size 4 + s.replace ( QRegExp ( QString::fromLatin1("<font ptsize=\"1[456]\">")), + QString::fromLatin1("<font size=\"4\">")); + //17-22 are size 5 + s.replace ( QRegExp ( QString::fromLatin1("<font ptsize=\"(?:1[789]|2[012])\">")), + QString::fromLatin1("<font size=\"5\">")); + //23-29 are size 6 + s.replace ( QRegExp ( QString::fromLatin1("<font ptsize=\"2[3456789]\">")),QString::fromLatin1("<font size=\"6\">")); + //30- (and any I missed) are size 7 + s.replace ( QRegExp ( QString::fromLatin1("<font ptsize=\"[^\"]*\">")),QString::fromLatin1("<font size=\"7\">")); + + s.replace ( QRegExp ( QString::fromLatin1("<br[ /]*>")), QString::fromLatin1("<br>") ); + + kdDebug(14190) << k_funcinfo << "sending " + << s << endl; + + msg.setSender( contactId() ); + msg.setText( Oscar::Message::UserDefined, s, m_acct->defaultCodec() ); + msg.setTimestamp(message.timestamp()); + msg.setType(0x03); + msg.addProperty( Oscar::Message::ChatRoom ); + + AIMChatSession* aimSession = dynamic_cast<AIMChatSession*>( session ); + if ( !aimSession ) + { + kdWarning(OSCAR_AIM_DEBUG) << "couldn't convert to AIM chat room session!" << endl; + session->messageSucceeded(); + return; + } + msg.setExchange( aimSession->exchange() ); + msg.setChatRoom( aimSession->roomName() ); + + m_acct->engine()->sendMessage( msg ); + //session->appendMessage( message ); + session->messageSucceeded(); +} + + +AIMAccount::AIMAccount(Kopete::Protocol *parent, QString accountID, const char *name) + : OscarAccount(parent, accountID, name, false) +{ + kdDebug(14152) << k_funcinfo << accountID << ": Called."<< endl; + AIMMyselfContact* mc = new AIMMyselfContact( this ); + setMyself( mc ); + myself()->setOnlineStatus( static_cast<AIMProtocol*>( parent )->statusOffline ); + QString profile = configGroup()->readEntry( "Profile", + i18n( "Visit the Kopete website at <a href=\"http://kopete.kde.org\">http://kopete.kde.org</a>") ); + mc->setOwnProfile( profile ); + + m_joinChatDialog = 0; + m_visibilityDialog = 0; + QObject::connect( Kopete::ContactList::self(), + SIGNAL( globalIdentityChanged( const QString&, const QVariant& ) ), + this, + SLOT( slotGlobalIdentityChanged( const QString&, const QVariant& ) ) ); + + QObject::connect( engine(), SIGNAL( chatRoomConnected( WORD, const QString& ) ), + this, SLOT( connectedToChatRoom( WORD, const QString& ) ) ); + + QObject::connect( engine(), SIGNAL( userJoinedChat( Oscar::WORD, const QString&, const QString& ) ), + this, SLOT( userJoinedChat( Oscar::WORD, const QString&, const QString& ) ) ); + + QObject::connect( engine(), SIGNAL( userLeftChat( Oscar::WORD, const QString&, const QString& ) ), + this, SLOT( userLeftChat( Oscar::WORD, const QString&, const QString& ) ) ); + + QObject::connect( this, SIGNAL( buddyIconChanged() ), this, SLOT( slotBuddyIconChanged() ) ); + +} + +AIMAccount::~AIMAccount() +{ +} + +OscarContact *AIMAccount::createNewContact( const QString &contactId, Kopete::MetaContact *parentContact, const SSI& ssiItem ) +{ + AIMContact* contact = new AIMContact( this, contactId, parentContact, QString::null, ssiItem ); + if ( !ssiItem.alias().isEmpty() ) + contact->setProperty( Kopete::Global::Properties::self()->nickName(), ssiItem.alias() ); + + return contact; +} + +QString AIMAccount::sanitizedMessage( const QString& message ) +{ + QDomDocument doc; + QString domError; + int errLine = 0, errCol = 0; + doc.setContent( message, false, &domError, &errLine, &errCol ); + if ( !domError.isEmpty() ) //error parsing, do nothing + { + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "error from dom document conversion: " + << domError << endl; + return message; + } + else + { + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "conversion to dom document successful." + << "looking for font tags" << endl; + QDomNodeList fontTagList = doc.elementsByTagName( "font" ); + if ( fontTagList.count() == 0 ) + { + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "No font tags found. Returning normal message" << endl; + return message; + } + else + { + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "Found font tags. Attempting replacement" << endl; + uint numFontTags = fontTagList.count(); + for ( uint i = 0; i < numFontTags; i++ ) + { + QDomNode fontNode = fontTagList.item(i); + QDomElement fontEl; + if ( !fontNode.isNull() && fontNode.isElement() ) + fontEl = fontTagList.item(i).toElement(); + else + continue; + if ( fontEl.hasAttribute( "back" ) ) + { + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "Found attribute to replace. Doing replacement" << endl; + QString backgroundColor = fontEl.attribute( "back" ); + backgroundColor.insert( 0, "background-color: " ); + backgroundColor.append( ';' ); + fontEl.setAttribute( "style", backgroundColor ); + fontEl.removeAttribute( "back" ); + } + } + } + } + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "sanitized message is " << doc.toString(); + return doc.toString(); +} + +KActionMenu* AIMAccount::actionMenu() +{ +// kdDebug(14152) << k_funcinfo << accountId() << ": Called." << endl; + // mActionMenu is managed by Kopete::Account. It is deleted when + // it is no longer shown, so we can (safely) just make a new one here. + KActionMenu *mActionMenu = new KActionMenu(accountId(), + myself()->onlineStatus().iconFor( this ), this, "AIMAccount::mActionMenu"); + + AIMProtocol *p = AIMProtocol::protocol(); + + QString accountNick = myself()->property( Kopete::Global::Properties::self()->nickName() ).value().toString(); + mActionMenu->popupMenu()->insertTitle( myself()->onlineStatus().iconFor( myself() ), + i18n( "%2 <%1>" ).arg( accountId(), accountNick )); + + mActionMenu->insert( new KAction( i18n("Online"), p->statusOnline.iconFor( this ), 0, this, + SLOT( slotGoOnline() ), mActionMenu, "AIMAccount::mActionOnline") ); + + KAction* mActionAway = new Kopete::AwayAction(i18n("Away"), p->statusAway.iconFor( this ), 0, this, + SLOT(slotGoAway( const QString & )), this, "AIMAccount::mActionNA" ); + mActionAway->setEnabled( isConnected() ); + mActionMenu->insert( mActionAway ); + + KAction* mActionOffline = new KAction( i18n("Offline"), p->statusOffline.iconFor(this), 0, this, + SLOT( slotGoOffline() ), mActionMenu, "AIMAccount::mActionOffline"); + + mActionMenu->insert( mActionOffline ); + mActionMenu->popupMenu()->insertSeparator(); + + KAction* m_joinChatAction = new KAction( i18n( "Join Chat..." ), QString::null, 0, this, + SLOT( slotJoinChat() ), mActionMenu, "join_a_chat" ); + + mActionMenu->insert( new KToggleAction( i18n( "Set Visibility..." ), 0, 0, + this, SLOT( slotSetVisiblility() ), this, + "AIMAccount::mActionSetVisibility") ); + + mActionMenu->insert( m_joinChatAction ); + + KAction* m_editInfoAction = new KAction( i18n( "Edit User Info..." ), "identity", 0, + this, SLOT( slotEditInfo() ), mActionMenu, "actionEditInfo"); + + mActionMenu->insert( m_editInfoAction ); + + return mActionMenu; +} + +void AIMAccount::setAway(bool away, const QString &awayReason) +{ +// kdDebug(14152) << k_funcinfo << accountId() << "reason is " << awayReason << endl; + if ( away ) + { + engine()->setStatus( Client::Away, awayReason ); + AIMMyselfContact* me = static_cast<AIMMyselfContact *> ( myself() ); + me->setLastAwayMessage(awayReason); + me->setProperty( Kopete::Global::Properties::self()->awayMessage(), awayReason ); + } + else + { + engine()->setStatus( Client::Online ); + AIMMyselfContact* me = static_cast<AIMMyselfContact *> ( myself() ); + me->setLastAwayMessage(QString::null); + me->removeProperty( Kopete::Global::Properties::self()->awayMessage() ); + } +} + +void AIMAccount::setOnlineStatus( const Kopete::OnlineStatus& status, const QString& reason ) +{ + kdDebug(14152) << k_funcinfo << "called with reason = " << reason <<" status = "<< status.status() << endl;; + if ( status.status() == Kopete::OnlineStatus::Online ) + setAway( false ); + if ( status.status() == Kopete::OnlineStatus::Away ) + setAway( true, reason ); +} + + +void AIMAccount::setUserProfile(const QString &profile) +{ + kdDebug(14152) << k_funcinfo << "called." << endl; + AIMMyselfContact* aimmc = dynamic_cast<AIMMyselfContact*>( myself() ); + if ( aimmc ) + aimmc->setOwnProfile( profile ); + configGroup()->writeEntry( QString::fromLatin1( "Profile" ), profile ); +} + +void AIMAccount::slotEditInfo() +{ + if ( !isConnected() ) + { + KMessageBox::sorry( Kopete::UI::Global::mainWidget(), + i18n( "Editing your user info is not possible because " + "you are not connected." ), + i18n( "Unable to edit user info" ) ); + return; + } + AIMUserInfoDialog *myInfo = new AIMUserInfoDialog(static_cast<AIMContact *>( myself() ), this, true, 0L, "myInfo"); + myInfo->exec(); // This is a modal dialog +} + +void AIMAccount::slotGlobalIdentityChanged( const QString& key, const QVariant& value ) +{ + //do something with the photo + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "Global identity changed" << endl; + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "key: " << key << endl; + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "value: " << value << endl; + + if( !configGroup()->readBoolEntry("ExcludeGlobalIdentity", false) ) + { + if ( key == Kopete::Global::Properties::self()->nickName().key() ) + { + //edit ssi item to change alias (if possible) + } + + if ( key == Kopete::Global::Properties::self()->photo().key() ) + { + setBuddyIcon( value.toString() ); + } + } +} + +void AIMAccount::slotBuddyIconChanged() +{ + // need to disconnect because we could end up with many connections + QObject::disconnect( engine(), SIGNAL( iconServerConnected() ), this, SLOT( slotBuddyIconChanged() ) ); + if ( !engine()->isActive() ) + { + QObject::connect( engine(), SIGNAL( iconServerConnected() ), this, SLOT( slotBuddyIconChanged() ) ); + return; + } + + QString photoPath = myself()->property( Kopete::Global::Properties::self()->photo() ).value().toString(); + + SSIManager* ssi = engine()->ssiManager(); + Oscar::SSI item = ssi->findItemForIconByRef( 1 ); + + if ( photoPath.isEmpty() ) + { + if ( item ) + { + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "Removing icon hash item from ssi" << endl; + Oscar::SSI s(item); + + //remove hash and alias + QValueList<TLV> tList( item.tlvList() ); + TLV t = Oscar::findTLV( tList, 0x00D5 ); + if ( t ) + tList.remove( t ); + + item.setTLVList( tList ); + //s is old, item is new. modification will occur + engine()->modifySSIItem( s, item ); + } + } + else + { + QFile iconFile( photoPath ); + iconFile.open( IO_ReadOnly ); + + KMD5 iconHash; + iconHash.update( iconFile ); + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "hash is :" << iconHash.hexDigest() << endl; + + //find old item, create updated item + if ( !item ) + { + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "no existing icon hash item in ssi. creating new" << endl; + + TLV t; + t.type = 0x00D5; + t.data.resize( 18 ); + t.data[0] = 0x00; + t.data[1] = 0x10; + memcpy(t.data.data() + 2, iconHash.rawDigest(), 16); + t.length = t.data.size(); + + QValueList<Oscar::TLV> list; + list.append( t ); + + Oscar::SSI s( "1", 0, ssi->nextContactId(), ROSTER_BUDDYICONS, list ); + + //item is a non-valid ssi item, so the function will add an item + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "setting new icon item" << endl; + engine()->modifySSIItem( item, s ); + } + else + { //found an item + Oscar::SSI s(item); + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "modifying old item in ssi." << endl; + QValueList<TLV> tList( item.tlvList() ); + + TLV t = Oscar::findTLV( tList, 0x00D5 ); + if ( t ) + tList.remove( t ); + else + t.type = 0x00D5; + + t.data.resize( 18 ); + t.data[0] = 0x00; + t.data[1] = 0x10; + memcpy(t.data.data() + 2, iconHash.rawDigest(), 16); + t.length = t.data.size(); + tList.append( t ); + + item.setTLVList( tList ); + //s is old, item is new. modification will occur + engine()->modifySSIItem( s, item ); + } + iconFile.close(); + } +} + +void AIMAccount::slotJoinChat() +{ + if ( !isConnected() ) + { + KMessageBox::sorry( Kopete::UI::Global::mainWidget(), + i18n( "Joining an AIM chat room is not possible because " + "you are not connected." ), + i18n( "Unable to Join AIM Chat Room" ) ); + return; + } + + //get the exchange info + //create the dialog + //join the chat room + if ( !m_joinChatDialog ) + { + m_joinChatDialog = new AIMJoinChatUI( this, false, Kopete::UI::Global::mainWidget() ); + QObject::connect( m_joinChatDialog, SIGNAL( closing( int ) ), + this, SLOT( joinChatDialogClosed( int ) ) ); + QValueList<int> list = engine()->chatExchangeList(); + m_joinChatDialog->setExchangeList( list ); + m_joinChatDialog->show(); + } + else + m_joinChatDialog->raise(); +} + +void AIMAccount::slotGoOnline() +{ + if ( myself()->onlineStatus().status() == Kopete::OnlineStatus::Away ) + { + kdDebug(14152) << k_funcinfo << accountId() << " was away. welcome back." << endl; + engine()->setStatus( Client::Online ); + myself()->removeProperty( Kopete::Global::Properties::self()->awayMessage() ); + } + else if ( myself()->onlineStatus().status() == Kopete::OnlineStatus::Offline ) + { + kdDebug(14152) << k_funcinfo << accountId() << " was offline. time to connect" << endl; + OscarAccount::connect(); + } + else + { + kdDebug(14152) << k_funcinfo << accountId() << " is already online, doing nothing" << endl; + } +} + +void AIMAccount::slotGoAway(const QString &message) +{ + kdDebug(14152) << k_funcinfo << message << endl; + setAway(true, message); +} + +void AIMAccount::joinChatDialogClosed( int code ) +{ + if ( code == QDialog::Accepted ) + { + //join the chat + kdDebug(14152) << k_funcinfo << "chat accepted." << endl; + engine()->joinChatRoom( m_joinChatDialog->roomName(), + m_joinChatDialog->exchange().toInt() ); + } + + m_joinChatDialog->delayedDestruct(); + m_joinChatDialog = 0L; +} + +void AIMAccount::loginActions() +{ + OscarAccount::loginActions(); + + using namespace AIM::PrivacySettings; + int privacySetting = this->configGroup()->readNumEntry( "PrivacySetting", AllowAll ); + this->setPrivacySettings( privacySetting ); +} + +void AIMAccount::disconnected( DisconnectReason reason ) +{ + kdDebug( OSCAR_AIM_DEBUG ) << k_funcinfo << "Attempting to set status offline" << endl; + myself()->setOnlineStatus( static_cast<AIMProtocol*>( protocol() )->statusOffline ); + + QDictIterator<Kopete::Contact> it( contacts() ); + for( ; it.current(); ++it ) + { + OscarContact* oc = dynamic_cast<OscarContact*>( it.current() ); + if ( oc ) + oc->setOnlineStatus( static_cast<AIMProtocol*>( protocol() )->statusOffline ); + } + + OscarAccount::disconnected( reason ); +} + +void AIMAccount::messageReceived( const Oscar::Message& message ) +{ + kdDebug(14152) << k_funcinfo << " Got a message, calling OscarAccount::messageReceived" << endl; + // Want to call the parent to do everything else + if ( message.type() != 0x0003 ) + { + OscarAccount::messageReceived(message); + + // Check to see if our status is away, and send an away message + // Might be duplicate code from the parent class to get some needed information + // Perhaps a refactoring is needed. + kdDebug(14152) << k_funcinfo << "Checking to see if I'm online.." << endl; + if( myself()->onlineStatus().status() == Kopete::OnlineStatus::Away ) + { + QString sender = Oscar::normalize( message.sender() ); + AIMContact* aimSender = static_cast<AIMContact *> ( contacts()[sender] ); //should exist now + if ( !aimSender ) + { + kdWarning(OSCAR_RAW_DEBUG) << "For some reason, could not get the contact " + << "That this message is from: " << message.sender() << ", Discarding message" << endl; + return; + } + // Create, or get, a chat session with the contact + Kopete::ChatSession* chatSession = aimSender->manager( Kopete::Contact::CanCreate ); + + // get the away message we have set + AIMMyselfContact* myContact = static_cast<AIMMyselfContact *> ( myself() ); + QString msg = myContact->lastAwayMessage(); + kdDebug(14152) << k_funcinfo << "Got away message: " << msg << endl; + // Create the message + Kopete::Message chatMessage( myself(), aimSender, msg, Kopete::Message::Outbound, + Kopete::Message::RichText ); + kdDebug(14152) << k_funcinfo << "Sending autoresponse" << endl; + // Send the message + aimSender->sendAutoResponse( chatMessage ); + } + } + + if ( message.type() == 0x0003 ) + { + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "have chat message" << endl; + //handle chat room messages seperately + QValueList<Kopete::ChatSession*> chats = Kopete::ChatSessionManager::self()->sessions(); + QValueList<Kopete::ChatSession*>::iterator it, itEnd = chats.end(); + for ( it = chats.begin(); it != itEnd; ++it ) + { + Kopete::ChatSession* kcs = ( *it ); + AIMChatSession* session = dynamic_cast<AIMChatSession*>( kcs ); + if ( !session ) + continue; + + if ( session->exchange() == message.exchange() && + Oscar::normalize( session->roomName() ) == + Oscar::normalize( message.chatRoom() ) ) + { + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "found chat session for chat room" << endl; + Kopete::Contact* ocSender = contacts()[Oscar::normalize( message.sender() )]; + //sanitize; + QString sanitizedMsg = sanitizedMessage( message.text( defaultCodec() ) ); + + Kopete::ContactPtrList me; + me.append( myself() ); + Kopete::Message chatMessage( message.timestamp(), ocSender, me, sanitizedMsg, + Kopete::Message::Inbound, Kopete::Message::RichText ); + + session->appendMessage( chatMessage ); + } + } + } +} + +void AIMAccount::connectedToChatRoom( WORD exchange, const QString& room ) +{ + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "Creating chat room session" << endl; + Kopete::ContactPtrList emptyList; + AIMMyselfContact* me = static_cast<AIMMyselfContact*>( myself() ); + AIMChatSession* session = dynamic_cast<AIMChatSession*>( me->manager( Kopete::Contact::CanCreate, + exchange, room ) ); + session->setDisplayName( room ); + if ( session->view( true ) ) + session->raiseView(); +} + +void AIMAccount::userJoinedChat( WORD exchange, const QString& room, const QString& contact ) +{ + if ( Oscar::normalize( contact ) == Oscar::normalize( myself()->contactId() ) ) + return; + + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "user " << contact << " has joined the chat" << endl; + QValueList<Kopete::ChatSession*> chats = Kopete::ChatSessionManager::self()->sessions(); + QValueList<Kopete::ChatSession*>::iterator it, itEnd = chats.end(); + for ( it = chats.begin(); it != itEnd; ++it ) + { + Kopete::ChatSession* kcs = ( *it ); + AIMChatSession* session = dynamic_cast<AIMChatSession*>( kcs ); + if ( !session ) + continue; + + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << session->exchange() << " " << exchange << endl; + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << session->roomName() << " " << room << endl; + if ( session->exchange() == exchange && session->roomName() == room ) + { + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "found correct chat session" << endl; + Kopete::Contact* c; + if ( contacts()[Oscar::normalize( contact )] ) + c = contacts()[Oscar::normalize( contact )]; + else + { + Kopete::MetaContact* mc = addContact( Oscar::normalize( contact ), + contact, 0, Kopete::Account::Temporary ); + if ( !mc ) + kdWarning(OSCAR_AIM_DEBUG) << "Unable to add contact for chat room" << endl; + + c = mc->contacts().first(); + c->setNickName( contact ); + } + + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "adding contact" << endl; + session->addContact( c, static_cast<AIMProtocol*>( protocol() )->statusOnline, true /* suppress */ ); + } + } +} + +void AIMAccount::userLeftChat( WORD exchange, const QString& room, const QString& contact ) +{ + if ( Oscar::normalize( contact ) == Oscar::normalize( myself()->contactId() ) ) + return; + + QValueList<Kopete::ChatSession*> chats = Kopete::ChatSessionManager::self()->sessions(); + QValueList<Kopete::ChatSession*>::iterator it, itEnd = chats.end(); + for ( it = chats.begin(); it != itEnd; ++it ) + { + Kopete::ChatSession* kcs = ( *it ); + AIMChatSession* session = dynamic_cast<AIMChatSession*>( kcs ); + if ( !session ) + continue; + + if ( session->exchange() == exchange && session->roomName() == room ) + { + //delete temp contact + Kopete::Contact* c = contacts()[Oscar::normalize( contact )]; + if ( !c ) + { + kdWarning(OSCAR_AIM_DEBUG) << k_funcinfo << "couldn't find the contact that's left the chat!" << endl; + continue; + } + session->removeContact( c ); + Kopete::MetaContact* mc = c->metaContact(); + if ( mc->isTemporary() ) + { + mc->removeContact( c ); + delete c; + delete mc; + } + } + } +} + + +void AIMAccount::connectWithPassword( const QString & ) +{ + kdDebug(14152) << k_funcinfo << "accountId='" << accountId() << "'" << endl; + + // Get the screen name for this account + QString screenName = accountId(); + QString server = configGroup()->readEntry( "Server", QString::fromLatin1( "login.oscar.aol.com" ) ); + uint port = configGroup()->readNumEntry( "Port", 5190 ); + + Connection* c = setupConnection( server, port ); + + QString _password = password().cachedValue(); + if ( _password.isEmpty() ) + { + kdDebug(14150) << "Kopete is unable to attempt to sign-on to the " + << "AIM network because no password was specified in the " + << "preferences." << endl; + } + else if ( myself()->onlineStatus() == static_cast<AIMProtocol*>( protocol() )->statusOffline ) + { + kdDebug(14152) << k_funcinfo << "Logging in as " << accountId() << endl ; + updateVersionUpdaterStamp(); + engine()->start( server, port, accountId(), _password ); + engine()->connectToServer( c, server, true /* doAuth */ ); + myself()->setOnlineStatus( static_cast<AIMProtocol*>( protocol() )->statusConnecting ); + } +} + +void AIMAccount::slotSetVisiblility() +{ + if( !isConnected() ) + { + KMessageBox::sorry( Kopete::UI::Global::mainWidget(), + i18n("You must be online to set users visibility."), + i18n("ICQ Plugin") ); + return; + } + + if ( !m_visibilityDialog ) + { + m_visibilityDialog = new OscarVisibilityDialog( engine(), Kopete::UI::Global::mainWidget() ); + QObject::connect( m_visibilityDialog, SIGNAL( closing() ), + this, SLOT( slotVisibilityDialogClosed() ) ); + + //add all contacts; + OscarVisibilityDialog::ContactMap contactMap; + QMap<QString, QString> revContactMap; + + QValueList<Oscar::SSI> contactList = engine()->ssiManager()->contactList(); + QValueList<Oscar::SSI>::const_iterator it, cEnd = contactList.constEnd(); + + for ( it = contactList.constBegin(); it != cEnd; ++it ) + { + QString contactId = ( *it ).name(); + + OscarContact* oc = dynamic_cast<OscarContact*>( contacts()[( *it ).name()] ); + if ( oc ) + { + contactMap.insert( oc->nickName(), contactId ); + revContactMap.insert( contactId, oc->nickName() ); + } + else + { + contactMap.insert( contactId, contactId ); + revContactMap.insert( contactId, contactId ); + } + } + m_visibilityDialog->addContacts( contactMap ); + + //add contacts from visible list + QStringList tmpList; + + contactList = engine()->ssiManager()->visibleList(); + cEnd = contactList.constEnd(); + + for ( it = contactList.constBegin(); it != cEnd; ++it ) + tmpList.append( revContactMap[( *it ).name()] ); + + m_visibilityDialog->addVisibleContacts( tmpList ); + + //add contacts from invisible list + tmpList.clear(); + + contactList = engine()->ssiManager()->invisibleList(); + cEnd = contactList.constEnd(); + + for ( it = contactList.constBegin(); it != cEnd; ++it ) + tmpList.append( revContactMap[( *it ).name()] ); + + m_visibilityDialog->addInvisibleContacts( tmpList ); + + m_visibilityDialog->resize( 550, 350 ); + m_visibilityDialog->show(); + } + else + { + m_visibilityDialog->raise(); + } +} + +void AIMAccount::slotVisibilityDialogClosed() +{ + m_visibilityDialog->delayedDestruct(); + m_visibilityDialog = 0L; +} + +void AIMAccount::setPrivacySettings( int privacy ) +{ + using namespace AIM::PrivacySettings; + + BYTE privacyByte = 0x01; + DWORD userClasses = 0xFFFFFFFF; + + switch ( privacy ) + { + case AllowAll: + privacyByte = 0x01; + break; + case BlockAll: + privacyByte = 0x02; + break; + case AllowPremitList: + privacyByte = 0x03; + break; + case BlockDenyList: + privacyByte = 0x04; + break; + case AllowMyContacts: + privacyByte = 0x05; + break; + case BlockAIM: + privacyByte = 0x01; + userClasses = 0x00000004; + break; + } + + this->setPrivacyTLVs( privacyByte, userClasses ); +} + +void AIMAccount::setPrivacyTLVs( BYTE privacy, DWORD userClasses ) +{ + SSIManager* ssi = engine()->ssiManager(); + Oscar::SSI item = ssi->findItem( QString::null, ROSTER_VISIBILITY ); + + QValueList<Oscar::TLV> tList; + + tList.append( TLV( 0x00CA, 1, (char *)&privacy ) ); + tList.append( TLV( 0x00CB, sizeof(userClasses), (char *)&userClasses ) ); + + if ( !item ) + { + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "Adding new privacy TLV item" << endl; + Oscar::SSI s( QString::null, 0, ssi->nextContactId(), ROSTER_VISIBILITY, tList ); + engine()->modifySSIItem( item, s ); + } + else + { //found an item + Oscar::SSI s(item); + + if ( Oscar::uptateTLVs( s, tList ) == true ) + { + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "Updating privacy TLV item" << endl; + engine()->modifySSIItem( item, s ); + } + } +} + +#include "aimaccount.moc" +//kate: tab-width 4; indent-mode csands; diff --git a/kopete/protocols/oscar/aim/aimaccount.h b/kopete/protocols/oscar/aim/aimaccount.h new file mode 100644 index 00000000..034b9836 --- /dev/null +++ b/kopete/protocols/oscar/aim/aimaccount.h @@ -0,0 +1,146 @@ +/* + AIMAccount - Oscar Protocol Account + + Copyright (c) 2002 by Chris TenHarmsel <tenharmsel@staticmethod.net> + + Kopete (c) 2002 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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. * + * * + ************************************************************************* + +*/ + +#ifndef AIMACCOUNT_H +#define AIMACCOUNT_H + +#include <qdict.h> +#include <qstring.h> +#include <qwidget.h> +#include "oscartypeclasses.h" + +#include "oscaraccount.h" +#include "oscarmyselfcontact.h" + +namespace AIM +{ + namespace PrivacySettings + { + enum { AllowAll = 0, AllowMyContacts, AllowPremitList, BlockAll, BlockAIM, BlockDenyList }; + } +} + +namespace Kopete +{ +class Contact; +class Group; +class ChatSession; +} + +class KAction; +class OscarContact; +class AIMContact; +class AIMAccount; +class AIMJoinChatUI; +class AIMChatSession; +class OscarVisibilityDialog; + +class AIMMyselfContact : public OscarMyselfContact +{ +Q_OBJECT +public: + AIMMyselfContact( AIMAccount *acct ); + void userInfoUpdated(); + void setOwnProfile( const QString& newProfile ); + QString userProfile(); + void setLastAwayMessage( const QString& msg) {m_lastAwayMessage = msg;} + QString lastAwayMessage() { return m_lastAwayMessage; }; + + virtual Kopete::ChatSession* manager( Kopete::Contact::CanCreateFlags = Kopete::Contact::CannotCreate, + WORD exchange = 0, const QString& room = QString::null); + +public slots: + void sendMessage( Kopete::Message&, Kopete::ChatSession* session ); + void chatSessionDestroyed( Kopete::ChatSession* ); + +private: + QString m_profileString; + AIMAccount* m_acct; + /** + * There has GOT to be a better way to get this away message + */ + QString m_lastAwayMessage; + QValueList<Kopete::ChatSession*> m_chatRoomSessions; + + +}; + +class AIMAccount : public OscarAccount +{ +Q_OBJECT + +public: + AIMAccount(Kopete::Protocol *parent, QString accountID, const char *name=0L); + virtual ~AIMAccount(); + + // Accessor method for the action menu + virtual KActionMenu* actionMenu(); + + void setAway(bool away, const QString &awayReason = QString::null ); + + virtual void connectWithPassword( const QString &password ); + + void setUserProfile(const QString &profile); + + void setPrivacySettings( int privacy ); + +public slots: + /** Reimplementation from Kopete::Account */ + void setOnlineStatus( const Kopete::OnlineStatus& status, const QString& reason = QString::null ); + void slotEditInfo(); + void slotGoOnline(); + + void slotGlobalIdentityChanged( const QString&, const QVariant& ); + void slotBuddyIconChanged(); + + void slotJoinChat(); + +protected slots: + void slotGoAway(const QString&); + void joinChatDialogClosed( int ); + + virtual void loginActions(); + virtual void disconnected( Kopete::Account::DisconnectReason reason ); + virtual void messageReceived( const Oscar::Message& message ); + + void connectedToChatRoom( WORD exchange, const QString& roomName ); + void userJoinedChat( Oscar::WORD exchange, const QString& room, const QString& contact ); + void userLeftChat( Oscar::WORD exchange, const QString& room, const QString& contact ); + + void slotSetVisiblility(); + void slotVisibilityDialogClosed(); + +protected: + + /** + * Implement virtual method from OscarAccount + * This allows OscarAccount to take care of adding new contacts + */ + OscarContact *createNewContact( const QString &contactId, Kopete::MetaContact *parentContact, const SSI& ssiItem ); + + QString sanitizedMessage( const QString& message ); + +private: + // Set privacy tlv item + void setPrivacyTLVs( BYTE privacy, DWORD userClasses ); + + AIMJoinChatUI* m_joinChatDialog; + OscarVisibilityDialog* m_visibilityDialog; +}; +#endif +//kate: tab-width 4; indent-mode csands; diff --git a/kopete/protocols/oscar/aim/aimchatsession.cpp b/kopete/protocols/oscar/aim/aimchatsession.cpp new file mode 100644 index 00000000..fa0616a6 --- /dev/null +++ b/kopete/protocols/oscar/aim/aimchatsession.cpp @@ -0,0 +1,73 @@ +// aimchatsession.cpp + +// Copyright (C) 2005 Matt Rogers <mattr@kde.org> + +// 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 Steet, Fifth Floor, Boston, MA +// 02110-1301, USA. + + +#include "aimchatsession.h" +#include "kopetecontact.h" +#include "kopetechatsessionmanager.h" +#include "kopeteprotocol.h" +#include "client.h" + +AIMChatSession::AIMChatSession( const Kopete::Contact* user, Kopete::ContactPtrList others, + Kopete::Protocol* protocol, Oscar::WORD exchange, + const QString& room ) + + : Kopete::ChatSession( user, others, protocol, "AIMChatSession" ) +{ + Kopete::ChatSessionManager::self()->registerChatSession( this ); + setInstance( protocol->instance() ); + setMayInvite( false ); + m_exchange = exchange; + m_roomName = room; + m_engine = 0; +} + +AIMChatSession::~AIMChatSession() +{ + m_engine->disconnectChatRoom( m_exchange, m_roomName ); +} + +void AIMChatSession::setEngine( Client* engine ) +{ + m_engine = engine; +} + +QString AIMChatSession::roomName() const +{ + + return m_roomName; +} + +void AIMChatSession::setRoomName( const QString& room ) +{ + m_roomName = room; +} + +Oscar::WORD AIMChatSession::exchange() const +{ + return m_exchange; +} + +void AIMChatSession::setExchange( Oscar::WORD exchange ) +{ + m_exchange = exchange; +} + + +#include "aimchatsession.moc" diff --git a/kopete/protocols/oscar/aim/aimchatsession.h b/kopete/protocols/oscar/aim/aimchatsession.h new file mode 100644 index 00000000..79c0685e --- /dev/null +++ b/kopete/protocols/oscar/aim/aimchatsession.h @@ -0,0 +1,77 @@ +// aimchatsession.h +// Copyright (C) 2005 Matt Rogers <mattr@kde.org> + +// 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 Steet, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#ifndef AIMCHATSESSION_H +#define AIMCHATSESSION_H + +#include "kopetechatsession.h" +#include "oscartypes.h" + +class Client; + +class AIMChatSession : public Kopete::ChatSession +{ +Q_OBJECT +public: + AIMChatSession( const Kopete::Contact* contact, Kopete::ContactPtrList others, + Kopete::Protocol* protocol, Oscar::WORD exchange = 0, + const QString& room = QString::null ); + virtual ~AIMChatSession(); + + /** + * Set the engine to use so that we can disconnect from the chat service + * properly + */ + void setEngine( Client* engine ); + + /** + * Get the name of the AIM chat room represented by + * this ChatSession object + * @return the name of the chat room + */ + QString roomName() const; + + /** + * Set the name of the AIM chat room represented by + * this ChatSession object + * @param room the name of the AIM chat room + */ + void setRoomName( const QString& room ); + + /** + * Get the exchange of the AIM chat room represented by + * this ChatSession object + * @return the exchange of the chat room + */ + Oscar::WORD exchange() const; + + /** + * Set the exchange of the AIM chat room represented by + * this ChatSession object + * @param exchange the exchange of the AIM chat room + */ + void setExchange( Oscar::WORD exchange ); + +private: + QString m_roomName; + Oscar::WORD m_exchange; + Client* m_engine; +}; + + +#endif diff --git a/kopete/protocols/oscar/aim/aimcontact.cpp b/kopete/protocols/oscar/aim/aimcontact.cpp new file mode 100644 index 00000000..7e46c585 --- /dev/null +++ b/kopete/protocols/oscar/aim/aimcontact.cpp @@ -0,0 +1,517 @@ +/* + aimcontact.cpp - Oscar Protocol Plugin + + Copyright (c) 2003 by Will Stephenson + Kopete (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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. * + * * + ************************************************************************* +*/ + +#include <time.h> + +#include <qimage.h> +#include <qregexp.h> +#include <qtimer.h> +#include <qtextcodec.h> + +#include <kapplication.h> +#include <kactionclasses.h> +#include <klocale.h> +#include <kdebug.h> +#include <kmessagebox.h> + +#include "kopeteaway.h" +#include "kopetechatsession.h" +#include "kopeteuiglobal.h" +#include "kopetemetacontact.h" + +//liboscar +#include "client.h" +#include "oscartypes.h" +#include "oscarutils.h" +#include "ssimanager.h" + +#include "aimprotocol.h" +#include "aimuserinfo.h" +#include "aimcontact.h" +#include "aimaccount.h" + +AIMContact::AIMContact( Kopete::Account* account, const QString& name, Kopete::MetaContact* parent, + const QString& icon, const Oscar::SSI& ssiItem ) +: OscarContact(account, name, parent, icon, ssiItem ) +{ + mProtocol=static_cast<AIMProtocol *>(protocol()); + setOnlineStatus( mProtocol->statusOffline ); + + m_infoDialog = 0L; + m_warnUserAction = 0L; + mUserProfile=""; + m_haveAwayMessage = false; + m_mobile = false; + // Set the last autoresponse time to the current time yesterday + m_lastAutoresponseTime = QDateTime::currentDateTime().addDays(-1); + + QObject::connect( mAccount->engine(), SIGNAL( receivedUserInfo( const QString&, const UserDetails& ) ), + this, SLOT( userInfoUpdated( const QString&, const UserDetails& ) ) ); + QObject::connect( mAccount->engine(), SIGNAL( userIsOffline( const QString& ) ), + this, SLOT( userOffline( const QString& ) ) ); + QObject::connect( mAccount->engine(), SIGNAL( receivedAwayMessage( const QString&, const QString& ) ), + this, SLOT( updateAwayMessage( const QString&, const QString& ) ) ); + QObject::connect( mAccount->engine(), SIGNAL( receivedProfile( const QString&, const QString& ) ), + this, SLOT( updateProfile( const QString&, const QString& ) ) ); + QObject::connect( mAccount->engine(), SIGNAL( userWarned( const QString&, Q_UINT16, Q_UINT16 ) ), + this, SLOT( gotWarning( const QString&, Q_UINT16, Q_UINT16 ) ) ); + QObject::connect( mAccount->engine(), SIGNAL( haveIconForContact( const QString&, QByteArray ) ), + this, SLOT( haveIcon( const QString&, QByteArray ) ) ); + QObject::connect( mAccount->engine(), SIGNAL( iconServerConnected() ), + this, SLOT( requestBuddyIcon() ) ); + QObject::connect( this, SIGNAL( featuresUpdated() ), this, SLOT( updateFeatures() ) ); +} + +AIMContact::~AIMContact() +{ +} + +bool AIMContact::isReachable() +{ + return true; +} + +QPtrList<KAction> *AIMContact::customContextMenuActions() +{ + + QPtrList<KAction> *actionCollection = new QPtrList<KAction>(); + if ( !m_warnUserAction ) + { + m_warnUserAction = new KAction( i18n( "&Warn User" ), 0, this, SLOT( warnUser() ), this, "warnAction" ); + } + m_actionVisibleTo = new KToggleAction(i18n("Always &Visible To"), "", 0, + this, SLOT(slotVisibleTo()), this, "actionVisibleTo"); + m_actionInvisibleTo = new KToggleAction(i18n("Always &Invisible To"), "", 0, + this, SLOT(slotInvisibleTo()), this, "actionInvisibleTo"); + + bool on = account()->isConnected(); + + m_warnUserAction->setEnabled( on ); + + m_actionVisibleTo->setEnabled(on); + m_actionInvisibleTo->setEnabled(on); + + SSIManager* ssi = account()->engine()->ssiManager(); + m_actionVisibleTo->setChecked( ssi->findItem( m_ssiItem.name(), ROSTER_VISIBLE )); + m_actionInvisibleTo->setChecked( ssi->findItem( m_ssiItem.name(), ROSTER_INVISIBLE )); + + actionCollection->append( m_warnUserAction ); + + actionCollection->append(m_actionVisibleTo); + actionCollection->append(m_actionInvisibleTo); + + + return actionCollection; +} + +const QString AIMContact::awayMessage() +{ + return property(mProtocol->awayMessage).value().toString(); +} + +void AIMContact::setAwayMessage(const QString &message) +{ + kdDebug(14152) << k_funcinfo << + "Called for '" << contactId() << "', away msg='" << message << "'" << endl; + QString filteredMessage = message; + filteredMessage.replace( + QRegExp(QString::fromLatin1("<[hH][tT][mM][lL].*>(.*)</[hH][tT][mM][lL]>")), + QString::fromLatin1("\\1")); + filteredMessage.replace( + QRegExp(QString::fromLatin1("<[bB][oO][dD][yY].*>(.*)</[bB][oO][dD][yY]>")), + QString::fromLatin1("\\1") ); + QRegExp fontRemover( QString::fromLatin1("<[fF][oO][nN][tT].*>(.*)</[fF][oO][nN][tT]>") ); + fontRemover.setMinimal(true); + while ( filteredMessage.find( fontRemover ) != -1 ) + filteredMessage.replace( fontRemover, QString::fromLatin1("\\1") ); + setProperty(mProtocol->awayMessage, filteredMessage); +} + +int AIMContact::warningLevel() const +{ + return m_warningLevel; +} + +void AIMContact::updateSSIItem() +{ + if ( m_ssiItem.type() != 0xFFFF && m_ssiItem.waitingAuth() == false && + onlineStatus() == Kopete::OnlineStatus::Unknown ) + { + //make sure they're offline + setOnlineStatus( static_cast<AIMProtocol*>( protocol() )->statusOffline ); + } +} + +void AIMContact::slotUserInfo() +{ + if ( !m_infoDialog) + { + m_infoDialog = new AIMUserInfoDialog( this, static_cast<AIMAccount*>( account() ), false, Kopete::UI::Global::mainWidget(), 0 ); + if( !m_infoDialog ) + return; + connect( m_infoDialog, SIGNAL( finished() ), this, SLOT( closeUserInfoDialog() ) ); + m_infoDialog->show(); + if ( mAccount->isConnected() ) + { + mAccount->engine()->requestAIMProfile( contactId() ); + mAccount->engine()->requestAIMAwayMessage( contactId() ); + } + } + else + m_infoDialog->raise(); +} + +void AIMContact::userInfoUpdated( const QString& contact, const UserDetails& details ) +{ + if ( Oscar::normalize( contact ) != Oscar::normalize( contactId() ) ) + return; + + kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << contact << endl; + + //if they don't have an SSI alias, make sure we use the capitalization from the + //server so their contact id looks all pretty. + QString nickname = property( Kopete::Global::Properties::self()->nickName() ).value().toString(); + if ( nickname.isEmpty() || Oscar::normalize( nickname ) == Oscar::normalize( contact ) ) + setNickName( contact ); + + ( details.userClass() & CLASS_WIRELESS ) ? m_mobile = true : m_mobile = false; + + if ( ( details.userClass() & CLASS_AWAY ) == STATUS_ONLINE ) + { + if ( m_mobile ) + { + kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Contact: " << contact << " is mobile-online." << endl; + setOnlineStatus( mProtocol->statusWirelessOnline ); + } + else + { + kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Contact: " << contact << " is online." << endl; + setOnlineStatus( mProtocol->statusOnline ); //we're online + } + removeProperty( mProtocol->awayMessage ); + m_haveAwayMessage = false; + } + else if ( ( details.userClass() & CLASS_AWAY ) ) // STATUS_AWAY + { + if ( m_mobile ) + { + kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Contact: " << contact << " is mobile-away." << endl; + setOnlineStatus( mProtocol->statusWirelessOnline ); + } + else + { + kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Contact: " << contact << " is away." << endl; + setOnlineStatus( mProtocol->statusAway ); //we're away + } + if ( !m_haveAwayMessage ) //prevent cyclic away message requests + { + mAccount->engine()->requestAIMAwayMessage( contactId() ); + m_haveAwayMessage = true; + } + } + else + { + kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Contact: " << contact << " class " << details.userClass() << " is unhandled... defaulting to away." << endl; + setOnlineStatus( mProtocol->statusAway ); //we're away + if ( !m_haveAwayMessage ) //prevent cyclic away message requests + { + mAccount->engine()->requestAIMAwayMessage( contactId() ); + m_haveAwayMessage = true; + } + } + + if ( details.buddyIconHash().size() > 0 && details.buddyIconHash() != m_details.buddyIconHash() ) + { + if ( !mAccount->engine()->hasIconConnection() ) + mAccount->engine()->requestServerRedirect( 0x0010 ); + + int time = ( KApplication::random() % 10 ) * 1000; + kdDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << "updating buddy icon in " << time/1000 << " seconds" << endl; + QTimer::singleShot( time, this, SLOT( requestBuddyIcon() ) ); + } + + OscarContact::userInfoUpdated( contact, details ); +} + +void AIMContact::userOnline( const QString& userId ) +{ + if ( Oscar::normalize( userId ) == Oscar::normalize( contactId() ) ) + { + kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Getting more contact info" << endl; + setOnlineStatus( mProtocol->statusOnline ); + } +} + +void AIMContact::userOffline( const QString& userId ) +{ + if ( Oscar::normalize( userId ) == Oscar::normalize( contactId() ) ) + { + setOnlineStatus( mProtocol->statusOffline ); + removeProperty( mProtocol->awayMessage ); + } +} + +void AIMContact::updateAwayMessage( const QString& contact, const QString& message ) +{ + if ( Oscar::normalize( contact ) != Oscar::normalize( contactId() ) ) + return; + else + { + if ( message.isEmpty() ) + { + removeProperty( mProtocol->awayMessage ); + if ( !m_mobile ) + setOnlineStatus( mProtocol->statusOnline ); + else + setOnlineStatus( mProtocol->statusWirelessOnline ); + m_haveAwayMessage = false; + } + else + { + m_haveAwayMessage = true; + setAwayMessage( message ); + if ( !m_mobile ) + setOnlineStatus( mProtocol->statusAway ); + else + setOnlineStatus( mProtocol->statusWirelessAway ); + } + } + + emit updatedProfile(); +} + +void AIMContact::updateProfile( const QString& contact, const QString& profile ) +{ + if ( Oscar::normalize( contact ) != Oscar::normalize( contactId() ) ) + return; + + setProperty( mProtocol->clientProfile, profile ); + emit updatedProfile(); +} + +void AIMContact::gotWarning( const QString& contact, Q_UINT16 increase, Q_UINT16 newLevel ) +{ + //somebody just got bitchslapped! :O + Q_UNUSED( increase ); + if ( Oscar::normalize( contact ) == Oscar::normalize( contactId() ) ) + m_warningLevel = newLevel; + + //TODO add a KNotify event after merge to HEAD +} + +void AIMContact::requestBuddyIcon() +{ + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "Updating buddy icon for " << contactId() << endl; + if ( m_details.buddyIconHash().size() > 0 ) + { + account()->engine()->requestBuddyIcon( contactId(), m_details.buddyIconHash(), + m_details.iconCheckSumType() ); + } +} + +void AIMContact::haveIcon( const QString& user, QByteArray icon ) +{ + if ( Oscar::normalize( user ) != Oscar::normalize( contactId() ) ) + return; + + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "Updating icon for " << contactId() << endl; + QImage buddyIcon( icon ); + if ( buddyIcon.isNull() ) + { + kdWarning(OSCAR_AIM_DEBUG) << k_funcinfo << "Failed to convert buddy icon to QImage" << endl; + return; + } + + setProperty( Kopete::Global::Properties::self()->photo(), buddyIcon ); +} + +void AIMContact::closeUserInfoDialog() +{ + m_infoDialog->delayedDestruct(); + m_infoDialog = 0L; +} + +void AIMContact::warnUser() +{ + QString nick = property( Kopete::Global::Properties::self()->nickName() ).value().toString(); + QString message = i18n( "<qt>Would you like to warn %1 anonymously or with your name?<br>" \ + "(Warning a user on AIM will result in a \"Warning Level\"" \ + " increasing for the user you warn. Once this level has reached a" \ + " certain point, they will not be able to sign on. Please do not abuse" \ + " this function, it is meant for legitimate practices.)</qt>" ).arg( nick ); + + + int result = KMessageBox::questionYesNoCancel( Kopete::UI::Global::mainWidget(), message, + i18n( "Warn User %1?" ).arg( nick ), + i18n( "Warn Anonymously" ), i18n( "Warn" ) ); + + if ( result == KMessageBox::Yes ) + mAccount->engine()->sendWarning( contactId(), true); + else if ( result == KMessageBox::No ) + mAccount->engine()->sendWarning( contactId(), false); +} + +void AIMContact::slotVisibleTo() +{ + account()->engine()->setVisibleTo( contactId(), m_actionVisibleTo->isChecked() ); +} + +void AIMContact::slotInvisibleTo() +{ + account()->engine()->setInvisibleTo( contactId(), m_actionInvisibleTo->isChecked() ); +} + +void AIMContact::slotSendMsg(Kopete::Message& message, Kopete::ChatSession *) +{ + Oscar::Message msg; + QString s; + + if (message.plainBody().isEmpty()) // no text, do nothing + return; + //okay, now we need to change the message.escapedBody from real HTML to aimhtml. + //looking right now for docs on that "format". + //looks like everything except for alignment codes comes in the format of spans + + //font-style:italic -> <i> + //font-weight:600 -> <b> (anything > 400 should be <b>, 400 is not bold) + //text-decoration:underline -> <u> + //font-family: -> <font face=""> + //font-size:xxpt -> <font ptsize=xx> + + s=message.escapedBody(); + s.replace ( QRegExp( QString::fromLatin1("<span style=\"([^\"]*)\">([^<]*)</span>")), + QString::fromLatin1("<style>\\1;\"\\2</style>")); + + s.replace ( QRegExp( QString::fromLatin1("<style>([^\"]*)font-style:italic;([^\"]*)\"([^<]*)</style>")), + QString::fromLatin1("<i><style>\\1\\2\"\\3</style></i>")); + + s.replace ( QRegExp( QString::fromLatin1("<style>([^\"]*)font-weight:600;([^\"]*)\"([^<]*)</style>")), + QString::fromLatin1("<b><style>\\1\\2\"\\3</style></b>")); + + s.replace ( QRegExp( QString::fromLatin1("<style>([^\"]*)text-decoration:underline;([^\"]*)\"([^<]*)</style>")), + QString::fromLatin1("<u><style>\\1\\2\"\\3</style></u>")); + + s.replace ( QRegExp( QString::fromLatin1("<style>([^\"]*)font-family:([^;]*);([^\"]*)\"([^<]*)</style>")), + QString::fromLatin1("<font face=\"\\2\"><style>\\1\\3\"\\4</style></font>")); + + s.replace ( QRegExp( QString::fromLatin1("<style>([^\"]*)font-size:([^p]*)pt;([^\"]*)\"([^<]*)</style>")), + QString::fromLatin1("<font ptsize=\"\\2\"><style>\\1\\3\"\\4</style></font>")); + + s.replace ( QRegExp( QString::fromLatin1("<style>([^\"]*)color:([^;]*);([^\"]*)\"([^<]*)</style>")), + QString::fromLatin1("<font color=\"\\2\"><style>\\1\\3\"\\4</style></font>")); + + s.replace ( QRegExp( QString::fromLatin1("<style>([^\"]*)\"([^<]*)</style>")), + QString::fromLatin1("\\2")); + + //okay now change the <font ptsize="xx"> to <font size="xx"> + + //0-9 are size 1 + s.replace ( QRegExp ( QString::fromLatin1("<font ptsize=\"\\d\">")), + QString::fromLatin1("<font size=\"1\">")); + //10-11 are size 2 + s.replace ( QRegExp ( QString::fromLatin1("<font ptsize=\"1[01]\">")), + QString::fromLatin1("<font size=\"2\">")); + //12-13 are size 3 + s.replace ( QRegExp ( QString::fromLatin1("<font ptsize=\"1[23]\">")), + QString::fromLatin1("<font size=\"3\">")); + //14-16 are size 4 + s.replace ( QRegExp ( QString::fromLatin1("<font ptsize=\"1[456]\">")), + QString::fromLatin1("<font size=\"4\">")); + //17-22 are size 5 + s.replace ( QRegExp ( QString::fromLatin1("<font ptsize=\"(?:1[789]|2[012])\">")), + QString::fromLatin1("<font size=\"5\">")); + //23-29 are size 6 + s.replace ( QRegExp ( QString::fromLatin1("<font ptsize=\"2[3456789]\">")),QString::fromLatin1("<font size=\"6\">")); + //30- (and any I missed) are size 7 + s.replace ( QRegExp ( QString::fromLatin1("<font ptsize=\"[^\"]*\">")),QString::fromLatin1("<font size=\"7\">")); + + s.replace ( QRegExp ( QString::fromLatin1("<br[ /]*>")), QString::fromLatin1("<br>") ); + + // strip left over line break + s.remove( QRegExp( QString::fromLatin1( "<br>$" ) ) ); + + kdDebug(14190) << k_funcinfo << "sending " + << s << endl; + + // XXX Need to check for message size? + + if ( m_details.hasCap( CAP_UTF8 ) ) + msg.setText( Oscar::Message::UCS2, s ); + else + msg.setText( Oscar::Message::UserDefined, s, contactCodec() ); + + msg.setReceiver(mName); + msg.setTimestamp(message.timestamp()); + msg.setType(0x01); + + mAccount->engine()->sendMessage(msg); + + // Show the message we just sent in the chat window + manager(Kopete::Contact::CanCreate)->appendMessage(message); + manager(Kopete::Contact::CanCreate)->messageSucceeded(); +} + +void AIMContact::updateFeatures() +{ + setProperty( static_cast<AIMProtocol*>(protocol())->clientFeatures, m_clientFeatures ); +} + +void AIMContact::sendAutoResponse(Kopete::Message& msg) +{ + // The target time is 2 minutes later than the last message + int delta = m_lastAutoresponseTime.secsTo( QDateTime::currentDateTime() ); + kdDebug(14152) << k_funcinfo << "Last autoresponse time: " << m_lastAutoresponseTime << endl; + kdDebug(14152) << k_funcinfo << "Current time: " << QDateTime::currentDateTime() << endl; + kdDebug(14152) << k_funcinfo << "Difference: " << delta << endl; + // Check to see if we're past that time + if(delta > 120) + { + kdDebug(14152) << k_funcinfo << "Sending auto response" << endl; + + // This code was yoinked straight from OscarContact::slotSendMsg() + // If only that slot wasn't private, but I'm not gonna change it right now. + Oscar::Message message; + + if ( m_details.hasCap( CAP_UTF8 ) ) + { + message.setText( Oscar::Message::UCS2, msg.plainBody() ); + } + else + { + QTextCodec* codec = contactCodec(); + message.setText( Oscar::Message::UserDefined, msg.plainBody(), codec ); + } + + message.setTimestamp( msg.timestamp() ); + message.setSender( mAccount->accountId() ); + message.setReceiver( mName ); + message.setType( 0x01 ); + + // isAuto defaults to false + mAccount->engine()->sendMessage( message, true); + kdDebug(14152) << k_funcinfo << "Sent auto response" << endl; + manager(Kopete::Contact::CanCreate)->appendMessage(msg); + manager(Kopete::Contact::CanCreate)->messageSucceeded(); + // Update the last autoresponse time + m_lastAutoresponseTime = QDateTime::currentDateTime(); + } + else + { + kdDebug(14152) << k_funcinfo << "Not enough time since last autoresponse, NOT sending" << endl; + } +} +#include "aimcontact.moc" +//kate: tab-width 4; indent-mode csands; diff --git a/kopete/protocols/oscar/aim/aimcontact.h b/kopete/protocols/oscar/aim/aimcontact.h new file mode 100644 index 00000000..458db2f5 --- /dev/null +++ b/kopete/protocols/oscar/aim/aimcontact.h @@ -0,0 +1,102 @@ +/* + aimcontact.h - Oscar Protocol Plugin + + Copyright (c) 2003 by Will Stephenson + Copyright (c) 2004 by Matt Rogers <mattr@kde.org> + Kopete (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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. * + * * + ************************************************************************* +*/ + +#ifndef AIMCONTACT_H +#define AIMCONTACT_H + +#include <qdatetime.h> + +#include "oscarcontact.h" + + +namespace Kopete +{ +class ChatSession; +} + +class AIMAccount; +class AIMProtocol; +class AIMUserInfoDialog; + +class AIMContact : public OscarContact +{ +Q_OBJECT + +public: + AIMContact( Kopete::Account*, const QString&, Kopete::MetaContact*, + const QString& icon = QString::null, const Oscar::SSI& ssiItem = Oscar::SSI() ); + virtual ~AIMContact(); + + bool isReachable(); + QPtrList<KAction> *customContextMenuActions(); + + const QString &userProfile() { return mUserProfile; } + + virtual const QString awayMessage(); + virtual void setAwayMessage( const QString &message ); + + int warningLevel() const; + + /** + * Gets the last time an autoresponse was sent to this contact + * @returns QDateTime Object that represents the date/time + */ + QDateTime lastAutoResponseTime() {return m_lastAutoresponseTime;} + + /** Sends an auto response to this contact */ + virtual void sendAutoResponse(Kopete::Message& msg); + +public slots: + void updateSSIItem(); + void slotUserInfo(); + void userInfoUpdated( const QString& contact, const UserDetails& details ); + void userOnline( const QString& userId ); + void userOffline( const QString& userId ); + void updateAwayMessage( const QString& userId, const QString& message ); + void updateProfile( const QString& contact, const QString& profile ); + void gotWarning( const QString& contact, Q_UINT16, Q_UINT16 ); + +signals: + void updatedProfile(); + +protected slots: + virtual void slotSendMsg(Kopete::Message& message, Kopete::ChatSession *); + virtual void updateFeatures(); + +private slots: + void requestBuddyIcon(); + void haveIcon( const QString&, QByteArray ); + void closeUserInfoDialog(); + void warnUser(); + + void slotVisibleTo(); + void slotInvisibleTo(); + +private: + AIMProtocol* mProtocol; + AIMUserInfoDialog* m_infoDialog; + QString mUserProfile; + bool m_haveAwayMessage; + bool m_mobile; // Is this user mobile (i.e. do they have message forwarding on, or mobile AIM) + QDateTime m_lastAutoresponseTime; + + KAction* m_warnUserAction; + KToggleAction *m_actionVisibleTo; + KToggleAction *m_actionInvisibleTo; +}; +#endif +//kate: tab-width 4; indent-mode csands; diff --git a/kopete/protocols/oscar/aim/aimjoinchat.cpp b/kopete/protocols/oscar/aim/aimjoinchat.cpp new file mode 100644 index 00000000..8b8c78a9 --- /dev/null +++ b/kopete/protocols/oscar/aim/aimjoinchat.cpp @@ -0,0 +1,94 @@ +// aimjoinchat.cpp + +// Copyright (C) 2005 Matt Rogers <mattr@kde.org> + +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 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 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301 USA + +#include "aimjoinchat.h" + +#include <qlineedit.h> +#include <qcombobox.h> +#include <klocale.h> + +#include "aimjoinchatbase.h" +#include "aimaccount.h" + +AIMJoinChatUI::AIMJoinChatUI( AIMAccount* account, bool modal, + QWidget* parent, const char* name ) + : KDialogBase( parent, name, modal, i18n( "Join AIM Chat Room" ), + Cancel | User1, User1, true, i18n( "Join" ) ) +{ + + kdDebug(OSCAR_AIM_DEBUG) << k_funcinfo << "Account " << account->accountId() + << " joining a chat room" << endl; + + m_account = account; + + m_joinUI = new AIMJoinChatBase( this, "aimjoinchatbase" ); + + setMainWidget( m_joinUI ); + + QObject::connect( this, SIGNAL( user1Clicked() ), this, SLOT( joinChat() ) ); + QObject::connect( this, SIGNAL( cancelClicked() ), this, SLOT( closeClicked() ) ); +} + +AIMJoinChatUI::~AIMJoinChatUI() +{ + m_exchanges.clear(); +} + +void AIMJoinChatUI::setExchangeList( const QValueList<int>& list ) +{ + m_exchanges = list; + QStringList exchangeList; + QValueList<int>::const_iterator it = list.begin(); + while ( it != list.end() ) + { + exchangeList.append( QString::number( ( *it ) ) ); + ++it; + } + + + m_joinUI->exchange->insertStringList( exchangeList ); +} + +void AIMJoinChatUI::joinChat() +{ + m_roomName = m_joinUI->roomName->text(); + int item = m_joinUI->exchange->currentItem(); + m_exchange = m_joinUI->exchange->text( item ); + + emit closing( QDialog::Accepted ); +} + +void AIMJoinChatUI::closeClicked() +{ + //hmm, do nothing? + emit closing( QDialog::Rejected ); +} + +QString AIMJoinChatUI::roomName() const +{ + return m_roomName; +} + +QString AIMJoinChatUI::exchange() const +{ + return m_exchange; +} + +#include "aimjoinchat.moc" +//kate: space-indent on; indent-width 4; diff --git a/kopete/protocols/oscar/aim/aimjoinchat.h b/kopete/protocols/oscar/aim/aimjoinchat.h new file mode 100644 index 00000000..dc74a8a9 --- /dev/null +++ b/kopete/protocols/oscar/aim/aimjoinchat.h @@ -0,0 +1,62 @@ +// aimjoinchat.h + +// Copyright (C) 2005 Matt Rogers <mattr@kde.org> + +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 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 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301 USA + +#ifndef AIMJOINCHAT_H +#define AIMJOINCHAT_H + +#include <kdialogbase.h> + +#include "oscartypes.h" + +class AIMAccount; +class AIMJoinChatBase; + +class AIMJoinChatUI : public KDialogBase +{ +Q_OBJECT +public: + AIMJoinChatUI( AIMAccount*, bool modal, QWidget* parent = 0, + const char* name = 0 ); + ~AIMJoinChatUI(); + + void setExchangeList( const QValueList<int>& ); + QValueList<int> exchangeList() const; + + QString roomName() const; + QString exchange() const; + + +protected slots: + void joinChat(); + void closeClicked(); + +signals: + void closing( int ); + +private: + AIMJoinChatBase* m_joinUI; + AIMAccount* m_account; + QValueList<int> m_exchanges; + QString m_roomName; + QString m_exchange; + +}; + +#endif +//kate: space-indent on; indent-width 4; diff --git a/kopete/protocols/oscar/aim/aimprotocol.cpp b/kopete/protocols/oscar/aim/aimprotocol.cpp new file mode 100644 index 00000000..9f64fe28 --- /dev/null +++ b/kopete/protocols/oscar/aim/aimprotocol.cpp @@ -0,0 +1,320 @@ +/* + oscarprotocol.cpp - Oscar Protocol Plugin + + Copyright (c) 2002 by Tom Linsky <twl6@po.cwru.edu> + + Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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. * + * * + ************************************************************************* + */ + +#include <qstringlist.h> +#include <kgenericfactory.h> +#include <kmessagebox.h> +#include <kdebug.h> + +#include "aimprotocol.h" +#include "aimaccount.h" +#include "aimcontact.h" +#include "aimaddcontactpage.h" +#include "aimeditaccountwidget.h" + +#include "accountselector.h" +#include "kopeteaccountmanager.h" +#include "kopeteonlinestatusmanager.h" +#include "kopeteglobal.h" +#include "kopeteuiglobal.h" +#include "kopetemetacontact.h" + +#include <kdialogbase.h> +#include <kmessagebox.h> +#include <kimageio.h> + +typedef KGenericFactory<AIMProtocol> AIMProtocolFactory; + +K_EXPORT_COMPONENT_FACTORY( kopete_aim, AIMProtocolFactory( "kopete_aim" ) ) + +AIMProtocol* AIMProtocol::protocolStatic_ = 0L; + + +AIMProtocolHandler::AIMProtocolHandler() : Kopete::MimeTypeHandler(false) +{ + registerAsProtocolHandler(QString::fromLatin1("aim")); +} + +void AIMProtocolHandler::handleURL(const KURL &url) const +{ +/** + * Send a Message ================================================= + * aim:goim + * aim:goim?screenname=screen+name + * aim:goim?screenname=screen+name&message=message + * Add Buddy ====================================================== + * aim:addbuddy + * aim:addbuddy?screenname=screen+name + * Buddy Icon ===================================================== + * aim:buddyicon + * aim:buddyicon?src=image_source + * aim:buddyicon?screename=screen+name + * aim:buddyicon?src=image_source&screename=screen+name + * Get and Send Files ============================================= + * aim:getfile?screename=(sn) + * aim:sendfile?screenname=(sn) + * Register User ================================================== + * aim:RegisterUser?ScreenName=sn&Password=pw&SignonNow=False + * Away Message =================================================== + * aim:goaway?message=brb+or+something + * Chat Rooms ===================================================== + * aim:GoChat?RoomName=room+name&Exchange=number + **/ + + AIMProtocol *proto = AIMProtocol::protocol(); + kdDebug(14152) << k_funcinfo << "URL url : '" << url.url() << "'" << endl; + kdDebug(14152) << k_funcinfo << "URL path : '" << url.path() << "'" << endl; + QString command = url.path(); + QString realCommand, firstParam, secondParam; + bool needContactAddition = false; + if ( command.find( "goim", 0, false ) != -1 ) + { + realCommand = "goim"; + kdDebug(14152) << k_funcinfo << "Handling send IM request" << endl; + command.remove(0,4); + if ( command.find( "?screenname=", 0, false ) == -1 ) + { + kdWarning(14152) << k_funcinfo << "Unhandled AIM URI:" << url.url() << endl; + return; + } + command.remove( 0, 12 ); + int andSign = command.find( "&" ); + if ( andSign > 0 ) + command = command.left( andSign ); + + firstParam = command; + firstParam.replace( "+", " " ); + needContactAddition = true; + } + else + if ( command.find( "addbuddy", 0, false ) != -1 ) + { + realCommand = "addbuddy"; + kdDebug(14152) << k_funcinfo << "Handling AIM add buddy request" << endl; + command.remove( 0, 8 ); + if ( command.find( "?screenname=", 0, false ) == -1 ) + { + kdWarning(14152) << k_funcinfo << "Unhandled AIM URI:" << url.url() << endl; + return; + } + + command.remove(0, 12); + int andSign = command.find("&"); + if ( andSign > 0 ) + command = command.left(andSign); + command.replace("+", " "); + + firstParam = command; + needContactAddition = true; + } + else + if ( command.find( "gochat", 0, false ) != -1 ) + { + realCommand = "gochat"; + kdDebug(14152) << k_funcinfo << "Handling AIM chat room request" << endl; + command.remove( 0, 6 ); + + if ( command.find( "?RoomName=", 0, false ) == -1 ) + { + kdWarning(14152) << "Unhandled AIM URI: " << url.url() << endl; + return; + } + + command.remove( 0, 10 ); + + int andSign = command.find("&"); + if (andSign > 0) // strip off anything else for now + { + firstParam = command.left(andSign); + } + command.remove( 0, andSign ); + kdDebug(14152) << "command is now: " << command << endl; + command.remove( 0, 10 ); //remove "&Exchange=" + secondParam = command; + kdDebug(14152) << k_funcinfo << firstParam << " " << secondParam << endl; + firstParam.replace("+", " "); + } + + Kopete::Account *account = 0; + QDict<Kopete::Account> accounts = Kopete::AccountManager::self()->accounts(proto); + + if (accounts.count() == 1) + { + QDictIterator<Kopete::Account> it(accounts); + account = it.current(); + + } + else + { + KDialogBase *chooser = new KDialogBase(0, "chooser", true, + i18n("Choose Account"), KDialogBase::Ok|KDialogBase::Cancel, + KDialogBase::Ok, false); + AccountSelector *accSelector = new AccountSelector(proto, chooser, "accSelector"); + chooser->setMainWidget(accSelector); + + int ret = chooser->exec(); + account = accSelector->selectedItem(); + + delete chooser; + if (ret == QDialog::Rejected || account == 0) + { + kdDebug(14152) << k_funcinfo << "Cancelled" << endl; + return; + } + } + + Kopete::MetaContact* mc = 0; + if ( needContactAddition || realCommand == "addbuddy" ) + { + if ( !account->isConnected() ) + { + kdDebug(14152) << k_funcinfo << "Can't add contact, we are offline!" << endl; + KMessageBox::sorry( Kopete::UI::Global::mainWidget(), i18n("You need to be connected to be able to add contacts."), + i18n("AIM") ); + return; + } + + if (KMessageBox::questionYesNo(Kopete::UI::Global::mainWidget(), + i18n("Do you want to add '%1' to your contact list?").arg(command), + QString::null, i18n("Add"), i18n("Do Not Add")) + != KMessageBox::Yes) + { + kdDebug(14152) << k_funcinfo << "Cancelled" << endl; + return; + } + + kdDebug(14152) << k_funcinfo << + "Adding Contact; screenname = " << firstParam << endl; + mc = account->addContact(firstParam, command, 0L, Kopete::Account::Temporary); + } + + if ( realCommand == "gochat" ) + { + AIMAccount* aimAccount = dynamic_cast<AIMAccount*>( account ); + if ( aimAccount && aimAccount->isConnected() ) + { + aimAccount->engine()->joinChatRoom( firstParam, secondParam.toInt() ); + } + else + KMessageBox::sorry( Kopete::UI::Global::mainWidget(), + i18n( "Unable to connect to the chat room %1 because the account" + " for %2 is not connected." ).arg( firstParam ).arg( aimAccount->accountId() ), + QString::null ); + + } + + if ( mc && realCommand == "goim" ) + { + mc->execute(); + } + +} + + + + +AIMProtocol::AIMProtocol(QObject *parent, const char *name, const QStringList &) + : Kopete::Protocol( AIMProtocolFactory::instance(), parent, name ), + statusOnline( Kopete::OnlineStatus::Online, 2, this, 0, QString::null, i18n("Online"), i18n("Online"), Kopete::OnlineStatusManager::Online ), + statusOffline( Kopete::OnlineStatus::Offline, 2, this, 10, QString::null, i18n("Offline"), i18n("Offline"), Kopete::OnlineStatusManager::Offline ), + statusAway( Kopete::OnlineStatus::Away, 2, this, 20, "contact_away_overlay", i18n("Away"), i18n("Away"), Kopete::OnlineStatusManager::Away, + Kopete::OnlineStatusManager::HasAwayMessage ), + statusWirelessOnline( Kopete::OnlineStatus::Online, 1, this, 30, "contact_phone_overlay", i18n("Mobile"), i18n("Mobile"), + Kopete::OnlineStatusManager::Online, Kopete::OnlineStatusManager::HideFromMenu ), + statusWirelessAway( Kopete::OnlineStatus::Away, 1, this, 31, QStringList::split( " ", "contact_phone_overlay contact_away_overlay"), + i18n("Mobile Away"), i18n("Mobile Away"), Kopete::OnlineStatusManager::Away, Kopete::OnlineStatusManager::HideFromMenu ), + statusConnecting(Kopete::OnlineStatus::Connecting, 99, this, 99, "aim_connecting", i18n("Connecting...")), + awayMessage(Kopete::Global::Properties::self()->awayMessage()), + clientFeatures("clientFeatures", i18n("Client Features"), 0, false), + clientProfile( "clientProfile", i18n( "User Profile"), 0, false, true), + iconHash("iconHash", i18n("Buddy Icon MD5 Hash"), QString::null, true, false, true) +{ + if (protocolStatic_) + kdDebug(14152) << k_funcinfo << "AIM plugin already initialized" << endl; + else + protocolStatic_ = this; + + setCapabilities(0x1FFF); // setting capabilities - FIXME to use proper enum + kdDebug(14152) << k_funcinfo << "capabilities set to 0x1FFF" << endl; + addAddressBookField("messaging/aim", Kopete::Plugin::MakeIndexField); + KImageIO::registerFormats(); +} + +AIMProtocol::~AIMProtocol() +{ + protocolStatic_ =0L; +} + +AIMProtocol *AIMProtocol::protocol(void) +{ + return protocolStatic_; +} + +Kopete::Contact *AIMProtocol::deserializeContact(Kopete::MetaContact *metaContact, + const QMap<QString, QString> &serializedData, + const QMap<QString, QString> &/*addressBookData*/) +{ + + QString contactId = serializedData["contactId"]; + QString accountId = serializedData["accountId"]; + QString displayName = serializedData["displayName"]; + + // Get the account it belongs to + QDict<Kopete::Account> accounts = Kopete::AccountManager::self()->accounts( this ); + Kopete::Account *account = accounts[accountId]; + + if ( !account ) //no account + return 0; + + uint ssiGid = 0, ssiBid = 0, ssiType = 0xFFFF; + QString ssiName; + bool ssiWaitingAuth = false; + if ( serializedData.contains( "ssi_type" ) ) + { + ssiName = serializedData["ssi_name"]; + QString authStatus = serializedData["ssi_waitingAuth"]; + if ( authStatus == "true" ) + ssiWaitingAuth = true; + ssiGid = serializedData["ssi_gid"].toUInt(); + ssiBid = serializedData["ssi_bid"].toUInt(); + ssiType = serializedData["ssi_type"].toUInt(); + } + + Oscar::SSI item( ssiName, ssiGid, ssiBid, ssiType, QValueList<TLV>(), 0 ); + item.setWaitingAuth( ssiWaitingAuth ); + + AIMContact *c = new AIMContact( account, contactId, metaContact, QString::null, item ); + return c; +} + +AddContactPage *AIMProtocol::createAddContactWidget(QWidget *parent, Kopete::Account *account) +{ + return ( new AIMAddContactPage( account->isConnected(), parent ) ); +} + +KopeteEditAccountWidget *AIMProtocol::createEditAccountWidget(Kopete::Account *account, QWidget *parent) +{ + return ( new AIMEditAccountWidget( this, account, parent ) ); +} + +Kopete::Account *AIMProtocol::createNewAccount(const QString &accountId) +{ + return ( new AIMAccount( this, accountId ) ); +} + +#include "aimprotocol.moc" +// vim: set noet ts=4 sts=4 sw=4: diff --git a/kopete/protocols/oscar/aim/aimprotocol.h b/kopete/protocols/oscar/aim/aimprotocol.h new file mode 100644 index 00000000..e6c578e6 --- /dev/null +++ b/kopete/protocols/oscar/aim/aimprotocol.h @@ -0,0 +1,85 @@ +/* + oscarprotocol.h - Oscar Protocol Plugin + + Copyright (c) 2002 by Tom Linsky <twl6@po.cwru.edu> + Copyright (c) 2005 by Matt Rogers <mattr@kde.org> + Kopete (c) 2002 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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. * + * * + ************************************************************************* + */ + +#ifndef AIMPROTOCOL_H +#define AIMPROTOCOL_H + +#include "kopeteprotocol.h" +#include "kopetecontactproperty.h" +#include "kopetemimetypehandler.h" +#include "kopeteonlinestatus.h" + +#include <qmap.h> + +namespace Kopete +{ +class OnlineStatus; +} + +class AIMProtocolHandler : public Kopete::MimeTypeHandler +{ +public: + AIMProtocolHandler(); + void handleURL( const KURL & url ) const; +}; + +class AIMProtocol : public Kopete::Protocol +{ + Q_OBJECT + +public: + AIMProtocol( QObject *parent, const char *name, const QStringList &args ); + virtual ~AIMProtocol(); + /** + * Return the active instance of the protocol + * because it's a singleton, can only be used inside AIM classes, not in oscar lib + */ + static AIMProtocol *protocol(); + + bool canSendOffline() const { return false; } + + virtual Kopete::Contact *deserializeContact( Kopete::MetaContact *metaContact, + const QMap<QString, QString> &serializedData, + const QMap<QString, QString> &addressBookData ); + + AddContactPage*createAddContactWidget( QWidget *parent, Kopete::Account *account ); + KopeteEditAccountWidget* createEditAccountWidget( Kopete::Account *account, QWidget *parent ); + Kopete::Account* createNewAccount( const QString &accountId ); + + /** + * The set of online statuses that AIM contacts can have + */ + const Kopete::OnlineStatus statusOnline; + const Kopete::OnlineStatus statusOffline; + const Kopete::OnlineStatus statusAway; + const Kopete::OnlineStatus statusWirelessOnline; + const Kopete::OnlineStatus statusWirelessAway; + const Kopete::OnlineStatus statusConnecting; + + const Kopete::ContactPropertyTmpl awayMessage; + const Kopete::ContactPropertyTmpl clientFeatures; + const Kopete::ContactPropertyTmpl clientProfile; + const Kopete::ContactPropertyTmpl iconHash; + +private: + /** The active instance of oscarprotocol */ + static AIMProtocol *protocolStatic_; + AIMProtocolHandler protohandler; +}; + +#endif +//kate: tab-width 4; indent-mode csands; diff --git a/kopete/protocols/oscar/aim/aimuserinfo.cpp b/kopete/protocols/oscar/aim/aimuserinfo.cpp new file mode 100644 index 00000000..81bdd9c7 --- /dev/null +++ b/kopete/protocols/oscar/aim/aimuserinfo.cpp @@ -0,0 +1,224 @@ +/* + oscaruserinfo.cpp - Oscar Protocol Plugin + + Copyright (c) 2002 by Tom Linsky <twl6@po.cwru.edu> + + Kopete (c) 2002 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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. * + * * + ************************************************************************* + */ + +#include "aimuserinfo.h" + +#include "aimaccount.h" +#include "aimcontact.h" +#include "aimprotocol.h" + +#include <qlineedit.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qtimer.h> + +#include <klocale.h> +#include <kstandarddirs.h> +#include <ktextbrowser.h> +#include <kdebug.h> +#include <kapplication.h> + +#include <ktextedit.h> +#include <krun.h> + +AIMUserInfoDialog::AIMUserInfoDialog( Kopete::Contact *c, AIMAccount *acc, bool modal, + QWidget *parent, const char* name ) + : KDialogBase( parent, name, modal, i18n( "User Information on %1" ) + .arg( c->property( Kopete::Global::Properties::self()->nickName() ).value().toString() ), + Cancel | Ok , Ok, true ) +{ + kdDebug(14200) << k_funcinfo << "for contact '" << c->contactId() << "'" << endl; + + m_contact = c; + mAccount = acc; + + mMainWidget = new AIMUserInfoWidget(this, "aimuserinfowidget"); + setMainWidget(mMainWidget); + + QObject::connect(this, SIGNAL(okClicked()), this, SLOT(slotSaveClicked())); + QObject::connect(this, SIGNAL(user1Clicked()), this, SLOT(slotUpdateClicked())); + QObject::connect(this, SIGNAL(cancelClicked()), this, SLOT(slotCloseClicked())); + QObject::connect(c, SIGNAL(updatedProfile()), this, SLOT(slotUpdateProfile())); + + mMainWidget->txtScreenName->setText( c->contactId() ); + + QString nickName = c->property( Kopete::Global::Properties::self()->nickName() ).value().toString(); + if( nickName.isEmpty() ) + mMainWidget->txtNickName->setText( c->contactId() ); + else + mMainWidget->txtNickName->setText( nickName ); + + if(m_contact == mAccount->myself()) // edit own account profile + { + mMainWidget->lblWarnLevel->hide(); + mMainWidget->txtWarnLevel->hide(); + mMainWidget->lblIdleTime->hide(); + mMainWidget->txtIdleTime->hide(); + mMainWidget->lblOnlineSince->hide(); + mMainWidget->txtOnlineSince->hide(); + mMainWidget->txtAwayMessage->hide(); + mMainWidget->lblAwayMessage->hide(); + + userInfoView=0L; + mMainWidget->userInfoFrame->setFrameStyle(QFrame::NoFrame | QFrame::Plain); + QVBoxLayout *l = new QVBoxLayout(mMainWidget->userInfoFrame); + userInfoEdit = new KTextEdit(QString::null, QString::null, + mMainWidget->userInfoFrame, "userInfoEdit"); + userInfoEdit->setTextFormat(PlainText); + + AIMMyselfContact* aimmc = dynamic_cast<AIMMyselfContact*>( c ); + if ( aimmc ) + userInfoEdit->setText( aimmc->userProfile() ); + else + userInfoEdit->setText( QString::null ); + + setButtonText(Ok, i18n("&Save Profile")); + showButton(User1, false); + l->addWidget(userInfoEdit); + } + else + { + userInfoEdit=0L; + mMainWidget->userInfoFrame->setFrameStyle(QFrame::NoFrame | QFrame::Plain); + QVBoxLayout *l = new QVBoxLayout(mMainWidget->userInfoFrame); + userInfoView = new KTextBrowser(mMainWidget->userInfoFrame, "userInfoView"); + userInfoView->setTextFormat(AutoText); + userInfoView->setNotifyClick(true); + QObject::connect( + userInfoView, SIGNAL(urlClick(const QString&)), + this, SLOT(slotUrlClicked(const QString&))); + QObject::connect( + userInfoView, SIGNAL(mailClick(const QString&, const QString&)), + this, SLOT(slotMailClicked(const QString&, const QString&))); + showButton(Cancel, false); + setButtonText(Ok, i18n("&Close")); + setEscapeButton(Ok); + l->addWidget(userInfoView); + + if(m_contact->isOnline()) + { + // Update the user view to indicate that we're requesting the user's profile + userInfoView->setText(i18n("Requesting User Profile, please wait...")); + } + QTimer::singleShot(0, this, SLOT(slotUpdateProfile())); + } +} + +AIMUserInfoDialog::~AIMUserInfoDialog() +{ + kdDebug(14200) << k_funcinfo << "Called." << endl; +} + +void AIMUserInfoDialog::slotUpdateClicked() +{ + kdDebug(14200) << k_funcinfo << "Called." << endl; + QString newNick = mMainWidget->txtNickName->text(); + QString currentNick = m_contact->property( Kopete::Global::Properties::self()->nickName() ).value().toString(); + if ( !newNick.isEmpty() && ( newNick != currentNick ) ) + { + //m_contact->rename(newNick); + //emit updateNickname(newNick); + setCaption(i18n("User Information on %1").arg(newNick)); + } + +} + +void AIMUserInfoDialog::slotSaveClicked() +{ + kdDebug(14200) << k_funcinfo << "Called." << endl; + + if (userInfoEdit) + { // editable mode, set profile + QString newNick = mMainWidget->txtNickName->text(); + QString currentNick = m_contact->property( Kopete::Global::Properties::self()->nickName() ).value().toString(); + if(!newNick.isEmpty() && ( newNick != currentNick ) ) + { + //m_contact->rename(newNick); + //emit updateNickname(newNick); + setCaption(i18n("User Information on %1").arg(newNick)); + } + + mAccount->setUserProfile(userInfoEdit->text()); + } + + emit closing(); +} + +void AIMUserInfoDialog::slotCloseClicked() +{ + kdDebug(14200) << k_funcinfo << "Called." << endl; + emit closing(); +} + +void AIMUserInfoDialog::slotUpdateProfile() +{ + kdDebug(14152) << k_funcinfo << "Got User Profile." << endl; + AIMProtocol* p = static_cast<AIMProtocol*>( mAccount->protocol() ); + QString awayMessage = m_contact->property( p->awayMessage ).value().toString(); + mMainWidget->txtAwayMessage->setText( awayMessage ); + + if ( awayMessage.isNull() ) + { + mMainWidget->txtAwayMessage->hide(); + mMainWidget->lblAwayMessage->hide(); + } + else + { + mMainWidget->txtAwayMessage->show(); + mMainWidget->lblAwayMessage->show(); + } + + QString onlineSince = m_contact->property("onlineSince").value().toString(); + //QString onlineSince = m_details.onlineSinceTime().toString(); + mMainWidget->txtOnlineSince->setText( onlineSince ); + + AIMContact* c = static_cast<AIMContact*>( m_contact ); + mMainWidget->txtIdleTime->setText(c->formattedIdleTime()); + mMainWidget->txtWarnLevel->setText(QString::number(c->warningLevel())); + + QString contactProfile = m_contact->property( p->clientProfile ).value().toString(); + if ( contactProfile.isNull() ) + { + contactProfile = + i18n("<html><body><I>No user information provided</I></body></html>"); + } + + if(userInfoEdit) + { + userInfoEdit->setText(contactProfile); + } + else if(userInfoView) + { + userInfoView->setText(contactProfile); + } + +} + +void AIMUserInfoDialog::slotUrlClicked(const QString &url) +{ + new KRun(KURL(url)); +} + +void AIMUserInfoDialog::slotMailClicked(const QString&, const QString &address) +{ + new KRun(KURL(address)); +} + +#include "aimuserinfo.moc" + +//kate: indent-mode csands; tab-width 4; space-indent off; replace-tabs off; diff --git a/kopete/protocols/oscar/aim/aimuserinfo.h b/kopete/protocols/oscar/aim/aimuserinfo.h new file mode 100644 index 00000000..f128610f --- /dev/null +++ b/kopete/protocols/oscar/aim/aimuserinfo.h @@ -0,0 +1,59 @@ +/* + oscaruserinfo.h - Oscar Protocol Plugin + + Copyright (c) 2002 by Tom Linsky <twl6@po.cwru.edu> + + Kopete (c) 2002 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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. * + * * + ************************************************************************* +*/ + +#ifndef AIMUSERINFO_H +#define AIMUSERINFO_H + +#include <kdialogbase.h> +#include "aiminfobase.h" + +namespace Kopete { class Contact; } +class KTextEdit; +class OscarAccount; +class AIMMyselfContact; +class AIMAccount; + +class AIMUserInfoDialog : public KDialogBase +{ + Q_OBJECT + public: + AIMUserInfoDialog(Kopete::Contact *c, AIMAccount *acc, bool modal, + QWidget *parent, const char* name); + ~AIMUserInfoDialog(); + + private: + AIMAccount *mAccount; + Kopete::Contact* m_contact; + AIMUserInfoWidget *mMainWidget; + KTextBrowser *userInfoView; + KTextEdit *userInfoEdit; + + private slots: + void slotSaveClicked(); + void slotCloseClicked(); + void slotUpdateClicked(); + void slotUpdateProfile(); + void slotUrlClicked(const QString&); + void slotMailClicked(const QString&, const QString&); + + signals: +// void updateNickname(const QString &); + void closing(); +}; + +#endif + diff --git a/kopete/protocols/oscar/aim/kopete_aim.desktop b/kopete/protocols/oscar/aim/kopete_aim.desktop new file mode 100644 index 00000000..0ab4fe69 --- /dev/null +++ b/kopete/protocols/oscar/aim/kopete_aim.desktop @@ -0,0 +1,77 @@ +[Desktop Entry] +Type=Service +X-Kopete-Version=1000900 +Icon=aim_protocol +ServiceTypes=Kopete/Protocol +X-KDE-Library=kopete_aim +X-Kopete-Messaging-Protocol=messaging/aim +X-KDE-PluginInfo-Author=Kopete Developers +X-KDE-PluginInfo-Email=kopete-devel@kde.org +X-KDE-PluginInfo-Name=kopete_aim +X-KDE-PluginInfo-Version=0.10.0 +X-KDE-PluginInfo-Website=http://kopete.kde.org +X-KDE-PluginInfo-Category=Protocols +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=false +Name=AIM +Name[bn]=এ-আই-এম +Name[hi]=एआरईएम +Name[ne]=एआईएम +Comment=Protocol to connect to AIM +Comment[ar]=البرتوكول سيتصل بـ AIM +Comment[be]=Пратакол AIM +Comment[bg]=Протокол за връзка с AIM +Comment[bn]=এ-আই-এমতে সংযোগ করতে প্রোটোকল +Comment[br]=Komenad kevreañ ouzh AIM +Comment[bs]=AIM protokol +Comment[ca]=Protocol per a connectar-se a AIM +Comment[cs]=Protokol k připojení k AIM +Comment[cy]=Protocol i gysylltu ag AIM +Comment[da]=Protokol til at forbinde til AIM +Comment[de]=Protokoll zur Verbindung mit dem AIM +Comment[el]=Πρωτόκολλο για σύνδεση στο AIM +Comment[es]=Protocolo para conectar a AIM +Comment[et]=Protokoll ühendumiseks AIM-iga +Comment[eu]=AIM-era konektatzeko protokoloa +Comment[fa]=قرارداد برای اتصال به AIM +Comment[fi]=Yhteyskäytäntö AIM-verkkoon kytkeytymiseen +Comment[fr]=Protocole pour se connecter sur AIM +Comment[ga]=Prótacal chun ceangal le AIM +Comment[gl]=Protocolo para se conectar ó AIM +Comment[he]=פרוטוקול התחברות ל- AIM +Comment[hi]=से जुड़ने का प्रोटोकॉल +Comment[hr]=Protokol za povezivanje na AIM +Comment[hu]=Protokoll az AIM használatához +Comment[is]=Samskiptamáti til að tengjast AIM +Comment[it]=Protocollo per connessione a AIM +Comment[ja]=AIM に接続するプロトコル +Comment[ka]=AIM დაკავშირების ოქმი +Comment[kk]=AIM-ге қосылу протоколы +Comment[km]=ពិធីការភ្ជាប់ទៅ AIM +Comment[lt]=Protokolas prisijungimui prie AIM +Comment[mk]=Протокол за поврзување на AIM +Comment[nb]=Protokoll for å koble til AIM +Comment[nds]=Protokoll för't Tokoppeln na AIM +Comment[ne]=एआईएम मा जडान गर्नुपर्ने प्रोटोकल +Comment[nl]=Protocol voor AOL Instant Messenger +Comment[nn]=Protokoll for å kopla til AIM +Comment[pl]=Protokół połączenia z serwerem AIM +Comment[pt]=Um protocolo para se ligar ao AIM +Comment[pt_BR]=Protocolo de conexão ao AIM +Comment[ro]=Protocol de conectare la AIM +Comment[ru]=Протокол для подключения к AIM +Comment[sk]=Protokol pre pripojenie k AIM +Comment[sl]=Protokol za povezavo na AIM +Comment[sr]=Протокол за повезивање на AIM +Comment[sr@Latn]=Protokol za povezivanje na AIM +Comment[sv]=Protokoll för att ansluta till AIM +Comment[ta]=IRC உடன் இணைக்க விதிமுறை +Comment[tg]=Қарордоди пайвастшавӣ ба AIM +Comment[tr]=AIM'e bağlantı iletişim kuralı +Comment[uk]=Протокол для з'єднання з AIM +Comment[uz]=AIM bilan aloqa oʻrnatish uchun protokol +Comment[uz@cyrillic]=AIM билан алоқа ўрнатиш учун протокол +Comment[zh_CN]=连接到 AIM 协议 +Comment[zh_HK]=用來連接至 AIM 的通訊協定 +Comment[zh_TW]=連線到 AIM 的協定 diff --git a/kopete/protocols/oscar/aim/ui/Makefile.am b/kopete/protocols/oscar/aim/ui/Makefile.am new file mode 100644 index 00000000..aa690449 --- /dev/null +++ b/kopete/protocols/oscar/aim/ui/Makefile.am @@ -0,0 +1,15 @@ +METASOURCES = AUTO +AM_CPPFLAGS = $(KOPETE_INCLUDES) \ + -I$(srcdir)/.. \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../liboscar \ + $(all_includes) + +noinst_LTLIBRARIES = libkopeteaimui.la + +libkopeteaimui_la_SOURCES = aimaddcontactui.ui aimeditaccountui.ui \ + aiminfobase.ui aimjoinchatbase.ui aimaddcontactpage.cpp aimeditaccountwidget.cpp + +libkopeteaimui_la_LIBADD = $(top_builddir)/kopete/libkopete/libkopete.la + + diff --git a/kopete/protocols/oscar/aim/ui/aimaddcontactpage.cpp b/kopete/protocols/oscar/aim/ui/aimaddcontactpage.cpp new file mode 100644 index 00000000..cf5fbae5 --- /dev/null +++ b/kopete/protocols/oscar/aim/ui/aimaddcontactpage.cpp @@ -0,0 +1,83 @@ +/*************************************************************************** + description + ------------------- + begin : + copyright : (C) 2002 by nbetcher + email : nbetcher@usinternet.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "aimaddcontactui.h" +#include "aimaddcontactpage.h" + +#include "kopeteaccount.h" + +#include <qlayout.h> +#include <qlineedit.h> +#include <klocale.h> +#include <kmessagebox.h> + +AIMAddContactPage::AIMAddContactPage(bool connected, QWidget *parent, + const char *name ) + : AddContactPage(parent,name) +{ + m_gui = 0; + (new QVBoxLayout(this))->setAutoAdd(true); + + if(connected) + { + m_gui = new aimAddContactUI(this); + canadd = true; + } + else + { + noaddMsg1 = new QLabel(i18n("You need to be connected to be able to add contacts."), this); + noaddMsg2 = new QLabel(i18n("Connect to the AIM network and try again."), this); + canadd = false; + } +} + + +AIMAddContactPage::~AIMAddContactPage() +{ +} + +bool AIMAddContactPage::validateData() +{ + if ( !canadd ) + return false; + + if ( !m_gui ) + return false; + + QString sn = m_gui->addSN->text(); + if ( sn.isEmpty() ) + { + KMessageBox::sorry ( this, + i18n("<qt>You must enter a valid screen name.</qt>"), + i18n("No Screen Name") ); + return false; + } + return true; +} + +bool AIMAddContactPage::apply(Kopete::Account *account, + Kopete::MetaContact *metaContact) +{ + if(validateData()) + { // If everything is ok + return account->addContact( m_gui->addSN->text(), metaContact, Kopete::Account::ChangeKABC ); + } + return false; +} +//kate: tab-width 4; indent-mode csands; + +#include "aimaddcontactpage.moc" diff --git a/kopete/protocols/oscar/aim/ui/aimaddcontactpage.h b/kopete/protocols/oscar/aim/ui/aimaddcontactpage.h new file mode 100644 index 00000000..979d0472 --- /dev/null +++ b/kopete/protocols/oscar/aim/ui/aimaddcontactpage.h @@ -0,0 +1,41 @@ + +#ifndef AIMADDCONTACTPAGE_H +#define AIMADDCONTACTPAGE_H + +#include <qwidget.h> +#include <qlabel.h> +#include "addcontactpage.h" + +class aimAddContactUI; +class AIMAccount; +namespace Kopete +{ +class Account; +class MetaContact; +} + +class AIMAddContactPage : public AddContactPage +{ +Q_OBJECT + +public: + AIMAddContactPage(bool connected, QWidget *parent=0, + const char *name=0); + ~AIMAddContactPage(); + + /** Validates the data entered */ + virtual bool validateData(); + /** Applies the addition to the account */ + virtual bool apply( Kopete::Account *account, Kopete::MetaContact *); + +protected: + /** The actual GUI */ + aimAddContactUI *m_gui; + QLabel *noaddMsg1; + QLabel *noaddMsg2; + bool canadd; +}; +#endif + +//kate: tab-width 4; indent-mode csands; + diff --git a/kopete/protocols/oscar/aim/ui/aimaddcontactui.ui b/kopete/protocols/oscar/aim/ui/aimaddcontactui.ui new file mode 100644 index 00000000..b3267eb0 --- /dev/null +++ b/kopete/protocols/oscar/aim/ui/aimaddcontactui.ui @@ -0,0 +1,64 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>aimAddContactUI</class> +<widget class="QWidget"> + <property name="name"> + <cstring>aimAddContactUI</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>455</width> + <height>131</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>GroupBox1</cstring> + </property> + <property name="title"> + <string>Contact Information</string> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLineEdit" row="0" column="1"> + <property name="name"> + <cstring>addSN</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>TextLabel1</cstring> + </property> + <property name="text"> + <string>AIM screen name:</string> + </property> + </widget> + </grid> + </widget> + </vbox> +</widget> +<tabstops> + <tabstop>addSN</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kopete/protocols/oscar/aim/ui/aimeditaccountui.ui b/kopete/protocols/oscar/aim/ui/aimeditaccountui.ui new file mode 100644 index 00000000..d8a7b9f3 --- /dev/null +++ b/kopete/protocols/oscar/aim/ui/aimeditaccountui.ui @@ -0,0 +1,540 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>aimEditAccountUI</class> +<widget class="QWidget"> + <property name="name"> + <cstring>aimEditAccountUI</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>560</width> + <height>583</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="caption"> + <string>Account Preferences - AIM</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>labelStatusMessage</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + </widget> + <widget class="QTabWidget" row="0" column="0"> + <property name="name"> + <cstring>tabWidget6</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>&Basic Setup</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox72</cstring> + </property> + <property name="title"> + <string>Account Information</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>lblAccountId</cstring> + </property> + <property name="text"> + <string>AIM &screen name:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>edtAccountId</cstring> + </property> + <property name="toolTip" stdset="0"> + <string>The screen name of your AIM account.</string> + </property> + <property name="whatsThis" stdset="0"> + <string>The screen name of your AIM account. This should be in the form of an alphanumeric string (spaces allowed, not case sensitive).</string> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>edtAccountId</cstring> + </property> + <property name="toolTip" stdset="0"> + <string>The screen name of your AIM account.</string> + </property> + <property name="whatsThis" stdset="0"> + <string>The screen name of your AIM account. This should be in the form of an alphanumeric string (spaces allowed, not case sensitive).</string> + </property> + </widget> + </hbox> + </widget> + <widget class="Kopete::UI::PasswordWidget" row="1" column="0"> + <property name="name"> + <cstring>mPasswordWidget</cstring> + </property> + </widget> + <widget class="QCheckBox" row="3" column="0"> + <property name="name"> + <cstring>mGlobalIdentity</cstring> + </property> + <property name="text"> + <string>Exclu&de from Global Identity</string> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0"> + <property name="name"> + <cstring>mAutoLogon</cstring> + </property> + <property name="text"> + <string>E&xclude from connect all</string> + </property> + <property name="whatsThis" stdset="0"> + <string>If you check that case, the account will not be connected when you press the "Connect All" button, or at startup even if you selected to automatically connect at startup</string> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox5</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Registration</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel6</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>To connect to the AOL Instant Messaging network, you will need to use a screen name from AIM, AOL, or .Mac.<br><br>If you do not currently have an AIM screen name, please click the button to create one.</string> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter</set> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonRegister</cstring> + </property> + <property name="text"> + <string>Re&gister New Account</string> + </property> + </widget> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer7</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>90</height> + </size> + </property> + </spacer> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Accou&nt Preferences</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>groupBox73</cstring> + </property> + <property name="title"> + <string>Connection Preferences</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>optionOverrideServer</cstring> + </property> + <property name="text"> + <string>&Override default server information</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout58</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>lblServer</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Ser&ver:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>edtServerAddress</cstring> + </property> + <property name="toolTip" stdset="0"> + <string>The IP address or hostmask of the AIM server you wish to connect to.</string> + </property> + <property name="whatsThis" stdset="0"> + <string>The IP address or hostmask of the AIM server you wish to connect to. Normally you will want the default (login.oscar.aol.com).</string> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>edtServerAddress</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>login.oscar.aol.com</string> + </property> + <property name="toolTip" stdset="0"> + <string>The IP address or hostmask of the AIM server you wish to connect to.</string> + </property> + <property name="whatsThis" stdset="0"> + <string>The IP address or hostmask of the AIM server you wish to connect to. Normally you will want the default (login.oscar.aol.com).</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>lblPort</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Po&rt:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>sbxServerPort</cstring> + </property> + <property name="toolTip" stdset="0"> + <string>The port on the AIM server that you would like to connect to.</string> + </property> + <property name="whatsThis" stdset="0"> + <string>The port on the AIM server that you would like to connect to. Normally this is 5190.</string> + </property> + </widget> + <widget class="QSpinBox"> + <property name="name"> + <cstring>sbxServerPort</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="maxValue"> + <number>65534</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="value"> + <number>5190</number> + </property> + <property name="toolTip" stdset="0"> + <string>The port on the AIM server that you would like to connect to.</string> + </property> + <property name="whatsThis" stdset="0"> + <string>The port on the AIM server that you would like to connect to. Normally this is 5190.</string> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <spacer row="2" column="0"> + <property name="name"> + <cstring>spacer21</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>200</height> + </size> + </property> + </spacer> + <widget class="QComboBox" row="1" column="1"> + <property name="name"> + <cstring>encodingCombo</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Default to the following &encoding for messages:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>encodingCombo</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Pri&vacy</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QButtonGroup" row="0" column="0"> + <property name="name"> + <cstring>buttonGroup1</cstring> + </property> + <property name="title"> + <string>Visibility settings</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton" row="2" column="0"> + <property name="name"> + <cstring>rbAllowPerimtList</cstring> + </property> + <property name="text"> + <string>Allow only from visible list</string> + </property> + </widget> + <widget class="QRadioButton" row="0" column="1"> + <property name="name"> + <cstring>rbBlockAll</cstring> + </property> + <property name="text"> + <string>Block all users</string> + </property> + </widget> + <widget class="QRadioButton" row="1" column="1"> + <property name="name"> + <cstring>rbBlockAIM</cstring> + </property> + <property name="text"> + <string>Block AIM users</string> + </property> + </widget> + <widget class="QRadioButton" row="2" column="1"> + <property name="name"> + <cstring>rbBlockDenyList</cstring> + </property> + <property name="text"> + <string>Block only from invisible list</string> + </property> + </widget> + <widget class="QRadioButton" row="0" column="0"> + <property name="name"> + <cstring>rbAllowAll</cstring> + </property> + <property name="text"> + <string>Allow all users</string> + </property> + </widget> + <widget class="QRadioButton" row="1" column="0"> + <property name="name"> + <cstring>rbAllowMyContacts</cstring> + </property> + <property name="text"> + <string>Allow only contact list's users</string> + </property> + </widget> + </grid> + </widget> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>31</width> + <height>225</height> + </size> + </property> + </spacer> + </grid> + </widget> + </widget> + </grid> +</widget> +<customwidgets> + <customwidget> + <class>Kopete::UI::PasswordWidget</class> + <header location="local">kopetepasswordwidget.h</header> + <sizehint> + <width>50</width> + <height>50</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>1</hordata> + <verdata>0</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + <signal>changed()</signal> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data> + </image> +</images> +<connections> + <connection> + <sender>optionOverrideServer</sender> + <signal>toggled(bool)</signal> + <receiver>lblServer</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>optionOverrideServer</sender> + <signal>toggled(bool)</signal> + <receiver>lblPort</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>optionOverrideServer</sender> + <signal>toggled(bool)</signal> + <receiver>edtServerAddress</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>optionOverrideServer</sender> + <signal>toggled(bool)</signal> + <receiver>sbxServerPort</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>tabWidget6</tabstop> + <tabstop>edtAccountId</tabstop> + <tabstop>mAutoLogon</tabstop> + <tabstop>buttonRegister</tabstop> + <tabstop>optionOverrideServer</tabstop> + <tabstop>edtServerAddress</tabstop> + <tabstop>sbxServerPort</tabstop> + <tabstop>encodingCombo</tabstop> + <tabstop>rbAllowAll</tabstop> + <tabstop>rbAllowMyContacts</tabstop> + <tabstop>rbAllowPerimtList</tabstop> + <tabstop>rbBlockAll</tabstop> + <tabstop>rbBlockAIM</tabstop> + <tabstop>rbBlockDenyList</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kopetepasswordwidget.h</includehint> +</includehints> +</UI> diff --git a/kopete/protocols/oscar/aim/ui/aimeditaccountwidget.cpp b/kopete/protocols/oscar/aim/ui/aimeditaccountwidget.cpp new file mode 100644 index 00000000..de720e17 --- /dev/null +++ b/kopete/protocols/oscar/aim/ui/aimeditaccountwidget.cpp @@ -0,0 +1,172 @@ +#include "aimeditaccountwidget.h" +#include "aimeditaccountui.h" + +#include <qlayout.h> +#include <qcheckbox.h> +#include <qpushbutton.h> +#include <qradiobutton.h> +#include <qlineedit.h> +#include <qspinbox.h> + +#include <kdebug.h> +#include <krun.h> +#include <kpassdlg.h> +#include <kconfig.h> + +#include "kopetepassword.h" +#include "kopetepasswordwidget.h" + +#include "aimprotocol.h" +#include "aimaccount.h" + +AIMEditAccountWidget::AIMEditAccountWidget( AIMProtocol *protocol, + Kopete::Account *account, QWidget *parent, const char *name ) + : QWidget( parent, name ), KopeteEditAccountWidget( account ) +{ + //kdDebug(14152) << k_funcinfo << "Called." << endl; + + mAccount = dynamic_cast<AIMAccount*>( account ); + mProtocol = protocol; + + // create the gui (generated from a .ui file) + ( new QVBoxLayout( this ) )->setAutoAdd( true ); + mGui = new aimEditAccountUI( this, "AIMEditAccountWidget::mGui" ); + + // Read in the settings from the account if it exists + if ( mAccount ) + { + mGui->mPasswordWidget->load( &mAccount->password() ); + mGui->edtAccountId->setText( account->accountId() ); + //Remove me after we can change Account IDs (Matt) + mGui->edtAccountId->setDisabled( true ); + mGui->mAutoLogon->setChecked( account->excludeConnect() ); + QString serverEntry = account->configGroup()->readEntry( "Server", "login.oscar.aol.com" ); + int portEntry = account->configGroup()->readNumEntry( "Port", 5190 ); + if ( serverEntry != "login.oscar.aol.com" || portEntry != 5190 ) + mGui->optionOverrideServer->setChecked( true ); + else + mGui->optionOverrideServer->setChecked( false ); + + mGui->edtServerAddress->setText( serverEntry ); + mGui->sbxServerPort->setValue( portEntry ); + + using namespace AIM::PrivacySettings; + + int privacySetting = mAccount->configGroup()->readNumEntry( "PrivacySetting", AllowAll ); + switch( privacySetting ) + { + case AllowAll: + mGui->rbAllowAll->setChecked( true ); + break; + case AllowMyContacts: + mGui->rbAllowMyContacts->setChecked( true ); + break; + case AllowPremitList: + mGui->rbAllowPerimtList->setChecked( true ); + break; + case BlockAll: + mGui->rbBlockAll->setChecked( true ); + break; + case BlockAIM: + mGui->rbBlockAIM->setChecked( true ); + break; + case BlockDenyList: + mGui->rbBlockDenyList->setChecked( true ); + break; + default: + mGui->rbAllowAll->setChecked( true ); + } + + // Global Identity + mGui->mGlobalIdentity->setChecked( account->configGroup()->readBoolEntry("ExcludeGlobalIdentity", false) ); + } + QObject::connect( mGui->buttonRegister, SIGNAL( clicked() ), this, SLOT( slotOpenRegister() ) ); + + /* Set tab order to password custom widget correctly */ + QWidget::setTabOrder( mGui->edtAccountId, mGui->mPasswordWidget->mRemembered ); + QWidget::setTabOrder( mGui->mPasswordWidget->mRemembered, mGui->mPasswordWidget->mPassword ); + QWidget::setTabOrder( mGui->mPasswordWidget->mPassword, mGui->mAutoLogon ); +} + +AIMEditAccountWidget::~AIMEditAccountWidget() +{} + +Kopete::Account *AIMEditAccountWidget::apply() +{ + kdDebug( 14152 ) << k_funcinfo << "Called." << endl; + + // If this is a new account, create it + if ( !mAccount ) + { + kdDebug( 14152 ) << k_funcinfo << "creating a new account" << endl; + QString newId = mGui->edtAccountId->text(); + mAccount = new AIMAccount( mProtocol, newId ); + } + + mGui->mPasswordWidget->save( &mAccount->password() ); + + mAccount->setExcludeConnect( mGui->mAutoLogon->isChecked() ); // save the autologon choice + if ( mGui->optionOverrideServer->isChecked() ) + { + static_cast<OscarAccount *>( mAccount )->setServerAddress( mGui->edtServerAddress->text() ); + static_cast<OscarAccount *>( mAccount )->setServerPort( mGui->sbxServerPort->value() ); + } + else + { + static_cast<OscarAccount *>( mAccount )->setServerAddress( "login.oscar.aol.com" ); + static_cast<OscarAccount *>( mAccount )->setServerPort( 5190 ); + } + + using namespace AIM::PrivacySettings; + int privacySetting = AllowAll; + + if ( mGui->rbAllowAll->isChecked() ) + privacySetting = AllowAll; + else if ( mGui->rbAllowMyContacts->isChecked() ) + privacySetting = AllowMyContacts; + else if ( mGui->rbAllowPerimtList->isChecked() ) + privacySetting = AllowPremitList; + else if ( mGui->rbBlockAll->isChecked() ) + privacySetting = BlockAll; + else if ( mGui->rbBlockAIM->isChecked() ) + privacySetting = BlockAIM; + else if ( mGui->rbBlockDenyList->isChecked() ) + privacySetting = BlockDenyList; + + mAccount->configGroup()->writeEntry( "PrivacySetting", privacySetting ); + mAccount->setPrivacySettings( privacySetting ); + + // Global Identity + mAccount->configGroup()->writeEntry( "ExcludeGlobalIdentity", mGui->mGlobalIdentity->isChecked() ); + return mAccount; +} + +bool AIMEditAccountWidget::validateData() +{ + //kdDebug(14152) << k_funcinfo << "Called." << endl; + + QString userName = mGui->edtAccountId->text(); + QString server = mGui->edtServerAddress->text(); + int port = mGui->sbxServerPort->value(); + + if ( userName.length() < 1 ) + return false; + + if ( port < 1 ) + return false; + + if ( server.length() < 1 ) + return false; + + // Seems good to me + //kdDebug(14152) << k_funcinfo << "Account data validated successfully." << endl; + return true; +} + +void AIMEditAccountWidget::slotOpenRegister() +{ + KRun::runURL( "http://my.screenname.aol.com/_cqr/login/login.psp?siteId=snshomepage&mcState=initialized&createSn=1", "text/html" ); +} + +#include "aimeditaccountwidget.moc" +// vim: set noet ts=4 sts=4 sw=4: diff --git a/kopete/protocols/oscar/aim/ui/aimeditaccountwidget.h b/kopete/protocols/oscar/aim/ui/aimeditaccountwidget.h new file mode 100644 index 00000000..ccb2b451 --- /dev/null +++ b/kopete/protocols/oscar/aim/ui/aimeditaccountwidget.h @@ -0,0 +1,58 @@ +/* + AIMeditaccountwidget.h - AIM Account Widget + + Copyright (c) 2003 by Chris TenHarmsel <tenharmsel@staticmethod.net> + + Kopete (c) 2003 by the Kopete developers <kopete-devel@kde.org> + + ************************************************************************* + * * + * 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. * + * * + ************************************************************************* +*/ + + +#ifndef AIMEDITACCOUNTWIDGET_H +#define AIMEDITACCOUNTWIDGET_H + +#include <qwidget.h> +#include "editaccountwidget.h" +/** + * @author Chris TenHarmsel <tenharmsel@staticmethod.net> + */ + +namespace Kopete +{ +class Account; +} + +class AIMAccount; +class AIMProtocol; +class aimEditAccountUI; + +class AIMEditAccountWidget : public QWidget, public KopeteEditAccountWidget +{ +Q_OBJECT + +public: + AIMEditAccountWidget(AIMProtocol *protocol, Kopete::Account *account, + QWidget *parent=0, const char *name=0); + virtual ~AIMEditAccountWidget(); + + virtual bool validateData(); + virtual Kopete::Account *apply(); + +private slots: + void slotOpenRegister(); + +protected: + AIMAccount *mAccount; + AIMProtocol *mProtocol; + aimEditAccountUI *mGui; +}; +#endif +//kate: tab-width 4; indent-mode csands; diff --git a/kopete/protocols/oscar/aim/ui/aiminfobase.ui b/kopete/protocols/oscar/aim/ui/aiminfobase.ui new file mode 100644 index 00000000..db22a574 --- /dev/null +++ b/kopete/protocols/oscar/aim/ui/aiminfobase.ui @@ -0,0 +1,246 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>AIMUserInfoWidget</class> +<widget class="QWidget"> + <property name="name"> + <cstring>AIMUserInfoWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>360</width> + <height>408</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>360</width> + <height>400</height> + </size> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout9</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>lblNickName</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Nickname:</string> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>txtNickName</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>lblScreenName</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Screen name:</string> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>txtScreenName</cstring> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout10</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>lblWarnLevel</cstring> + </property> + <property name="text"> + <string>Warning level:</string> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>txtWarnLevel</cstring> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>lblIdleTime</cstring> + </property> + <property name="text"> + <string>Idle minutes:</string> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>txtIdleTime</cstring> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout11</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>lblOnlineSince</cstring> + </property> + <property name="text"> + <string>Online since:</string> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>txtOnlineSince</cstring> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>lblAwayMessage</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Away message:</string> + </property> + <property name="alignment"> + <set>AlignTop</set> + </property> + </widget> + <widget class="KTextBrowser"> + <property name="name"> + <cstring>txtAwayMessage</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="textFormat"> + <enum>AutoText</enum> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Profile:</string> + </property> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>userInfoFrame</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>64</width> + <height>16</height> + </size> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + </widget> + </vbox> +</widget> +<tabstops> + <tabstop>txtNickName</tabstop> + <tabstop>txtScreenName</tabstop> + <tabstop>txtWarnLevel</tabstop> + <tabstop>txtIdleTime</tabstop> + <tabstop>txtOnlineSince</tabstop> + <tabstop>txtAwayMessage</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>ktextbrowser.h</includehint> +</includehints> +</UI> diff --git a/kopete/protocols/oscar/aim/ui/aimjoinchatbase.ui b/kopete/protocols/oscar/aim/ui/aimjoinchatbase.ui new file mode 100644 index 00000000..d1d93edf --- /dev/null +++ b/kopete/protocols/oscar/aim/ui/aimjoinchatbase.ui @@ -0,0 +1,124 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>AIMJoinChatBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>AIMJoinChatBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>343</width> + <height>99</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QLabel" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Please enter the name of the chat room you wish to join.</string> + </property> + </widget> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + <spacer row="2" column="0"> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Maximum</enum> + </property> + <property name="sizeHint"> + <size> + <width>60</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="2" column="1"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Room &name:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>roomName</cstring> + </property> + </widget> + <widget class="QLabel" row="3" column="1"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>E&xchange:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>exchange</cstring> + </property> + </widget> + <widget class="QLineEdit" row="2" column="2"> + <property name="name"> + <cstring>roomName</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QComboBox" row="3" column="2"> + <property name="name"> + <cstring>exchange</cstring> + </property> + </widget> + <spacer row="4" column="2"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> |