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