Logo Search packages:      
Sourcecode: kmess version File versions  Download package

contactbase.cpp

/***************************************************************************
                          contactbase.cpp  -  description
                             -------------------
    begin                : Thu Jan 16 2003
    copyright            : (C) 2003 by Mike K. Bennett
    email                : mkb137b@hotmail.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 "contactbase.h"

#include <kdebug.h>
#include <kstandarddirs.h>

#include <qimage.h>
#include <qfile.h>
#include <qstylesheet.h>

#include "../emoticon.h"
#include "../kmessdebug.h"
#include "../network/applications/applicationlist.h"

// The constructor
ContactBase::ContactBase(QString handle, QString friendlyName, uint capabilities)
 : capabilities_(capabilities)
 , friendlyName_(friendlyName)
 , handle_(handle)
 , applicationList_(0)
{
}



// The destructor
ContactBase::~ContactBase()
{
  delete applicationList_;
}



// Add a custom emoticon definition
void ContactBase::addEmoticonDefinition(const QString &emoticonCode, const QString &msnObjectDataHash )
{
#ifdef KMESSDEBUG_CONTACTBASE
  kdDebug() << "ContactBase::addEmoticonDefinition() - adding '" << emoticonCode << "' to pending replacements" << endl;
#endif

  // Escape the code so the HTML parser won't be fooled.
  QString shortcut = emoticonCode;
  shortcut.replace( "&", "&amp;" )
          .replace( "<", "&lt;" )
          .replace( ">", "&gt;" )
          .replace( "'", "&#39;" )
          .replace( '"', "&#34;" );

  // Add emoticon to pending list, until Msn object is received.
  pendingEmoticons_.insert(msnObjectDataHash, shortcut, true);

  // Escape the code to insert it safely into a regular expression
  QString escapedCode = QRegExp::escape( shortcut );

  // Update regexp pattern
  if( pendingRegExp_.isEmpty() )
  {
    pendingRegExp_ = QRegExp( escapedCode );
  }
  else
  {
    pendingRegExp_ = QRegExp( pendingRegExp_.pattern() + "|" + escapedCode );
  }

#ifdef KMESSTEST
  ASSERT( pendingRegExp_.isValid() );
#endif
}



// Add a custom emoticon file
void ContactBase::addEmoticonFile(const QString &msnObjectDataHash, const QString &filename)
{
  // Check whether the mapping is available.
  if( ! pendingEmoticons_.contains(msnObjectDataHash) )
  {
    kdWarning() << "Contact::addEmoticonFile: Received an custom emoticon, but no emoticon code found!" << endl;
    return;
  }

  // Get the emoticon code from pending list, remove it
  QString emoticonCode = pendingEmoticons_[msnObjectDataHash];    // no QString& because record gets removed.
  pendingEmoticons_.remove(msnObjectDataHash);

#ifdef KMESSDEBUG_CONTACTBASE
  kdDebug() << "ContactBase::addEmoticonFile() - linking '" << emoticonCode << "' to received file." << endl;
#endif

  // Check if filename exists, attempt to read it.
  if( ! QFile::exists(filename) )
  {
    kdWarning() << "Contact::addEmoticonFile: Could not read emoticon file: file not found!" << endl;
    return;
  }
  QImage emoticonData(filename);
  if( emoticonData.isNull() )
  {
    kdWarning() << "Contact::addEmoticonFile: Could not read emoticon file!" << endl;
    return;
  }

#ifdef KMESSDEBUG_CONTACT_GENERAL
  kdDebug() << "Contact::addEmoticonFile: Setting image for '" << emoticonCode << " to " << filename << endl;
#endif

  // Escape the code to insert it safely into a regular expression
  QString escapedCode = QRegExp::escape( emoticonCode );

  // Update regexp pattern
  if( emoticonRegExp_.isEmpty() )
  {
    emoticonRegExp_ = QRegExp( escapedCode );
  }
  else
  {
    emoticonRegExp_ = QRegExp( emoticonRegExp_.pattern() + "|" + escapedCode );
  }


  // Update pending regexp pattern.
  pendingRegExp_ = QRegExp(pendingRegExp_.pattern().remove( QRegExp("(^|\\|)" + escapedCode) ));

#ifdef KMESSTEST
  ASSERT( emoticonRegExp_.isValid() );
  ASSERT( pendingRegExp_.isValid() );
#endif


  // Get the image dimensions from the file
  int originalWidth = emoticonData.width();
  int originalHeight = emoticonData.height();

  // Resize the displayed image to match KMess' maximum emoticon size
  int width  = originalWidth; // QMIN( EMOTICONS_MAX_SIZE, originalWidth ); // Require only a max height
  int height = QMIN( EMOTICONS_MAX_SIZE, originalHeight );

  if( originalWidth > originalHeight )
  {
      height = ( width * originalHeight ) / originalWidth;
  }
  else
  {
      width = ( height * originalWidth ) / originalHeight;
  }

  // Add replacement.
  QString replacement = "<img src='" + filename
                      + "' alt='" + emoticonCode
                      + "' width='" + QString::number( width )
                      + "' height='" + QString::number( height )
                      + "' valign='middle'"
                      +  " class='customEmoticon' />";
  customEmoticons_.insert(emoticonCode, replacement);
}



// Register the contact as participant in the chat session
void ContactBase::addSwitchboardConnection( const MsnSwitchboardConnection *connection )
{
#ifdef KMESSDEBUG_CONTACTBASE
  kdDebug() << "ContactBase::addSwitchboardConnection() - adding connection to list." << endl;
#endif

  if( chatSessions_.contains(connection) )
  {
    kdWarning() << "ContactBase::addSwitchboardConnection: chat session is already added." << endl;
    return;
  }

  chatSessions_.append( connection );
}



// Initialize an application list for the contact.
ApplicationList * ContactBase::createApplicationList()
{
  if( applicationList_ != 0 )
  {
    kdWarning() << "ContactBase::createApplicationList: application list already created for contact '" << handle_ << "'." << endl;
  }
  else
  {
    applicationList_ = new ApplicationList( handle_ );

    connect( applicationList_, SIGNAL(        applicationsAborted(const QString &) ),
             this,             SLOT  ( slotApplicationListAborted()                ) );
  }

  return applicationList_;
}



// Return the application list of the contact
ApplicationList * ContactBase::getApplicationList() const
{
  return applicationList_;
}



// The capabilities of the client
uint ContactBase::getCapabilities() const
{
  return capabilities_;
}



// Return the default contact picture path
QString ContactBase::getContactDefaultPicturePath() const
{
  KStandardDirs *dirs   = KGlobal::dirs();
  return dirs->findResource( "data", "kmess/pics/unknown.png" );
}



// Return the custom emoticon code for an msn object
const QString & ContactBase::getEmoticonCode(const QString &msnObjectDataHash) const
{
  return pendingEmoticons_[msnObjectDataHash];
}



// Return the custom emoticon search pattern.
const QRegExp & ContactBase::getEmoticonPattern() const
{
  return emoticonRegExp_;
}



// Return the custom emoticon replacements.
const QMap<QString,QString>& ContactBase::getEmoticonReplacements() const
{
  return customEmoticons_;
}



// Return the contact's friendly name
QString ContactBase::getFriendlyName() const
{
  return friendlyName_;
}



// Return the contact's handle
QString ContactBase::getHandle() const
{
  return handle_;
}



// Return the search pattern for pending custom emoticons.
const QRegExp & ContactBase::getPendingEmoticonPattern() const
{
  return pendingRegExp_;
}



// Return the list of switchboard connections
const QPtrList<MsnSwitchboardConnection> ContactBase::getSwitchboardConnections() const
{
  return chatSessions_;
}



// Returns whether the contact has an application list initialized.
bool ContactBase::hasApplicationList() const
{
  return (applicationList_ != 0);
}



// Returns whether the contact's client supports the given MSNP2P version
bool ContactBase::hasP2PSupport( MsnClientCapabilities minimalVersion ) const
{
#ifdef KMESSTEST
  ASSERT( minimalVersion != 0 && (minimalVersion & 0x0fffffff) == 0 );  // don't pass some other capability.
#endif

  return capabilities_ >= (uint) minimalVersion;
}



// Return true if the contact is offline
bool ContactBase::isOffline() const
{
  return getStatus() == "FLN";
}



// Return true if the contact is online
bool ContactBase::isOnline() const
{
  return getStatus() != "FLN";
}



// Unregister the contact as participant, contact has left the chat.
void ContactBase::removeSwitchboardConnection( const MsnSwitchboardConnection *connection, bool userInitiated )
{
#ifdef KMESSDEBUG_CONTACTBASE
  kdDebug() << "ContactBase::removeSwitchboardConnection() - removing connection, userInitiated=" << userInitiated << endl;
#endif

  bool found = chatSessions_.remove( connection );
  if( ! found )
  {
    kdWarning() << "ContactBase::removeChatSession: chat session not found." << endl;
  }

  if( chatSessions_.isEmpty() )
  {
#ifdef KMESSDEBUG_CONTACTBASE
    kdDebug() << "ContactBase::removeSwitchboardConnection() - " << handle_ << " is no longer in any other chat conversation, cleaning up." << endl;
#endif

    // Inform the ApplicationList if we have one.
    // It's possible some sessions need to be terminated now.
    if( applicationList_ != 0 )
    {
      bool hasAbortingApps = applicationList_->contactLeftChat( userInitiated );

      // If there aren't any applications aborting, the object can be deleted now.
      // Also avoid deleting the object if there is still a direct connection.
      // It's possible a switchboard is replaced with another one (with WLM -> background chat -> normal chat).
      // Note the object could be destroyed from slotApplicationListAborted() too.
      if( ! hasAbortingApps && applicationList_ != 0 && ! applicationList_->hasAuthorizedDirectConnection() )
      {
#ifdef KMESSDEBUG_CONTACTBASE
        kdDebug() << "ContactBase::removeSwitchboardConnection() - no applications to abort, deleting ApplicationList object." << endl;
#endif

        delete applicationList_;
        applicationList_ = 0;
      }
    }

    // This will be used by CurrentAccount to clean up temporary InvitedContact objects.
    emit leftAllChats( this );
  }
}



// Set the client capabilities
void ContactBase::setCapabilities(uint capabilities)
{
  capabilities_ = capabilities;
}


// The application list completed aborting it's applications.
void ContactBase::slotApplicationListAborted()
{
  // Avoid killing an object if it was filled with new entries again
  if( ! applicationList_->isEmpty() || applicationList_->hasAuthorizedDirectConnection() )
  {
#ifdef KMESSDEBUG_CONTACTBASE
    kdDebug() << "ContactBase::slotApplicationListAborted() - requested abortion completed, but ApplicationList object has object references: not deleting object." << endl;
#endif
    return;
  }

#ifdef KMESSDEBUG_CONTACTBASE
  kdDebug() << "ContactBase::slotApplicationListAborted() - requested abortion completed, deleting ApplicationList object." << endl;
#endif


  // Use deleteLater() because this is called from the signal loop.
  applicationList_->deleteLater();
  applicationList_ = 0;
}



#include "contactbase.moc"

Generated by  Doxygen 1.6.0   Back to index