00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "chatview.h"
00020
00021 #include "chatmessagepart.h"
00022 #include "chattexteditpart.h"
00023 #include "kopetechatwindow.h"
00024 #include "kopetechatsession.h"
00025 #include "kopetemetacontact.h"
00026 #include "kopetepluginmanager.h"
00027 #include "kopeteprotocol.h"
00028 #include "kopeteaccount.h"
00029 #include "kopeteglobal.h"
00030 #include "kopetecontactlist.h"
00031 #include "kopeteviewmanager.h"
00032 #include "kopetebehaviorsettings.h"
00033
00034 #include <kconfig.h>
00035 #include <ktabwidget.h>
00036 #include <kdebug.h>
00037 #include <klocale.h>
00038 #include <kmessagebox.h>
00039 #include <kmenu.h>
00040 #include <kstringhandler.h>
00041 #include <kwindowsystem.h>
00042 #include <kglobalsettings.h>
00043 #include <kgenericfactory.h>
00044 #include <khtmlview.h>
00045
00046
00047
00048 #include <QTimer>
00049 #include <QSplitter>
00050
00051
00052 #include <QPixmap>
00053 #include <QDropEvent>
00054 #include <QDragEnterEvent>
00055 #include <Q3UriDrag>
00056 #include <QObject>
00057
00058 typedef KGenericFactory<ChatWindowPlugin> ChatWindowPluginFactory;
00059 K_EXPORT_COMPONENT_FACTORY( kopete_chatwindow, ChatWindowPluginFactory( "kopete_chatwindow" ) )
00060
00061 ChatWindowPlugin::ChatWindowPlugin(QObject *parent, const QStringList &) :
00062 Kopete::ViewPlugin( ChatWindowPluginFactory::componentData(), parent )
00063 {}
00064
00065 KopeteView* ChatWindowPlugin::createView( Kopete::ChatSession *manager )
00066 {
00067 return (KopeteView*)new ChatView(manager,this);
00068 }
00069
00070 class KopeteChatViewPrivate
00071 {
00072 public:
00073 QString captionText;
00074 QString statusText;
00075 bool isActive;
00076 bool sendInProgress;
00077 bool visibleMembers;
00078 QSplitter * splitter;
00079 };
00080
00081 ChatView::ChatView( Kopete::ChatSession *mgr, ChatWindowPlugin *parent )
00082 : KVBox( 0l ), KopeteView( mgr, parent )
00083 , d(new KopeteChatViewPrivate)
00084 {
00085 int i;
00086
00087 d->isActive = false;
00088 d->visibleMembers = false;
00089 d->sendInProgress = false;
00090
00091 KVBox *vbox=this;
00092
00093 m_mainWindow = 0L;
00094 m_tabState = Normal;
00095
00096
00097
00098 hide();
00099
00100 d->splitter = new QSplitter( Qt::Vertical, vbox );
00101
00102
00103 m_messagePart = new ChatMessagePart( mgr , this );
00104
00105
00106 m_editPart = new ChatTextEditPart( mgr, vbox );
00107
00108 d->splitter->addWidget(m_messagePart->view());
00109 d->splitter->addWidget(m_editPart->widget());
00110 d->splitter->setChildrenCollapsible( false );
00111 QList<int> sizes;
00112 sizes << 240 << 40;
00113 d->splitter->setSizes( sizes );
00114
00115
00116 connect( editPart(), SIGNAL( toolbarToggled(bool)), this, SLOT(slotToggleRtfToolbar(bool)) );
00117
00118 connect( editPart(), SIGNAL( messageSent( Kopete::Message & ) ),
00119 this, SIGNAL( messageSent( Kopete::Message & ) ) );
00120 connect( editPart(), SIGNAL( canSendChanged( bool ) ),
00121 this, SIGNAL( canSendChanged(bool) ) );
00122 connect( editPart(), SIGNAL( typing(bool) ),
00123 mgr, SLOT( typing(bool) ) );
00124
00125
00126
00127
00128
00129
00130 setAcceptDrops(true);
00131
00132
00133
00134 connect( mgr, SIGNAL( displayNameChanged() ),
00135 this, SLOT( slotChatDisplayNameChanged() ) );
00136 connect( mgr, SIGNAL( contactAdded(const Kopete::Contact*, bool) ),
00137 this, SLOT( slotContactAdded(const Kopete::Contact*, bool) ) );
00138 connect( mgr, SIGNAL( contactRemoved(const Kopete::Contact*, const QString&, Qt::TextFormat, bool) ),
00139 this, SLOT( slotContactRemoved(const Kopete::Contact*, const QString&, Qt::TextFormat, bool) ) );
00140 connect( mgr, SIGNAL( onlineStatusChanged( Kopete::Contact *, const Kopete::OnlineStatus & , const Kopete::OnlineStatus &) ),
00141 this, SLOT( slotContactStatusChanged( Kopete::Contact *, const Kopete::OnlineStatus &, const Kopete::OnlineStatus & ) ) );
00142 connect( mgr, SIGNAL( remoteTyping( const Kopete::Contact *, bool) ),
00143 this, SLOT( remoteTyping(const Kopete::Contact *, bool) ) );
00144 connect( mgr, SIGNAL( eventNotification( const QString& ) ),
00145 this, SLOT( setStatusText( const QString& ) ) );
00146
00147
00148 connect( this, SIGNAL( closing( KopeteView * ) ),
00149 KopeteViewManager::viewManager(), SLOT( slotViewDestroyed( KopeteView * ) ) );
00150 connect( this, SIGNAL( activated( KopeteView * ) ),
00151 KopeteViewManager::viewManager(), SLOT( slotViewActivated( KopeteView * ) ) );
00152 connect( this, SIGNAL( messageSent(Kopete::Message &) ),
00153 mgr, SLOT( sendMessage(Kopete::Message &) ) );
00154 connect( mgr, SIGNAL( messageSuccess() ),
00155 this, SLOT( messageSentSuccessfully() ));
00156
00157
00158 slotContactAdded( mgr->myself(), true );
00159 for ( i = 0; i != mgr->members().size(); i++ )
00160 slotContactAdded( mgr->members()[i], true );
00161
00162 setFocusProxy( editPart()->widget() );
00163 editPart()->widget()->setFocus();
00164
00165 setCaption( m_manager->displayName(), false );
00166
00167
00168 readOptions();
00169 }
00170
00171 ChatView::~ChatView()
00172 {
00173 emit( closing( static_cast<KopeteView*>(this) ) );
00174
00175 saveOptions();
00176
00177 delete d;
00178 }
00179
00180 KTextEdit *ChatView::editWidget()
00181 {
00182 return editPart()->textEdit();
00183 }
00184
00185 QWidget *ChatView::mainWidget()
00186 {
00187 return this;
00188 }
00189
00190 bool ChatView::canSend()
00191 {
00192 return editPart()->canSend();
00193 }
00194
00195 Kopete::Message ChatView::currentMessage()
00196 {
00197 return editPart()->contents();
00198 }
00199
00200 void ChatView::setCurrentMessage( const Kopete::Message &message )
00201 {
00202 editPart()->setContents( message );
00203 }
00204
00205 void ChatView::cut()
00206 {
00207 editPart()->textEdit()->cut();
00208 }
00209
00210 void ChatView::copy()
00211 {
00212 if ( messagePart()->hasSelection() )
00213 messagePart()->copy();
00214 else
00215 editPart()->textEdit()->copy();
00216 }
00217
00218 void ChatView::paste()
00219 {
00220 editPart()->textEdit()->paste();
00221 }
00222
00223 void ChatView::nickComplete()
00224 {
00225 return editPart()->complete();
00226 }
00227
00228 void ChatView::addText( const QString &text )
00229 {
00230 editPart()->addText( text );
00231 }
00232
00233 void ChatView::clear()
00234 {
00235 messagePart()->clear();
00236 }
00237
00238 void ChatView::setBgColor( const QColor &newColor )
00239 {
00240 Q_UNUSED(newColor);
00241
00242 }
00243
00244 void ChatView::setFont()
00245 {
00246 editPart()->setFont();
00247 }
00248
00249 QFont ChatView::font()
00250 {
00251 return editPart()->font();
00252 }
00253
00254 void ChatView::setFont( const QFont &font )
00255 {
00256 editPart()->setFont( font );
00257 }
00258
00259 void ChatView::setFgColor( const QColor &newColor )
00260 {
00261 if ( newColor.isValid() )
00262 {
00263 editPart()->setTextColor( newColor );
00264 }
00265 else
00266 {
00267 editPart()->setTextColor();
00268 }
00269 }
00270
00271 void ChatView::raise( bool activate )
00272 {
00273
00274
00275
00276
00277
00278 if ( !m_mainWindow || !m_mainWindow->isActiveWindow() || activate )
00279 makeVisible();
00280 #ifdef Q_WS_X11
00281 if ( !KWindowSystem::windowInfo( m_mainWindow->winId(), NET::WMDesktop ).onAllDesktops() )
00282 if( Kopete::BehaviorSettings::self()->trayflashNotifySetCurrentDesktopToChatView() && activate )
00283 KWindowSystem::setCurrentDesktop( KWindowSystem::windowInfo( m_mainWindow->winId(), NET::WMDesktop ).desktop() );
00284 else
00285 KWindowSystem::setOnDesktop( m_mainWindow->winId(), KWindowSystem::currentDesktop() );
00286 #endif
00287 if(m_mainWindow->isMinimized())
00288 {
00289 KWindowSystem::unminimizeWindow( m_mainWindow->winId());
00290 }
00291
00292
00293 m_mainWindow->raise();
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 if ( activate )
00305 KWindowSystem::activateWindow( m_mainWindow->winId() );
00306
00307 }
00308
00309 void ChatView::makeVisible()
00310 {
00311 if ( !m_mainWindow )
00312 {
00313 m_mainWindow = KopeteChatWindow::window( m_manager );
00314 m_mainWindow->setObjectName( QLatin1String("KopeteChatWindow") );
00315
00316
00317 emit windowCreated();
00318 }
00319
00320 if ( !m_mainWindow->isVisible() )
00321 {
00322 m_mainWindow->show();
00323
00324 m_messagePart->keepScrolledDown();
00325 }
00326
00327
00328
00329 m_mainWindow->setActiveView( this );
00330 }
00331
00332 bool ChatView::isVisible()
00333 {
00334 return ( m_mainWindow && m_mainWindow->isVisible() );
00335 }
00336
00337 bool ChatView::sendInProgress()
00338 {
00339 return d->sendInProgress;
00340 }
00341
00342 bool ChatView::closeView( bool force )
00343 {
00344 int response = KMessageBox::Continue;
00345
00346 if ( !force )
00347 {
00348 if ( m_manager->members().count() > 1 )
00349 {
00350 QString shortCaption = d->captionText;
00351 shortCaption = KStringHandler::rsqueeze( shortCaption );
00352
00353 response = KMessageBox::warningContinueCancel( this, i18n("<qt>You are about to leave the groupchat session <b>%1</b>.<br />"
00354 "You will not receive future messages from this conversation.</qt>", shortCaption ), i18n( "Closing Group Chat" ),
00355 KGuiItem( i18nc( "@action:button", "Close Chat" ) ), KStandardGuiItem::cancel(), QLatin1String( "AskCloseGroupChat" ) );
00356 }
00357
00358 if ( !unreadMessageFrom.isNull() && ( response == KMessageBox::Continue ) )
00359 {
00360 response = KMessageBox::warningContinueCancel( this, i18n("<qt>You have received a message from <b>%1</b> in the last "
00361 "second. Are you sure you want to close this chat?</qt>", unreadMessageFrom ), i18n( "Unread Message" ),
00362 KGuiItem( i18nc( "@action:button", "Close Chat" ) ), KStandardGuiItem::cancel(), QLatin1String("AskCloseChatRecentMessage" ) );
00363 }
00364
00365 if ( d->sendInProgress && ( response == KMessageBox::Continue ) )
00366 {
00367 response = KMessageBox::warningContinueCancel( this, i18n( "You have a message send in progress, which will be "
00368 "aborted if this chat is closed. Are you sure you want to close this chat?" ), i18n( "Message in Transit" ),
00369 KGuiItem( i18nc( "@action:button", "Close Chat" ) ), KStandardGuiItem::cancel(), QLatin1String( "AskCloseChatMessageInProgress" ) );
00370 }
00371 }
00372
00373 if( response == KMessageBox::Continue )
00374 {
00375
00376
00377 if( m_mainWindow )
00378 m_mainWindow->detachChatView( this );
00379 deleteLater();
00380
00381 return true;
00382 }
00383
00384 return false;
00385 }
00386
00387 void ChatView::updateChatState( KopeteTabState newState )
00388 {
00389 if ( newState == Undefined )
00390 newState = m_tabState;
00391 else if ( newState != Typing && ( newState != Changed || ( m_tabState != Message && m_tabState != Highlighted ) )
00392 && ( newState != Message || m_tabState != Highlighted ) )
00393 {
00394
00395 m_tabState = newState;
00396 }
00397
00398 newState = m_remoteTypingMap.isEmpty() ? m_tabState : Typing ;
00399
00400 emit updateChatState( this, newState );
00401
00402 if( newState != Typing )
00403 {
00404 setStatusText( i18np( "One other person in the chat",
00405 "%1 other people in the chat", m_manager->members().count() ) );
00406 }
00407 }
00408
00409 void ChatView::setMainWindow( KopeteChatWindow* parent )
00410 {
00411 m_mainWindow = parent;
00412 }
00413
00414 void ChatView::remoteTyping( const Kopete::Contact *contact, bool isTyping )
00415 {
00416 TypingMap::iterator it = m_remoteTypingMap.find(contact);
00417 if (it != m_remoteTypingMap.end())
00418 {
00419 if (it.value()->isActive())
00420 it.value()->stop();
00421 delete it.value();
00422 m_remoteTypingMap.erase(it);
00423 }
00424 if( isTyping )
00425 {
00426 m_remoteTypingMap.insert( contact, new QTimer(this) );
00427 connect( m_remoteTypingMap[ contact ], SIGNAL( timeout() ), SLOT( slotRemoteTypingTimeout() ) );
00428
00429 m_remoteTypingMap[ contact ]->setSingleShot( true );
00430 m_remoteTypingMap[ contact ]->start( 6000 );
00431 }
00432
00433
00434 QStringList typingList;
00435
00436 for( it = m_remoteTypingMap.begin(); it != m_remoteTypingMap.end(); ++it )
00437 {
00438 const Kopete::Contact *c = it.key();
00439 QString nick;
00440 if( c->metaContact() && c->metaContact() != Kopete::ContactList::self()->myself() )
00441 {
00442 nick = c->metaContact()->displayName();
00443 }
00444 else
00445 {
00446 nick = c->nickName();
00447 }
00448 typingList.append( nick );
00449 }
00450
00451
00452 if( !typingList.isEmpty() )
00453 {
00454 if ( typingList.count() == 1 )
00455 setStatusText( i18n( "%1 is typing a message", typingList.first() ) );
00456 else
00457 {
00458 QString statusTyping = typingList.join( QLatin1String( ", " ) );
00459 setStatusText( i18nc( "%1 is a list of names", "%1 are typing a message", statusTyping ) );
00460 }
00461 updateChatState( Typing );
00462 }
00463 else
00464 {
00465 updateChatState();
00466 }
00467 }
00468
00469 void ChatView::setStatusText( const QString &status )
00470 {
00471 d->statusText = status;
00472 if ( d->isActive )
00473 m_mainWindow->setStatus( status );
00474 }
00475
00476 const QString& ChatView::statusText()
00477 {
00478 return d->statusText;
00479 }
00480
00481 void ChatView::slotChatDisplayNameChanged()
00482 {
00483
00484
00485
00486 QString chatName = m_manager->displayName();
00487 if ( chatName != d->captionText )
00488 setCaption( chatName, true );
00489 }
00490
00491 void ChatView::slotPropertyChanged( Kopete::PropertyContainer*, const QString &key,
00492 const QVariant& oldValue, const QVariant &newValue )
00493 {
00494 if ( key == Kopete::Global::Properties::self()->nickName().key() )
00495 {
00496 QString newName=newValue.toString();
00497 QString oldName=oldValue.toString();
00498
00499 if(Kopete::BehaviorSettings::self()->showEvents())
00500 if ( oldName != newName && !oldName.isEmpty())
00501 sendInternalMessage( i18n( "%1 is now known as %2", oldName, newName ) );
00502 }
00503 }
00504
00505 void ChatView::slotDisplayNameChanged( const QString &oldValue, const QString &newValue )
00506 {
00507 if( Kopete::BehaviorSettings::self()->showEvents() )
00508 {
00509 if( oldValue != newValue )
00510 sendInternalMessage( i18n( "%1 is now known as %2", oldValue, newValue ) );
00511 }
00512 }
00513
00514 void ChatView::slotContactAdded(const Kopete::Contact *contact, bool suppress)
00515 {
00516 QString contactName;
00517
00518 if( contact->metaContact() && contact->metaContact() != Kopete::ContactList::self()->myself() )
00519 {
00520 contactName = contact->metaContact()->displayName();
00521 }
00522 else
00523 {
00524 contactName = contact->nickName();
00525 }
00526
00527 if( contact->metaContact() && contact->metaContact() != Kopete::ContactList::self()->myself() )
00528 {
00529 connect( contact->metaContact(), SIGNAL( displayNameChanged(const QString&, const QString&) ),
00530 this, SLOT( slotDisplayNameChanged(const QString &, const QString &) ) );
00531 }
00532 else
00533 {
00534 connect( contact, SIGNAL( propertyChanged( Kopete::PropertyContainer *, const QString &, const QVariant &, const QVariant & ) ),
00535 this, SLOT( slotPropertyChanged( Kopete::PropertyContainer *, const QString &, const QVariant &, const QVariant & ) ) ) ;
00536 }
00537
00538 if( !suppress && m_manager->members().count() > 1 )
00539 sendInternalMessage( i18n("%1 has joined the chat.", contactName) );
00540
00541 updateChatState();
00542 emit updateStatusIcon( this );
00543 }
00544
00545 void ChatView::slotContactRemoved( const Kopete::Contact *contact, const QString &reason, Qt::TextFormat format, bool suppressNotification )
00546 {
00547
00548 if ( contact != m_manager->myself() )
00549 {
00550 TypingMap::iterator it = m_remoteTypingMap.find( contact );
00551 if ( it != m_remoteTypingMap.end() )
00552 {
00553 if ((*it)->isActive())
00554 (*it)->stop();
00555 delete (*it);
00556 m_remoteTypingMap.remove( contact );
00557 }
00558
00559 QString contactName;
00560 if( contact->metaContact() && contact->metaContact() != Kopete::ContactList::self()->myself() )
00561 {
00562 contactName = contact->metaContact()->displayName();
00563 }
00564 else
00565 {
00566 contactName = contact->nickName();
00567 }
00568
00569
00570 if ( m_manager->members().count() > 0 )
00571 {
00572 if( contact->metaContact() )
00573 {
00574 disconnect( contact->metaContact(), SIGNAL( displayNameChanged(const QString&, const QString&) ),
00575 this, SLOT( slotDisplayNameChanged(const QString&, const QString&) ) );
00576 }
00577 else
00578 {
00579 disconnect(contact,SIGNAL(propertyChanged( Kopete::PropertyContainer *, const QString &, const QVariant &, const QVariant & )),
00580 this, SLOT( slotPropertyChanged( Kopete::PropertyContainer *, const QString &, const QVariant &, const QVariant & ) ) ) ;
00581 }
00582 }
00583
00584 if ( !suppressNotification )
00585 {
00586 if ( reason.isEmpty() )
00587 sendInternalMessage( i18n( "%1 has left the chat.", contactName ), format ) ;
00588 else
00589 sendInternalMessage( i18n( "%1 has left the chat (%2).", contactName, reason ), format);
00590 }
00591 }
00592
00593 updateChatState();
00594 emit updateStatusIcon( this );
00595 }
00596
00597 QString& ChatView::caption() const
00598 {
00599 return d->captionText;
00600 }
00601
00602 void ChatView::setCaption( const QString &text, bool modified )
00603 {
00604
00605 QString newCaption = text;
00606
00607
00608 d->captionText = text;
00609
00610
00611 newCaption = KStringHandler::rsqueeze( d->captionText, 20 );
00612
00613
00614 QWidget::setWindowTitle( newCaption );
00615
00616 emit updateChatTooltip( this, QString::fromLatin1("<qt>%1</qt>").arg( d->captionText ) );
00617 emit updateChatLabel( this, newCaption );
00618
00619 if( !d->isActive && modified )
00620 updateChatState( Changed );
00621 else
00622 updateChatState();
00623
00624
00625 emit( captionChanged( d->isActive ) );
00626 }
00627
00628 void ChatView::appendMessage(Kopete::Message &message)
00629 {
00630 remoteTyping( message.from(), false );
00631
00632 messagePart()->appendMessage(message);
00633
00634 if( !d->isActive )
00635 {
00636 switch ( message.importance() )
00637 {
00638 case Kopete::Message::Highlight:
00639 updateChatState( Highlighted );
00640 break;
00641 case Kopete::Message::Normal:
00642 if ( message.direction() == Kopete::Message::Inbound )
00643 {
00644 updateChatState( Message );
00645 break;
00646 }
00647 default:
00648 updateChatState( Changed );
00649 }
00650 }
00651
00652 if( message.direction() == Kopete::Message::Inbound )
00653 {
00654 if( message.from()->metaContact() && message.from()->metaContact() != Kopete::ContactList::self()->myself() )
00655 {
00656 unreadMessageFrom = message.from()->metaContact()->displayName();
00657 }
00658 else
00659 {
00660 unreadMessageFrom = message.from()->nickName();
00661 }
00662 QTimer::singleShot( 1000, this, SLOT( slotMarkMessageRead() ) );
00663 }
00664 else
00665 unreadMessageFrom.clear();
00666 }
00667
00668 void ChatView::slotMarkMessageRead()
00669 {
00670 unreadMessageFrom.clear();
00671 }
00672
00673 void ChatView::slotToggleRtfToolbar( bool enabled )
00674 {
00675 emit rtfEnabled( this, enabled );
00676 }
00677
00678 void ChatView::slotContactStatusChanged( Kopete::Contact *contact, const Kopete::OnlineStatus &newStatus, const Kopete::OnlineStatus &oldStatus )
00679 {
00680 kDebug(14000) << contact;
00681 bool inhibitNotification = ( newStatus.status() == Kopete::OnlineStatus::Unknown ||
00682 oldStatus.status() == Kopete::OnlineStatus::Unknown );
00683 if ( contact && Kopete::BehaviorSettings::self()->showEvents() && !inhibitNotification )
00684 {
00685 if ( contact->account() && contact == contact->account()->myself() )
00686 {
00687
00688 if ( newStatus.status() != Kopete::OnlineStatus::Connecting )
00689 sendInternalMessage( i18n( "You are now marked as %1.", newStatus.description() ) );
00690 }
00691 else if ( !contact->account() || !contact->account()->suppressStatusNotification() )
00692 {
00693
00694 if ( contact->metaContact() && contact->metaContact() != Kopete::ContactList::self()->myself() )
00695 {
00696 sendInternalMessage( i18n( "%2 is now %1.",
00697 newStatus.description(), contact->metaContact()->displayName() ) );
00698 }
00699 else
00700 {
00701 QString nick=contact->nickName();
00702 sendInternalMessage( i18n( "%2 is now %1.",
00703 newStatus.description(), nick ) );
00704 }
00705 }
00706 }
00707
00708
00709 slotChatDisplayNameChanged();
00710 emit updateStatusIcon( this );
00711 }
00712
00713 void ChatView::sendInternalMessage(const QString &msg, Qt::TextFormat format )
00714 {
00715
00716
00717 Kopete::Message message = Kopete::Message();
00718 message.setDirection( Kopete::Message::Internal );
00719 switch(format)
00720 {
00721 default:
00722 case Qt::PlainText:
00723 message.setPlainBody( msg );
00724 break;
00725 case Qt::RichText:
00726 message.setHtmlBody( msg );
00727 break;
00728 }
00729
00730
00731
00732
00733 messagePart()->appendMessage( message );
00734 }
00735
00736 void ChatView::sendMessage()
00737 {
00738 d->sendInProgress = true;
00739 editPart()->sendMessage();
00740 }
00741
00742 void ChatView::messageSentSuccessfully()
00743 {
00744 d->sendInProgress = false;
00745 emit messageSuccess( this );
00746 }
00747
00748 void ChatView::saveOptions()
00749 {
00750 KSharedConfig::Ptr config = KGlobal::config();
00751 KConfigGroup kopeteChatWindowMainWinSettings( config, ( msgManager()->form() == Kopete::ChatSession::Chatroom ? QLatin1String( "KopeteChatWindowGroupMode" ) : QLatin1String( "KopeteChatWindowIndividualMode" ) ) );
00752 kopeteChatWindowMainWinSettings.writeEntry( QLatin1String("ChatViewSplitter"), d->splitter->saveState().toBase64() );
00753 saveChatSettings();
00754 config->sync();
00755 }
00756
00757 void ChatView::saveChatSettings()
00758 {
00759 Kopete::ContactPtrList contacts = msgManager()->members();
00760
00761 if ( contacts.count() == 0 )
00762 return;
00763
00764 Kopete::MetaContact* mc = contacts.first()->metaContact();
00765
00766 if ( contacts.count() > 1 )
00767 return;
00768
00769 if ( !mc )
00770 return;
00771
00772 QString contactListGroup = QLatin1String("chatwindow_") +
00773 mc->metaContactId();
00774 KConfigGroup config = KGlobal::config()->group(contactListGroup);
00775 config.writeEntry( "EnableRichText", editPart()->isRichTextEnabled() );
00776 config.writeEntry( "EnableAutoSpellCheck", editPart()->autoSpellCheckEnabled() );
00777 config.sync();
00778 }
00779
00780 void ChatView::loadChatSettings()
00781 {
00782 Kopete::ContactPtrList contacts = msgManager()->members();
00783 if ( contacts.count() > 1 )
00784 return;
00785
00786
00787 QString contactListGroup = QLatin1String("chatwindow_") +
00788 contacts.first()->metaContact()->metaContactId();
00789 KConfigGroup config(KGlobal::config(), contactListGroup );
00790 bool enableRichText = config.readEntry( "EnableRichText", true );
00791 editPart()->setRichTextEnabled( enableRichText );
00792 emit rtfEnabled( this, editPart()->isRichTextEnabled() );
00793 bool enableAutoSpell = config.readEntry( "EnableAutoSpellCheck", false );
00794 emit autoSpellCheckEnabled( this, enableAutoSpell );
00795 }
00796
00797 void ChatView::readOptions()
00798 {
00799 KConfigGroup kopeteChatWindowMainWinSettings( KGlobal::config(), ( msgManager()->form() == Kopete::ChatSession::Chatroom ? QLatin1String( "KopeteChatWindowGroupMode" ) : QLatin1String( "KopeteChatWindowIndividualMode" ) ) );
00800
00801 QByteArray state;
00802 state = kopeteChatWindowMainWinSettings.readEntry( QLatin1String("ChatViewSplitter"), state );
00803 d->splitter->restoreState( QByteArray::fromBase64( state ) );
00804 }
00805
00806 void ChatView::setActive( bool value )
00807 {
00808 d->isActive = value;
00809 if ( d->isActive )
00810 {
00811 updateChatState( Normal );
00812 emit( activated( static_cast<KopeteView*>(this) ) );
00813 }
00814 }
00815
00816 void ChatView::slotRemoteTypingTimeout()
00817 {
00818
00819
00820 if ( !m_remoteTypingMap.isEmpty() )
00821 remoteTyping( m_remoteTypingMap.begin().key(), false );
00822 }
00823
00824 void ChatView::dragEnterEvent ( QDragEnterEvent * event )
00825 {
00826 if( event->provides( "kopete/x-contact" ) )
00827 {
00828 QStringList lst = QString::fromUtf8(event->encodedData ( "kopete/x-contact" )).split( QChar( 0xE000 ) , QString::SkipEmptyParts );
00829 if(m_manager->mayInvite() && m_manager->protocol()->pluginId() == lst[0] && m_manager->account()->accountId() == lst[1])
00830 {
00831 QString contact=lst[2];
00832
00833 bool found =false;
00834 foreach(Kopete::Contact * cts, m_manager->members())
00835 {
00836 if(cts->contactId() == contact)
00837 {
00838 found=true;
00839 break;
00840 }
00841 }
00842
00843 if(!found && contact != m_manager->myself()->contactId())
00844 event->accept();
00845 }
00846 }
00847 else if( event->provides( "kopete/x-metacontact" ) )
00848 {
00849 QString metacontactID=QString::fromUtf8(event->encodedData ( "kopete/x-metacontact" ));
00850 Kopete::MetaContact *parent = Kopete::ContactList::self()->metaContact(metacontactID);
00851 if ( parent && m_manager->mayInvite() )
00852 {
00853 foreach ( Kopete::Contact * candidate, parent->contacts() )
00854 {
00855 if( candidate && candidate->account() == m_manager->account() && candidate->isOnline())
00856 {
00857 if( candidate != m_manager->myself() && !m_manager->members().contains( candidate ) )
00858 event->accept();
00859 }
00860 }
00861 }
00862 }
00863
00864 else if ( event->provides( "text/uri-list" ) && m_manager->members().count() == 1 &&
00865 ( event->source() != (QWidget*)m_messagePart->view()->viewport() ) )
00866 {
00867 Kopete::ContactPtrList members = m_manager->members();
00868 Kopete::Contact *contact = members.first();
00869 if ( contact && contact->canAcceptFiles() )
00870 event->accept();
00871 }
00872 else
00873 QWidget::dragEnterEvent(event);
00874 }
00875
00876 void ChatView::dropEvent ( QDropEvent * event )
00877 {
00878 Kopete::ContactPtrList contacts;
00879
00880 if( event->provides( "kopete/x-contact" ) )
00881 {
00882 QStringList lst = QString::fromUtf8(event->encodedData ( "kopete/x-contact" )).split( QChar( 0xE000 ) , QString::SkipEmptyParts );
00883 if(m_manager->mayInvite() && m_manager->protocol()->pluginId() == lst[0] && m_manager->account()->accountId() == lst[1])
00884 {
00885 QString contact=lst[2];
00886
00887 bool found =false;
00888 foreach ( Kopete::Contact * candidate, m_manager->members() )
00889 {
00890 if(candidate->contactId() == contact)
00891 {
00892 found=true;
00893 break;
00894 }
00895 }
00896 if(!found && contact != m_manager->myself()->contactId())
00897 m_manager->inviteContact(contact);
00898 }
00899 }
00900 else if( event->provides( "kopete/x-metacontact" ) )
00901 {
00902 QString metacontactID=QString::fromUtf8(event->encodedData ( "kopete/x-metacontact" ));
00903 Kopete::MetaContact *parent = Kopete::ContactList::self()->metaContact(metacontactID);
00904 if ( parent && m_manager->mayInvite() )
00905 {
00906 foreach ( Kopete::Contact * candidate, parent->contacts() )
00907 {
00908 if( candidate && candidate->account() == m_manager->account() && candidate->isOnline())
00909 {
00910 if( candidate != m_manager->myself() && !m_manager->members().contains( candidate ) )
00911 m_manager->inviteContact(candidate->contactId());
00912 }
00913 }
00914 }
00915 }
00916 else if ( event->provides( "text/uri-list" ) && m_manager->members().count() == 1 )
00917 {
00918 Kopete::ContactPtrList members = m_manager->members();
00919 Kopete::Contact *contact = members.first();
00920
00921 if ( !contact || !contact->canAcceptFiles() || !Q3UriDrag::canDecode( event ) )
00922 {
00923 event->ignore();
00924 return;
00925 }
00926
00927 KUrl::List urlList = KUrl::List::fromMimeData( event->mimeData() );
00928
00929 for ( KUrl::List::Iterator it = urlList.begin(); it != urlList.end(); ++it )
00930 {
00931 if ( (*it).isLocalFile() )
00932 {
00933 contact->sendFile( *it );
00934 }
00935 else
00936 {
00937 addText( (*it).url() );
00938 }
00939 }
00940 event->accept();
00941 return;
00942 }
00943 else
00944 QWidget::dropEvent(event);
00945
00946 }
00947
00948 void ChatView::registerContextMenuHandler( QObject *target, const char* slot )
00949 {
00950 connect( m_messagePart,
00951 SIGNAL( contextMenuEvent( Kopete::Message &, const QString &, KMenu * ) ),
00952 target,
00953 slot
00954 );
00955 }
00956
00957 void ChatView::registerTooltipHandler( QObject *target, const char* slot )
00958 {
00959 connect( m_messagePart,
00960 SIGNAL( tooltipEvent( Kopete::Message &, const QString &, QString & ) ),
00961 target,
00962 slot
00963 );
00964 }
00965
00966 #include "chatview.moc"
00967
00968
00969