You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdenetwork/kopete/kopete/chatwindow/kopeteemailwindow.cpp

566 lines
17 KiB

/*
kopeteemailwindow.cpp - Kopete "email window" for single-shot messages
Copyright (c) 2002 by Daniel Stone <dstone@kde.org>
Copyright (c) 2003 by Jason Keirstead <jason@keirstead.org>
Copyright (c) 2003 by Martijn Klingens <klingens@kde.org>
Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>
*************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
*************************************************************************
*/
#include "kopeteemailwindow.h"
#include "chatmessagepart.h"
#include "chattexteditpart.h"
#include "kopetecontact.h"
#include "kopetemetacontact.h"
#include "kopeteemoticonaction.h"
#include "kopetechatsession.h"
#include "kopeteplugin.h"
#include "kopetepluginmanager.h"
#include "kopeteprefs.h"
#include "kopetestdaction.h"
#include "kopeteviewmanager.h"
#include <tdeaction.h>
#include <tdeapplication.h>
#include <kcolordialog.h>
#include <tdeconfig.h>
#include <kcursor.h>
#include <kdebug.h>
#include <tdeversion.h>
#include <kedittoolbar.h>
#include <tdefontdialog.h>
#include <kglobalsettings.h>
#include <tdehtmlview.h>
#include <kiconloader.h>
#include <kkeydialog.h>
#include <klibloader.h>
#include <klocale.h>
#include <kmenubar.h>
#include <kmessagebox.h>
#include <tdepopupmenu.h>
#include <kpushbutton.h>
#include <ktextedit.h>
#include <twin.h>
#include <kgenericfactory.h>
#include <tqlabel.h>
#include <tqlayout.h>
#include <tqtimer.h>
#include <tqvbox.h>
typedef KGenericFactory<EmailWindowPlugin> EmailWindowPluginFactory;
K_EXPORT_COMPONENT_FACTORY( kopete_emailwindow, EmailWindowPluginFactory( "kopete_emailwindow" ) )
EmailWindowPlugin::EmailWindowPlugin(TQObject *parent, const char *name, const TQStringList &) :
Kopete::ViewPlugin( EmailWindowPluginFactory::instance(), parent, name )
{}
KopeteView* EmailWindowPlugin::createView( Kopete::ChatSession *manager )
{
//TODO: foreignMessage, how will we do this cleanly?
return (KopeteView*)new KopeteEmailWindow(manager,this, false);
}
class KopeteEmailWindow::Private
{
public:
TQValueList<Kopete::Message> messageQueue;
bool showingMessage;
bool sendInProgress;
bool visible;
uint queuePosition;
KPushButton *btnReplySend;
KPushButton *btnReadNext;
KPushButton *btnReadPrev;
TQSplitter *split;
ChatMessagePart *messagePart;
KopeteEmailWindow::WindowMode mode;
TDEAction *chatSend;
TQLabel *anim;
TQMovie animIcon;
TQPixmap normalIcon;
TQString unreadMessageFrom;
ChatTextEditPart *editPart;
TDEActionMenu *actionActionMenu;
KopeteEmoticonAction *actionSmileyMenu;
};
KopeteEmailWindow::KopeteEmailWindow( Kopete::ChatSession *manager, EmailWindowPlugin *parent, bool foreignMessage )
: KParts::MainWindow( ), KopeteView( manager, parent ), d( new Private )
{
TQVBox *v = new TQVBox( this );
setCentralWidget( v );
setMinimumSize( TQSize( 75, 20 ) );
d->split = new TQSplitter( v );
d->split->setOrientation( Qt::Vertical );
d->messagePart = new ChatMessagePart( manager, d->split, "messagePart" );
// FIXME: should this be in ChatView too? maybe move to ChatMessagePart?
d->messagePart->view()->setMarginWidth( 4 );
d->messagePart->view()->setMarginHeight( 4 );
d->messagePart->view()->setMinimumSize( TQSize( 75, 20 ) );
d->editPart = new ChatTextEditPart( manager, d->split, "editPart" );
/*
FIXME: dude, wtf?
TQDomDocument doc = d->editPart->domDocument();
TQDomNode menu = doc.documentElement().firstChild();
menu.removeChild( menu.firstChild() ); // Remove File
menu.removeChild( menu.firstChild() ); // Remove Edit
menu.removeChild( menu.firstChild() ); // Remove View
menu.removeChild( menu.lastChild() ); //Remove Help
doc.documentElement().removeChild( doc.documentElement().childNodes().item(1) ); //Remove MainToolbar
doc.documentElement().removeChild( doc.documentElement().lastChild() ); // Remove Edit popup
*/
connect( d->editPart, TQT_SIGNAL( messageSent( Kopete::Message & ) ),
this, TQT_SIGNAL( messageSent( Kopete::Message & ) ) );
connect( d->editPart, TQT_SIGNAL( canSendChanged( bool ) ),
this, TQT_SLOT( slotUpdateReplySend() ) );
connect( d->editPart, TQT_SIGNAL( typing(bool) ),
manager, TQT_SIGNAL( typing(bool) ) );
//Connections to the manager and the ViewManager that every view should have
connect( this, TQT_SIGNAL( closing( KopeteView * ) ),
KopeteViewManager::viewManager(), TQT_SLOT( slotViewDestroyed( KopeteView * ) ) );
connect( this, TQT_SIGNAL( activated( KopeteView * ) ),
KopeteViewManager::viewManager(), TQT_SLOT( slotViewActivated( KopeteView * ) ) );
connect( this, TQT_SIGNAL( messageSent(Kopete::Message &) ),
manager, TQT_SLOT( sendMessage(Kopete::Message &) ) );
connect( manager, TQT_SIGNAL( messageSuccess() ),
this, TQT_SLOT( messageSentSuccessfully() ));
TQWidget *containerWidget = new TQWidget( v );
containerWidget->setSizePolicy( TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum) );
TQHBoxLayout *h = new TQHBoxLayout( containerWidget, 4, 4 );
h->addStretch();
d->btnReadPrev = new KPushButton( i18n( "<< Prev" ), containerWidget );
connect( d->btnReadPrev, TQT_SIGNAL( pressed() ), this, TQT_SLOT( slotReadPrev() ) );
h->addWidget( d->btnReadPrev, 0, TQt::AlignRight | TQt::AlignVCenter );
d->btnReadPrev->setEnabled( false );
d->btnReadNext = new KPushButton( i18n( "(0) Next >>" ), containerWidget );
connect( d->btnReadNext, TQT_SIGNAL( pressed() ), this, TQT_SLOT( slotReadNext() ) );
h->addWidget( d->btnReadNext, 0, TQt::AlignRight | TQt::AlignVCenter );
d->btnReplySend = new KPushButton( containerWidget );
connect( d->btnReplySend, TQT_SIGNAL( pressed() ), this, TQT_SLOT( slotReplySend() ) );
h->addWidget( d->btnReplySend, 0, TQt::AlignRight | TQt::AlignVCenter );
initActions();
setWFlags(TQt::WDestructiveClose);
d->showingMessage = false;
if( foreignMessage )
toggleMode( Read );
else
toggleMode( Send );
TDEConfig *config = TDEGlobal::config();
applyMainWindowSettings( config, TQString::fromLatin1( "KopeteEmailWindow" ) );
d->sendInProgress = false;
toolBar()->alignItemRight( 99 );
d->visible = false;
d->queuePosition = 0;
setCaption( manager->displayName() );
slotUpdateReplySend();
}
KopeteEmailWindow::~KopeteEmailWindow()
{
emit( closing( this ) );
// saves menubar, toolbar and statusbar setting
TDEConfig *config = TDEGlobal::config();
saveMainWindowSettings( config, TQString::fromLatin1( "KopeteEmailWindow" ) );
config->sync();
delete d;
}
void KopeteEmailWindow::initActions(void)
{
TDEActionCollection *coll = actionCollection();
d->chatSend = new TDEAction( i18n( "&Send Message" ), TQString::fromLatin1( "mail_send" ), 0,
TQT_TQOBJECT(this), TQT_SLOT( slotReplySend() ), coll, "chat_send" );
//Default to 'Return' for sending messages
d->chatSend->setShortcut( TQKeySequence( Key_Return ) );
KStdAction::quit ( TQT_TQOBJECT(this), TQT_SLOT( slotCloseView() ), coll );
KStdAction::cut( TQT_TQOBJECT(d->editPart->widget()), TQT_SLOT( cut() ), coll );
KStdAction::copy( TQT_TQOBJECT(this), TQT_SLOT(slotCopy()), coll);
KStdAction::paste( TQT_TQOBJECT(d->editPart->widget()), TQT_SLOT( paste() ), coll );
new TDEAction( i18n( "&Set Font..." ), TQString::fromLatin1( "charset" ), 0,
d->editPart, TQT_SLOT( setFont() ), coll, "format_font" );
new TDEAction( i18n( "Set Text &Color..." ), TQString::fromLatin1( "pencil" ), 0,
d->editPart, TQT_SLOT( setFgColor() ), coll, "format_color" );
new TDEAction( i18n( "Set &Background Color..." ), TQString::fromLatin1( "fill" ), 0,
d->editPart, TQT_SLOT( setBgColor() ), coll, "format_bgcolor" );
KStdAction::showMenubar( TQT_TQOBJECT(this), TQT_SLOT( slotViewMenuBar() ), coll );
setStandardToolBarMenuEnabled( true );
d->actionSmileyMenu = new KopeteEmoticonAction( coll, "format_smiley" );
d->actionSmileyMenu->setDelayed( false );
connect(d->actionSmileyMenu, TQT_SIGNAL(activated(const TQString &)), this, TQT_SLOT(slotSmileyActivated(const TQString &)));
// add configure key bindings menu item
KStdAction::keyBindings( guiFactory(), TQT_SLOT( configureShortcuts() ), coll );
KStdAction::configureToolbars(TQT_TQOBJECT(this), TQT_SLOT( slotConfToolbar() ), coll);
//FIXME: no longer works?
KopeteStdAction::preferences( coll , "settings_prefs" );
// The animated toolbarbutton
d->normalIcon = TQPixmap( BarIcon( TQString::fromLatin1( "kopete" ) ) );
d->animIcon = TDEGlobal::iconLoader()->loadMovie( TQString::fromLatin1( "newmessage" ), TDEIcon::Toolbar);
d->animIcon.pause();
d->anim = new TQLabel( this, "kde toolbar widget" );
d->anim->setMargin( 5 );
d->anim->setPixmap( d->normalIcon );
new KWidgetAction( d->anim, i18n("Toolbar Animation"), 0, 0, 0, coll, "toolbar_animation" );
setXMLFile( TQString::fromLatin1( "kopeteemailwindow.rc" ) );
createGUI( d->editPart );
//createGUI( TQString::fromLatin1( "kopeteemailwindow.rc" ) );
guiFactory()->addClient(m_manager);
}
void KopeteEmailWindow::closeEvent( TQCloseEvent *e )
{
// DO NOT call base class's closeEvent - see comment in KopeteApplication constructor for reason
// Save settings if auto-save is enabled, and settings have changed
if ( settingsDirty() && autoSaveSettings() )
saveAutoSaveSettings();
e->accept();
}
void KopeteEmailWindow::slotViewMenuBar()
{
if( !menuBar()->isHidden() )
menuBar()->hide();
else
menuBar()->show();
}
void KopeteEmailWindow::slotSmileyActivated(const TQString &sm )
{
if ( !sm.isNull() )
d->editPart->addText( sm );
}
void KopeteEmailWindow::slotConfToolbar()
{
saveMainWindowSettings(TDEGlobal::config(), TQString::fromLatin1( "KopeteEmailWindow" ));
KEditToolbar *dlg = new KEditToolbar(actionCollection(), TQString::fromLatin1("kopeteemailwindow.rc") );
if (dlg->exec())
{
createGUI( d->editPart );
applyMainWindowSettings(TDEGlobal::config(), TQString::fromLatin1( "KopeteEmailWindow" ));
}
delete dlg;
}
void KopeteEmailWindow::slotCopy()
{
// kdDebug(14010) << k_funcinfo << endl;
if ( d->messagePart->hasSelection() )
d->messagePart->copy();
else
d->editPart->widget()->copy();
}
void KopeteEmailWindow::appendMessage(Kopete::Message &message)
{
if( message.from() != m_manager->myself() )
{
if( d->mode == Send )
toggleMode( Reply );
d->messageQueue.append( message );
if( !d->showingMessage )
slotReadNext();
else
{
d->btnReadNext->setPaletteForegroundColor( TQColor("red") );
updateNextButton();
}
d->unreadMessageFrom = message.from()->metaContact() ?
message.from()->metaContact()->displayName() : message.from()->contactId();
TQTimer::singleShot( 1000, this, TQT_SLOT(slotMarkMessageRead()) );
}
}
void KopeteEmailWindow::slotMarkMessageRead()
{
d->unreadMessageFrom = TQString();
}
void KopeteEmailWindow::updateNextButton()
{
if( d->queuePosition == d->messageQueue.count() )
{
d->btnReadNext->setEnabled( false );
d->btnReadNext->setPaletteForegroundColor( TDEGlobalSettings::textColor() );
}
else
d->btnReadNext->setEnabled( true );
if( d->queuePosition == 1 )
d->btnReadPrev->setEnabled( false );
else
d->btnReadPrev->setEnabled( true );
d->btnReadNext->setText( i18n( "(%1) Next >>" ).arg( d->messageQueue.count() - d->queuePosition ) );
}
void KopeteEmailWindow::slotUpdateReplySend()
{
bool canSend;
if( d->mode == Read )
canSend = true;
else
canSend = d->editPart->canSend();
d->btnReplySend->setEnabled( canSend );
d->chatSend->setEnabled( canSend );
}
void KopeteEmailWindow::slotReadNext()
{
// kdDebug(14010) << k_funcinfo << endl;
d->showingMessage = true;
d->queuePosition++;
writeMessage( (*d->messageQueue.at( d->queuePosition - 1 )) );
updateNextButton();
}
void KopeteEmailWindow::slotReadPrev()
{
// kdDebug(14010) << k_funcinfo << endl;
d->showingMessage = true;
d->queuePosition--;
writeMessage( (*d->messageQueue.at( d->queuePosition - 1 )) );
updateNextButton();
}
void KopeteEmailWindow::writeMessage( Kopete::Message &msg )
{
d->messagePart->clear();
d->messagePart->appendMessage( msg );
}
void KopeteEmailWindow::sendMessage()
{
if ( !d->editPart->canSend() )
return;
d->sendInProgress = true;
d->anim->setMovie( d->animIcon );
d->animIcon.unpause();
d->editPart->widget()->setEnabled( false );
d->editPart->sendMessage();
}
void KopeteEmailWindow::messageSentSuccessfully()
{
d->sendInProgress = false;
d->anim->setPixmap( d->normalIcon );
d->animIcon.pause();
closeView();
}
bool KopeteEmailWindow::closeView( bool force )
{
int response = KMessageBox::Continue;
if( !force )
{
if( m_manager->members().count() > 1 )
{
TQString shortCaption = caption();
if( shortCaption.length() > 40 )
shortCaption = shortCaption.left( 40 ) + TQString::fromLatin1("...");
response = KMessageBox::warningContinueCancel(this, i18n("<qt>You are about to leave the group chat session <b>%1</b>.<br>"
"You will not receive future messages from this conversation.</qt>").arg(shortCaption), i18n("Closing Group Chat"),
i18n("Cl&ose Chat"), TQString::fromLatin1("AskCloseGroupChat"));
}
if( !d->unreadMessageFrom.isNull() && ( response == KMessageBox::Continue ) )
{
response = KMessageBox::warningContinueCancel(this, i18n("<qt>You have received a message from <b>%1</b> in the last "
"second. Are you sure you want to close this chat?</qt>").arg(d->unreadMessageFrom), i18n("Unread Message"),
i18n("Cl&ose Chat"), TQString::fromLatin1("AskCloseChatRecentMessage"));
}
if( d->sendInProgress && ( response == KMessageBox::Continue ) )
{
response = KMessageBox::warningContinueCancel(this, i18n("You have a message send in progress, which will be "
"aborted if this chat is closed. Are you sure you want to close this chat?"), i18n("Message in Transit"),
i18n("Cl&ose Chat"), TQString::fromLatin1("AskCloseChatMessageInProgress") );
}
}
if( response == KMessageBox::Continue )
{
d->visible = false;
deleteLater();
return true;
}
else
{
d->editPart->widget()->setEnabled( true );
}
return false;
}
void KopeteEmailWindow::toggleMode( WindowMode newMode )
{
d->mode = newMode;
switch( d->mode )
{
case Send:
d->btnReplySend->setText( i18n( "Send" ) );
d->editPart->widget()->show();
d->messagePart->view()->hide();
d->btnReadNext->hide();
d->btnReadPrev->hide();
break;
case Read:
d->btnReplySend->setText( i18n( "Reply" ) );
d->editPart->widget()->hide();
d->messagePart->view()->show();
d->btnReadNext->show();
d->btnReadPrev->show();
break;
case Reply:
TQValueList<int> splitPercent;
// FIXME: should be saved and restored
splitPercent.append(50);
splitPercent.append(50);
d->btnReplySend->setText( i18n( "Send" ) );
d->editPart->widget()->show();
d->messagePart->view()->show();
d->btnReadNext->show();
d->btnReadPrev->show();
d->split->setSizes( splitPercent );
d->editPart->widget()->setFocus();
break;
}
slotUpdateReplySend();
}
void KopeteEmailWindow::slotReplySend()
{
if( d->mode == Read )
toggleMode( Reply );
else
sendMessage();
}
//FIXME: Activate bool no longer needed due to setActiveWindow not being allowed
void KopeteEmailWindow::raise(bool activate)
{
makeVisible();
if ( !KWin::windowInfo( winId(), NET::WMDesktop ).onAllDesktops() )
KWin::setOnDesktop( winId(), KWin::currentDesktop() );
TDEMainWindow::raise();
/* Removed Nov 2003
According to Zack, the user double-clicking a contact is not valid reason for a non-pager
to grab window focus. While I don't agree with this, and it runs contradictory to every other
IM out there, commenting this code out to agree with KWin policy.
Redirect any bugs relating to the widnow now not grabbing focus on clicking a contact to KWin.
- Jason K
*/
//Will not activate window if user was typing
if(activate)
KWin::activateWindow( winId() );
}
void KopeteEmailWindow::windowActivationChange( bool )
{
if( isActiveWindow() )
emit( activated( static_cast<KopeteView*>(this) ) );
}
void KopeteEmailWindow::makeVisible()
{
// kdDebug(14010) << k_funcinfo << endl;
d->visible = true;
show();
}
bool KopeteEmailWindow::isVisible()
{
return d->visible;
}
Kopete::Message KopeteEmailWindow::currentMessage()
{
return d->editPart->contents();
}
void KopeteEmailWindow::setCurrentMessage( const Kopete::Message &newMessage )
{
d->editPart->setContents( newMessage );
}
void KopeteEmailWindow::slotCloseView()
{
closeView();
}
#include "kopeteemailwindow.moc"
// vim: set noet ts=4 sts=4 sw=4: