876 lines
27 KiB
C++
876 lines
27 KiB
C++
/***************************************************************************
|
|
contactframe.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 "contactframe.h"
|
|
|
|
#include "../contact/contact.h"
|
|
#include "../contact/contactextension.h"
|
|
#include "../contact/msnstatus.h"
|
|
#include "../dialogs/chathistorydialog.h"
|
|
#include "../dialogs/contactpropertiesdialog.h"
|
|
#include "../model/contactlist.h"
|
|
#include "../utils/kmessshared.h"
|
|
#include "../utils/richtextparser.h"
|
|
#include "../currentaccount.h"
|
|
#include "../emoticonmanager.h"
|
|
#include "../kmessdebug.h"
|
|
#include "chathistorymanager.h"
|
|
|
|
// HACK: Must go after 2.0-final
|
|
#include "../network/msnnotificationconnection.h"
|
|
#include "../kmess.h"
|
|
#include "../kmessapplication.h"
|
|
|
|
#include <QClipboard>
|
|
#include <QFileInfo>
|
|
#include <QMimeData>
|
|
#include <QMouseEvent>
|
|
|
|
#include <QApplication>
|
|
#include <QAction>
|
|
#include <KActionMenu>
|
|
#include <QIcon>
|
|
#include <KIconEffect>
|
|
#include <KIconLoader>
|
|
#include <KLocalizedString>
|
|
#include <QMenu>
|
|
#include <QUrl>
|
|
|
|
|
|
// Time in milliseconds before the glowing done for a typing user fades away
|
|
#define GLOWING_PICTURE_TIMEOUT 5000
|
|
|
|
|
|
|
|
// The constructor
|
|
ContactFrame::ContactFrame( QWidget *parent )
|
|
: QWidget(parent)
|
|
, Ui::ContactFrame()
|
|
, contact_(0)
|
|
, contactActionPopup_(0)
|
|
, contactPixmapLabelEnabled_(true)
|
|
, contactPropertiesDialog_(0)
|
|
, detailedContact_(0)
|
|
, handle_(QString())
|
|
, currentMode_(ModeNormal)
|
|
, infoLabelEnabled_(true)
|
|
, locked_(true)
|
|
{
|
|
// Setup the UI as first thing
|
|
setupUi( this );
|
|
layout()->setAlignment( Qt::AlignTop | Qt::AlignLeft );
|
|
|
|
// Just for show
|
|
const QPixmap pixmap( KMessShared::findResource( "data", "kmess/pics/unknown.png" ) );
|
|
contactPixmapLabel_->setPixmap( pixmap );
|
|
|
|
installEventFilter( this );
|
|
contactPixmapLabel_->installEventFilter( this );
|
|
friendlyNameLabel_ ->installEventFilter( this );
|
|
infoLabel_ ->installEventFilter( this );
|
|
|
|
// Set up and connect the typing timer
|
|
typingTimer_.setSingleShot( true );
|
|
connect( &typingTimer_, SIGNAL( timeout() ),
|
|
this, SLOT ( stopTyping() ) );
|
|
}
|
|
|
|
|
|
|
|
ContactFrame::~ContactFrame()
|
|
{
|
|
qDeleteAll( copyLinkActionsList_ );
|
|
}
|
|
|
|
|
|
|
|
// Activate the frame by giving it a contact
|
|
void ContactFrame::activate( ContactBase *contact )
|
|
{
|
|
// Disconnect the signals linked to previous contact( if there is anyone )
|
|
if ( contact_ != 0 )
|
|
{
|
|
disconnect( contact_, 0, this, 0 );
|
|
}
|
|
|
|
if( contact == 0 )
|
|
{
|
|
#ifdef KMESSDEBUG_CONTACTFRAME
|
|
kmDebug() << "Deactivating frame for contact:" << handle_;
|
|
#endif
|
|
|
|
contact_ = 0;
|
|
detailedContact_ = 0;
|
|
locked_ = true;
|
|
|
|
qDeleteAll( copyLinkActionsList_ );
|
|
copyLinkActionsList_.clear();
|
|
}
|
|
else
|
|
{
|
|
contact_ = contact;
|
|
handle_ = contact_->getHandle();
|
|
detailedContact_ = CurrentAccount::instance()->getContactList()->getContactByHandle( handle_ );
|
|
|
|
// ensure we know when the contact is now invalid.
|
|
connect( contact_, SIGNAL( destroyed(QObject*) ), this, SLOT( contactDestroyed(QObject*) ) );
|
|
|
|
if( detailedContact_ != 0 )
|
|
{
|
|
// Connect the contact, to update the frame on presence info changes
|
|
connect( detailedContact_, SIGNAL( changedList(Contact*) ),
|
|
this, SLOT ( contactChangedList() ) );
|
|
connect( detailedContact_, SIGNAL( changedFriendlyName() ),
|
|
this, SLOT ( updateStatusWidgets() ) );
|
|
connect( detailedContact_, SIGNAL( changedStatus() ),
|
|
this, SLOT ( updateStatusWidgets() ) );
|
|
connect( detailedContact_, SIGNAL( changedPicture() ),
|
|
this, SLOT ( updatePicture() ) );
|
|
connect( detailedContact_, SIGNAL( changedPersonalMessage(Contact*) ),
|
|
this, SLOT ( updateStatusWidgets() ) );
|
|
}
|
|
}
|
|
|
|
// Activate the right-click context menu
|
|
initContactPopup();
|
|
|
|
// And prepare the widgets
|
|
updatePicture();
|
|
updateStatusWidgets();
|
|
|
|
locked_ = false;
|
|
|
|
show();
|
|
}
|
|
|
|
|
|
|
|
// Allow this contact to see our MSN status
|
|
void ContactFrame::allowContact()
|
|
{
|
|
if( detailedContact_ == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
emit contactAllowed( handle_ );
|
|
|
|
locked_ = true;
|
|
}
|
|
|
|
|
|
|
|
// Foward the changed list signal from contact
|
|
void ContactFrame::contactChangedList()
|
|
{
|
|
locked_ = false;
|
|
updateStatusWidgets();
|
|
}
|
|
|
|
|
|
|
|
// The contact was destroyed
|
|
void ContactFrame::contactDestroyed( QObject *object )
|
|
{
|
|
// This method is relevant for invited contacts, the following happens:
|
|
// - an InvitedContact leaves the chat, SB notifies
|
|
// - ContactFrame::setDisplayMode() will be called, and updates the widgets.
|
|
// - CurrentAccount deletes the InvitedContact object.
|
|
// - somehow a code paths leads to this class (Chat::setSwitchboardConnection(0) is already patched).
|
|
// - crash.
|
|
|
|
// adam (17 Jan 2010) - the problem above occurs with InvitedContacts. we attach to the detailedContact_ destroyed() signal
|
|
// rather than the contact_ destroyed() signal. InvitedContact's have detailedContact_ == 0 so we never get notified
|
|
// of the InvitedContact deletion. fixed.
|
|
|
|
#ifdef KMESSDEBUG_CONTACTFRAME
|
|
if( contact_ && contact_ != object )
|
|
{
|
|
kmWarning() << "Received unexpected contact reference to" << object->metaObject()->className();
|
|
}
|
|
else
|
|
{
|
|
kmDebug() << "Resetting contact reference.";
|
|
}
|
|
#else
|
|
Q_UNUSED( object );
|
|
#endif
|
|
|
|
contact_ = 0;
|
|
detailedContact_ = 0;
|
|
}
|
|
|
|
|
|
|
|
// Copy some details of the contact to the clipboard.
|
|
// Only one method is used to copy all different details, and that's to avoid having three identical methods which only copy different
|
|
// text bits on the clipboard.
|
|
void ContactFrame::copyText()
|
|
{
|
|
// Get the signal sender to find out who called us
|
|
QAction *action = static_cast<QAction*>( const_cast<QObject*>( sender() ) );
|
|
if(KMESS_NULL(action)) return;
|
|
|
|
if( action == popupCopyFriendlyName_ )
|
|
{
|
|
QApplication::clipboard()->setText( contact_->getFriendlyName( STRING_CLEANED ) );
|
|
}
|
|
else if( action == popupCopyHandle_ )
|
|
{
|
|
QApplication::clipboard()->setText( handle_ );
|
|
}
|
|
else if( action == popupCopyPersonalMessage_ && detailedContact_ != 0 )
|
|
{
|
|
QApplication::clipboard()->setText( detailedContact_->getPersonalMessage( STRING_CLEANED ) );
|
|
}
|
|
else if( action == popupCopyMusic_ && detailedContact_ != 0 )
|
|
{
|
|
QApplication::clipboard()->setText( detailedContact_->getCurrentMediaString() );
|
|
}
|
|
else if( detailedContact_ != 0 )
|
|
{
|
|
// Copy the link from PM or Friendly Name
|
|
QApplication::clipboard()->setText( action->toolTip() );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// The personal status message received an event.
|
|
bool ContactFrame::eventFilter( QObject *obj, QEvent *event )
|
|
{
|
|
int eventType = event->type();
|
|
|
|
// Check if the obj is contactPixmapLabel
|
|
if( obj == contactPixmapLabel_ && detailedContact_ )
|
|
{
|
|
// Apply glow effect to image
|
|
if( eventType == QEvent::Enter )
|
|
{
|
|
QImage image( detailedContact_->getContactPicturePath() );
|
|
KIconEffect::toGamma( image, 0.8f );
|
|
contactPixmapLabel_->setPixmap( QPixmap::fromImage( image ) );
|
|
}
|
|
else if( eventType == QEvent::Leave && !typingTimer_.isActive() )
|
|
{
|
|
QImage image( detailedContact_->getContactPicturePath() );
|
|
|
|
// Only disable glow effect when the contact is not typing
|
|
contactPixmapLabel_->setPixmap( QPixmap::fromImage( image ) );
|
|
}
|
|
else if ( eventType == QEvent::DragEnter )
|
|
{
|
|
QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent*>( event );
|
|
const QMimeData *mimeData = dragEvent->mimeData();
|
|
|
|
// The mimeData object can contain one of the following objects: an image, HTML text, plain text, or a list of URLs.
|
|
// We need only the first URL object
|
|
if( mimeData->hasUrls() )
|
|
{
|
|
dragEvent->acceptProposedAction();
|
|
}
|
|
else
|
|
{
|
|
dragEvent->ignore();
|
|
}
|
|
}
|
|
else if ( eventType == QEvent::Drop )
|
|
{
|
|
QDropEvent* dropEvent = static_cast<QDropEvent*>( event );
|
|
const QMimeData *mimeData = dropEvent->mimeData();
|
|
|
|
// The mimeData object can contain one of the following objects: an image, HTML text, plain text, or a list of URLs.
|
|
// We need only the first URL object
|
|
if( ! mimeData->hasUrls() )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
QUrl mimeUrl = mimeData->urls().first();
|
|
QString filePath;
|
|
QPixmap pictureData;
|
|
|
|
if( mimeUrl.isEmpty() )
|
|
{
|
|
kmWarning() << "Dropped empty MIME URL";
|
|
return true;
|
|
}
|
|
|
|
filePath = mimeUrl.path();
|
|
|
|
if( ! pictureData.load( filePath ) )
|
|
{
|
|
kmWarning() << "The file dropped is not an image or doesn't exist";
|
|
return true;
|
|
}
|
|
|
|
detailedContact_->getExtension()->setContactAlternativePicturePath( filePath );
|
|
|
|
dropEvent->acceptProposedAction();
|
|
}
|
|
}
|
|
|
|
if( eventType != QEvent::MouseButtonRelease )
|
|
{
|
|
return false; // don't stop processing.
|
|
}
|
|
|
|
const QMouseEvent *mouseEvent = static_cast<QMouseEvent*>( event );
|
|
|
|
// Show the menu regardlessly of where the mouse button has been pressed
|
|
showContactPopup( mouseEvent->globalPosition().toPoint() );
|
|
|
|
return false; // don't stop processing.
|
|
}
|
|
|
|
|
|
|
|
// Return the handle of this frame's contact
|
|
const QString& ContactFrame::getHandle() const
|
|
{
|
|
return handle_;
|
|
}
|
|
|
|
|
|
|
|
// Initialize the contact popup
|
|
bool ContactFrame::initContactPopup()
|
|
{
|
|
// Check if there is a valid contact_ and if contact action menu was already initialized
|
|
if( contact_ == 0 || contactActionPopup_ != 0 )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Initialize context popup actions
|
|
popupStartPrivateChat_ = new QAction( QIcon::fromTheme( "user-group-new" ), i18n("&Start Private Chat"), this );
|
|
popupEmailContact_ = new QAction( QIcon::fromTheme( "mail-message-new" ), i18n("&Send Email"), this );
|
|
popupShowHistory_ = new QAction( QIcon::fromTheme( "chronometer" ), i18n("Chat &History"), this );
|
|
popupMsnProfile_ = new QAction( QIcon::fromTheme( "preferences-desktop-user" ), i18n("&View Profile"), this );
|
|
popupContactProperties_ = new QAction( QIcon::fromTheme( "user-properties" ), i18n("&Properties"), this );
|
|
|
|
popupAddContact_ = new QAction( QIcon::fromTheme( "list-add" ), i18n("&Add Contact"), this );
|
|
popupAllowContact_ = new QAction( QIcon::fromTheme( "dialog-ok-apply" ), i18n("A&llow Contact"), this );
|
|
popupRemoveContact_ = new QAction( QIcon::fromTheme( "list-remove-user" ), i18n("&Delete Contact"), this );
|
|
|
|
popupBlockContact_ = new QAction( QIcon::fromTheme( "dialog-cancel" ), i18n("&Block Contact"), this );
|
|
popupUnblockContact_ = new QAction( QIcon::fromTheme( "dialog-ok" ), i18n("&Unblock Contact"), this );
|
|
|
|
popupCopyFriendlyName_ = new QAction( i18n("&Friendly Name"), this );
|
|
popupCopyPersonalMessage_ = new QAction( i18n("&Personal Message"), this );
|
|
popupCopyHandle_ = new QAction( i18n("&Email Address"), this );
|
|
popupCopyMusic_ = new QAction( i18n("Song &Name"), this );
|
|
|
|
popupPropGeneral_ = new QAction( QIcon::fromTheme( "user-properties" ), i18n("&Information"), this );
|
|
popupPropImages_ = new QAction( QIcon::fromTheme( "draw-brush" ), i18n("Display Pictures"), this );
|
|
popupPropNotes_ = new QAction( QIcon::fromTheme( "document-edit" ), i18n("&Notes"), this );
|
|
popupPropEmoticons_ = new QAction( QIcon::fromTheme( "face-smile" ), i18n("&Emoticons"), this );
|
|
|
|
|
|
// Connect the actions
|
|
connect( popupStartPrivateChat_, SIGNAL(triggered( bool )), this, SLOT( slotStartPrivateChat() ) );
|
|
|
|
connect( popupEmailContact_, SIGNAL(triggered(bool)), this, SLOT( sendEmail() ) );
|
|
connect( popupShowHistory_, SIGNAL(triggered(bool)), this, SLOT( showChatHistory() ) );
|
|
connect( popupMsnProfile_, SIGNAL(triggered(bool)), this, SLOT( showProfile() ) );
|
|
|
|
connect( popupAddContact_, SIGNAL(triggered(bool)), this, SLOT( toggleContactAdded() ) );
|
|
connect( popupAllowContact_, SIGNAL(triggered(bool)), this, SLOT( allowContact() ) );
|
|
connect( popupRemoveContact_, SIGNAL(triggered(bool)), this, SLOT( toggleContactAdded() ) );
|
|
|
|
connect( popupBlockContact_, SIGNAL(triggered(bool)), this, SLOT( toggleContactBlocked() ) );
|
|
connect( popupUnblockContact_, SIGNAL(triggered(bool)), this, SLOT( toggleContactBlocked() ) );
|
|
|
|
connect( popupCopyFriendlyName_, SIGNAL(triggered(bool)), this, SLOT( copyText() ) );
|
|
connect( popupCopyPersonalMessage_, SIGNAL(triggered(bool)), this, SLOT( copyText() ) );
|
|
connect( popupCopyHandle_, SIGNAL(triggered(bool)), this, SLOT( copyText() ) );
|
|
connect( popupCopyMusic_, SIGNAL(triggered(bool)), this, SLOT( copyText() ) );
|
|
|
|
connect( popupPropGeneral_, SIGNAL(triggered(bool)), this, SLOT( showContactProperties() ) );
|
|
connect( popupPropImages_, SIGNAL(triggered(bool)), this, SLOT( showContactProperties() ) );
|
|
connect( popupPropNotes_, SIGNAL(triggered(bool)), this, SLOT( showContactProperties() ) );
|
|
connect( popupPropEmoticons_, SIGNAL(triggered(bool)), this, SLOT( showContactProperties() ) );
|
|
|
|
// Initialize sub popups
|
|
popupCopyMenu_ = new KActionMenu( i18n("&Copy"), this );
|
|
popupCopyMenu_ ->addAction( popupCopyFriendlyName_ );
|
|
popupCopyMenu_ ->addAction( popupCopyPersonalMessage_ );
|
|
popupCopyMenu_ ->addAction( popupCopyHandle_ );
|
|
popupCopyMenu_ ->addAction( popupCopyMusic_ );
|
|
popupCopyMenu_ ->addSeparator();
|
|
|
|
popupPropMenu_ = new KActionMenu( i18n("&Properties"), this );
|
|
popupPropMenu_ ->addAction( popupPropGeneral_ );
|
|
popupPropMenu_ ->addAction( popupPropImages_ );
|
|
popupPropMenu_ ->addAction( popupPropNotes_ );
|
|
popupPropMenu_ ->addAction( popupPropEmoticons_ );
|
|
|
|
// Initialize the popup popup
|
|
contactActionPopup_ = new QMenu( handle_, this );
|
|
|
|
// Attach the actions to the menu
|
|
// Order is as consistent as possible with the menu in KMessView
|
|
QAction *titleAction = contactActionPopup_->addAction( contact_->getHandle() );
|
|
titleAction->setEnabled( false );
|
|
contactActionPopup_->addAction( popupStartPrivateChat_ );
|
|
contactActionPopup_->addAction( popupEmailContact_ );
|
|
contactActionPopup_->addAction( popupShowHistory_ );
|
|
contactActionPopup_->addAction( popupMsnProfile_ );
|
|
contactActionPopup_->addAction( popupCopyMenu_ );
|
|
contactActionPopup_->addSeparator();
|
|
|
|
contactActionPopup_->addAction( popupAddContact_ );
|
|
contactActionPopup_->addAction( popupAllowContact_ );
|
|
|
|
contactActionPopup_->addAction( popupBlockContact_ );
|
|
contactActionPopup_->addAction( popupUnblockContact_ );
|
|
|
|
contactActionPopup_->addAction( popupRemoveContact_ );
|
|
|
|
contactActionPopup_->addSeparator();
|
|
|
|
contactActionPopup_->addAction( popupPropMenu_ );
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
// The user received a message from this contact
|
|
void ContactFrame::messageReceived()
|
|
{
|
|
// Stop the "user is typing" glow
|
|
typingTimer_.stop();
|
|
stopTyping();
|
|
}
|
|
|
|
|
|
|
|
// Email the contact
|
|
void ContactFrame::sendEmail()
|
|
{
|
|
if ( contact_ != 0 )
|
|
{
|
|
CurrentAccount::instance()->openMailAtCompose( handle_ );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Change the display mode of the frame when the contact leaves the chat or there are many active contacts
|
|
void ContactFrame::setDisplayMode( DisplayMode mode )
|
|
{
|
|
if( currentMode_ == mode )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Save the new current mode to avoid useless updates
|
|
currentMode_ = mode;
|
|
|
|
#ifdef KMESSDEBUG_CONTACTFRAME
|
|
kmDebug() << "Frame mode:" << mode;
|
|
#endif
|
|
|
|
// Change the displayed widgets
|
|
switch( mode )
|
|
{
|
|
case ModeSingle:
|
|
popupStartPrivateChat_->setVisible( false );
|
|
contactPixmapLabelEnabled_ = true;
|
|
infoLabelEnabled_ = true;
|
|
break;
|
|
|
|
case ModeNormal:
|
|
popupStartPrivateChat_->setVisible( true );
|
|
contactPixmapLabelEnabled_ = true;
|
|
infoLabelEnabled_ = true;
|
|
break;
|
|
|
|
case ModeSmall:
|
|
popupStartPrivateChat_->setVisible( true );
|
|
contactPixmapLabelEnabled_ = false;
|
|
infoLabelEnabled_ = true;
|
|
break;
|
|
|
|
case ModeTiny:
|
|
popupStartPrivateChat_->setVisible( true );
|
|
contactPixmapLabelEnabled_ = false;
|
|
infoLabelEnabled_ = false;
|
|
break;
|
|
}
|
|
|
|
// Update the status widgets
|
|
updateStatusWidgets();
|
|
}
|
|
|
|
|
|
|
|
// Enable or disable the frame
|
|
void ContactFrame::setEnabled( bool isEnabled )
|
|
{
|
|
contactPixmapLabel_->setEnabled( isEnabled );
|
|
}
|
|
|
|
|
|
|
|
// Show the contact's chat history
|
|
void ContactFrame::showChatHistory()
|
|
{
|
|
ChatHistoryDialog *dialog = new ChatHistoryDialog( this );
|
|
dialog->setInitialContact( CurrentAccount::instance()->getHandle(), handle_ );
|
|
dialog->show();
|
|
}
|
|
|
|
|
|
|
|
// Update and show the contact popup menu
|
|
void ContactFrame::showContactPopup( const QPoint &point )
|
|
{
|
|
bool isAdded = false;
|
|
bool isAllowed = false;
|
|
bool isBlocked = false;
|
|
bool hasPersonalMessage = false;
|
|
bool hasMediaMessage = false;
|
|
|
|
// If detailed contact information is available
|
|
if( detailedContact_ != 0 )
|
|
{
|
|
// We have the contact already in our list, but is possible to block/allow/unblock it
|
|
isAdded = detailedContact_->isFriend();
|
|
isAllowed = detailedContact_->isAllowed();
|
|
isBlocked = detailedContact_->isBlocked();
|
|
|
|
hasPersonalMessage = ! detailedContact_->getPersonalMessage().isEmpty();
|
|
hasMediaMessage = ! detailedContact_->getCurrentMediaString().isEmpty();
|
|
|
|
// Search for links
|
|
qDeleteAll( copyLinkActionsList_ );
|
|
copyLinkActionsList_.clear();
|
|
|
|
// Append friendly name and personal message so cycle only one time to search links
|
|
const QString nameAndPm( detailedContact_->getFriendlyName() + " " + detailedContact_->getPersonalMessage() );
|
|
QStringList links;
|
|
|
|
//Initialize index, link RegExp and found boolean for insert separator only at first found link
|
|
int pos = 0;
|
|
QRegExp linkRegExp( "(http://|https://|ftp://|sftp://|www\\..)\\S+" );
|
|
QString foundLink;
|
|
|
|
while( ( pos = linkRegExp.indexIn( nameAndPm, pos ) ) != -1 )
|
|
{
|
|
// Grep the found link and update the position for the next cycle
|
|
foundLink =linkRegExp.cap( 0 );
|
|
pos += linkRegExp.matchedLength();
|
|
|
|
// Skip duplicated links
|
|
if( links.contains( foundLink ) )
|
|
{
|
|
continue;
|
|
}
|
|
links.append( foundLink );
|
|
|
|
// Put the found link into QAction, replace & with && to avoid shortcut problem and use tooltip
|
|
// for future grep of link ( to avoid shortcut problem too )
|
|
popupCopyLink_ = new QAction( foundLink.replace( "&", "&&" ), this );
|
|
popupCopyLink_->setToolTip( foundLink );
|
|
connect( popupCopyLink_, SIGNAL( triggered( bool ) ), this, SLOT( copyText() ) );
|
|
|
|
// Append current QAction to the copy link list
|
|
copyLinkActionsList_.append( popupCopyLink_ );
|
|
|
|
// Add action to copy menu
|
|
popupCopyMenu_->addAction( popupCopyLink_ );
|
|
}
|
|
}
|
|
|
|
popupShowHistory_ ->setEnabled( ChatHistoryManager::contactsList().contains( handle_ ) );
|
|
|
|
popupContactProperties_ ->setVisible( detailedContact_ != 0 );
|
|
popupMsnProfile_ ->setVisible( detailedContact_ != 0 );
|
|
|
|
popupAllowContact_ ->setVisible( ! isAllowed && ! isAdded && detailedContact_ != 0 );
|
|
popupCopyPersonalMessage_->setVisible( hasPersonalMessage );
|
|
popupCopyMusic_ ->setVisible( hasMediaMessage );
|
|
|
|
popupAddContact_ ->setVisible( ! locked_ && ! isAdded );
|
|
popupRemoveContact_ ->setVisible( ! locked_ && isAdded );
|
|
|
|
popupBlockContact_ ->setVisible( ! locked_ && ! isBlocked && detailedContact_ != 0 );
|
|
popupUnblockContact_ ->setVisible( ! locked_ && isBlocked );
|
|
|
|
contactActionPopup_->popup( point );
|
|
}
|
|
|
|
|
|
|
|
// Show the contact properties window
|
|
void ContactFrame::showContactProperties()
|
|
{
|
|
// Check if there are details for contact
|
|
if( detailedContact_ != 0 && detailedContact_->getExtension() != 0 )
|
|
{
|
|
// Default is not to open notes tab
|
|
ContactPropertiesDialog::DefaultTab defaultTab = ContactPropertiesDialog::Information;
|
|
|
|
// If we've been called via a specialized properties action,
|
|
// open the corresponding tab
|
|
if( sender() == popupPropEmoticons_ )
|
|
{
|
|
defaultTab = ContactPropertiesDialog::Emoticons;
|
|
}
|
|
else if( sender() == popupPropImages_ )
|
|
{
|
|
defaultTab = ContactPropertiesDialog::Images;
|
|
}
|
|
else if( sender() == popupPropNotes_ )
|
|
{
|
|
defaultTab = ContactPropertiesDialog::Notes;
|
|
}
|
|
|
|
// the qlistwidget in the dialog doesn't seem to handle being reopened from
|
|
// a saved instance (unknown why). it causes display issues (i.e., displays the same
|
|
// groups multiple times or doesn't display them at all). This resolves the problem.
|
|
ContactPropertiesDialog *dialog = new ContactPropertiesDialog(this);
|
|
|
|
KMess *kmess = static_cast<KMessApplication *>(QApplication::instance())->getContactListWindow();
|
|
|
|
// HACK: MUST GO AFTER 2.0-final!!
|
|
connect( dialog, SIGNAL(addContactToGroup(QString, QString)),
|
|
kmess->getNsConnection(), SLOT( addContactToGroup(QString, QString) ) );
|
|
|
|
connect( dialog, SIGNAL(removeContactFromGroup(QString, QString)),
|
|
kmess->getNsConnection(), SLOT( removeContactFromGroup(QString, QString) ) );
|
|
|
|
dialog->launch( detailedContact_, defaultTab );
|
|
|
|
delete dialog;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Show the contact's profile
|
|
void ContactFrame::showProfile()
|
|
{
|
|
if( contact_ == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Create a URL to the msn profile page, localized with our system's locale.
|
|
const QUrl url( "https://nina.chat/contacts/" );
|
|
|
|
// Launch the browser for the given URL
|
|
KMessShared::openBrowser( url );
|
|
}
|
|
|
|
|
|
|
|
// Request to start private chat
|
|
void ContactFrame::slotStartPrivateChat()
|
|
{
|
|
emit startPrivateChat( handle_ );
|
|
}
|
|
|
|
|
|
|
|
// Receive notice that the contact is typing
|
|
void ContactFrame::startTyping()
|
|
{
|
|
contactPixmapLabel_->setPixmap( contactTypingPicture_ );
|
|
|
|
// Make the contact picture glow
|
|
// Start the timer to disable the label
|
|
typingTimer_.start( GLOWING_PICTURE_TIMEOUT );
|
|
}
|
|
|
|
|
|
|
|
// Disable the typing label when the timer has timed out
|
|
void ContactFrame::stopTyping()
|
|
{
|
|
contactPixmapLabel_->setPixmap( contactPicture_ );
|
|
}
|
|
|
|
|
|
|
|
// Add or remove the contact from the contact list
|
|
void ContactFrame::toggleContactAdded()
|
|
{
|
|
if( detailedContact_ == 0 )
|
|
{
|
|
emit contactAdded( handle_, true );
|
|
}
|
|
else
|
|
{
|
|
emit contactAdded( handle_, ! detailedContact_->isFriend() );
|
|
}
|
|
|
|
// Disallow adding unknown contacts more than once
|
|
locked_ = true;
|
|
}
|
|
|
|
|
|
|
|
// Change the contact's blocked/unblocked status
|
|
void ContactFrame::toggleContactBlocked()
|
|
{
|
|
if( detailedContact_ == 0 )
|
|
{
|
|
emit contactBlocked( handle_, true );
|
|
}
|
|
else
|
|
{
|
|
emit contactBlocked( handle_, ! detailedContact_->isBlocked() );
|
|
}
|
|
|
|
// Disallow adding unknown contacts more than once
|
|
locked_ = true;
|
|
}
|
|
|
|
|
|
|
|
// Update the contact picture
|
|
void ContactFrame::updatePicture()
|
|
{
|
|
if ( contact_ == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// See if the contact picture is not updated. Avoids GUI flashing on older boxes
|
|
const QString contactPicturePath( contact_->getContactPicturePath() );
|
|
const QFileInfo contactPictureInfo( contactPicturePath );
|
|
const QDateTime contactPictureDate( contactPictureInfo.lastModified() );
|
|
|
|
if( contactPicturePath == contactPicturePath_
|
|
&& contactPictureDate == contactPictureDate_ )
|
|
{
|
|
#ifdef KMESSDEBUG_CONTACTFRAME
|
|
kmDebug() << "Picture was already loaded.";
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
#ifdef KMESSDEBUG_CONTACTFRAME
|
|
kmDebug() << "New contact picture:" << contactPicturePath;
|
|
#endif
|
|
|
|
QImage contactImage( contactPicturePath );
|
|
bool loaded = ! contactImage.isNull();
|
|
if( loaded )
|
|
{
|
|
// Loaded
|
|
contactPicturePath_ = contactPicturePath;
|
|
contactPictureDate_ = contactPictureDate;
|
|
}
|
|
else
|
|
{
|
|
// Not loaded (PNG error?). load default if custom image could not be loaded
|
|
loaded = contactImage.load( contact_->getContactDefaultPicturePath() );
|
|
|
|
if( ! loaded )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Setup the normal and typing pixmaps
|
|
contactPicture_ = QPixmap::fromImage( contactImage );
|
|
KIconEffect::toGamma( contactImage, 0.8f );
|
|
contactTypingPicture_ = QPixmap::fromImage( contactImage );
|
|
|
|
// Display the image
|
|
contactPixmapLabel_->setPixmap( contactPicture_ );
|
|
}
|
|
|
|
|
|
|
|
// Update the status widgets
|
|
void ContactFrame::updateStatusWidgets()
|
|
{
|
|
if( contact_ == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
QString label, statusIdentifier;
|
|
const Status status( contact_->getStatus() );
|
|
Flags flags = FlagNone;
|
|
|
|
if( detailedContact_ != 0 && detailedContact_->isBlocked())
|
|
{
|
|
// Show blocked regardless of status
|
|
statusIdentifier = i18n( "Blocked" );
|
|
flags = FlagBlocked;
|
|
}
|
|
else
|
|
{
|
|
statusIdentifier = MsnStatus::getName( status );
|
|
}
|
|
|
|
friendlyNameLabel_->setText( contact_->getFriendlyName( STRING_CHAT_SETTING_ESCAPED ) );
|
|
friendlyNameLabel_->setToolTip( contact_->getFriendlyName() );
|
|
statusPixmapLabel_->setToolTip( i18nc( "Tooltip for a contact's status icon, "
|
|
"arg %1 is the Live Messenger status, like 'Online'",
|
|
"The contact is %1",
|
|
statusIdentifier ) );
|
|
statusPixmapLabel_->setPixmap( MsnStatus::getIcon( status, flags ) );
|
|
|
|
// Update the informative label
|
|
if( detailedContact_ && infoLabelEnabled_ )
|
|
{
|
|
const QString& mediaString = detailedContact_->getCurrentMediaString();
|
|
const QString& messageString = detailedContact_->getPersonalMessage( STRING_CHAT_SETTING_ESCAPED );
|
|
if( ! mediaString.isEmpty() )
|
|
{
|
|
// Determine the icon for the various media types, if none no icon will be shown
|
|
QString mediaEmoticon;
|
|
const QString& mediaType = detailedContact_->getCurrentMediaType();
|
|
if( mediaType == "Music" )
|
|
{
|
|
mediaEmoticon = EmoticonManager::instance()->getReplacement( "(8)", true );
|
|
}
|
|
else if( mediaType == "Gaming" )
|
|
{
|
|
mediaEmoticon = EmoticonManager::instance()->getReplacement( "(xx)", true );
|
|
}
|
|
|
|
infoLabel_->setVisible( true );
|
|
infoLabel_->setText( mediaEmoticon + mediaString.toHtmlEscaped() );
|
|
infoLabel_->setToolTip( mediaString );
|
|
}
|
|
else if( ! messageString.isEmpty() )
|
|
{
|
|
infoLabel_->setVisible( true );
|
|
infoLabel_->setText( messageString );
|
|
infoLabel_->setToolTip( detailedContact_->getPersonalMessage( STRING_CLEANED ) );
|
|
}
|
|
else
|
|
{
|
|
infoLabel_->setVisible( false );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
infoLabel_->setVisible( false );
|
|
}
|
|
|
|
contactPixmapLabel_->setVisible( contactPixmapLabelEnabled_ );
|
|
}
|