summaryrefslogtreecommitdiffstats
path: root/kopete/kopete/chatwindow/kopeteemailwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kopete/kopete/chatwindow/kopeteemailwindow.cpp')
-rw-r--r--kopete/kopete/chatwindow/kopeteemailwindow.cpp565
1 files changed, 565 insertions, 0 deletions
diff --git a/kopete/kopete/chatwindow/kopeteemailwindow.cpp b/kopete/kopete/chatwindow/kopeteemailwindow.cpp
new file mode 100644
index 00000000..84b71b16
--- /dev/null
+++ b/kopete/kopete/chatwindow/kopeteemailwindow.cpp
@@ -0,0 +1,565 @@
+/*
+ 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 <kaction.h>
+#include <kapplication.h>
+#include <kcolordialog.h>
+#include <kconfig.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kdeversion.h>
+#include <kedittoolbar.h>
+#include <kfontdialog.h>
+#include <kglobalsettings.h>
+#include <khtmlview.h>
+#include <kiconloader.h>
+#include <kkeydialog.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kmenubar.h>
+#include <kmessagebox.h>
+#include <kpopupmenu.h>
+#include <kpushbutton.h>
+#include <ktextedit.h>
+#include <kwin.h>
+#include <kgenericfactory.h>
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qtimer.h>
+#include <qvbox.h>
+
+typedef KGenericFactory<EmailWindowPlugin> EmailWindowPluginFactory;
+K_EXPORT_COMPONENT_FACTORY( kopete_emailwindow, EmailWindowPluginFactory( "kopete_emailwindow" ) )
+
+EmailWindowPlugin::EmailWindowPlugin(QObject *parent, const char *name, const QStringList &) :
+ 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:
+ QValueList<Kopete::Message> messageQueue;
+ bool showingMessage;
+ bool sendInProgress;
+ bool visible;
+ uint queuePosition;
+ KPushButton *btnReplySend;
+ KPushButton *btnReadNext;
+ KPushButton *btnReadPrev;
+ QSplitter *split;
+ ChatMessagePart *messagePart;
+ KopeteEmailWindow::WindowMode mode;
+ KAction *chatSend;
+ QLabel *anim;
+ QMovie animIcon;
+ QPixmap normalIcon;
+ QString unreadMessageFrom;
+ ChatTextEditPart *editPart;
+
+ KActionMenu *actionActionMenu;
+ KopeteEmoticonAction *actionSmileyMenu;
+};
+
+KopeteEmailWindow::KopeteEmailWindow( Kopete::ChatSession *manager, EmailWindowPlugin *parent, bool foreignMessage )
+ : KParts::MainWindow( ), KopeteView( manager, parent ), d( new Private )
+{
+ QVBox *v = new QVBox( this );
+ setCentralWidget( v );
+
+ setMinimumSize( QSize( 75, 20 ) );
+
+ d->split = new QSplitter( v );
+ d->split->setOrientation( QSplitter::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( QSize( 75, 20 ) );
+
+ d->editPart = new ChatTextEditPart( manager, d->split, "editPart" );
+
+ /*
+ FIXME: dude, wtf?
+ QDomDocument doc = d->editPart->domDocument();
+ QDomNode 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, SIGNAL( messageSent( Kopete::Message & ) ),
+ this, SIGNAL( messageSent( Kopete::Message & ) ) );
+ connect( d->editPart, SIGNAL( canSendChanged( bool ) ),
+ this, SLOT( slotUpdateReplySend() ) );
+ connect( d->editPart, SIGNAL( typing(bool) ),
+ manager, SIGNAL( typing(bool) ) );
+
+ //Connections to the manager and the ViewManager that every view should have
+ connect( this, SIGNAL( closing( KopeteView * ) ),
+ KopeteViewManager::viewManager(), SLOT( slotViewDestroyed( KopeteView * ) ) );
+ connect( this, SIGNAL( activated( KopeteView * ) ),
+ KopeteViewManager::viewManager(), SLOT( slotViewActivated( KopeteView * ) ) );
+ connect( this, SIGNAL( messageSent(Kopete::Message &) ),
+ manager, SLOT( sendMessage(Kopete::Message &) ) );
+ connect( manager, SIGNAL( messageSuccess() ),
+ this, SLOT( messageSentSuccessfully() ));
+
+ QWidget *containerWidget = new QWidget( v );
+ containerWidget->setSizePolicy( QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum) );
+
+ QHBoxLayout *h = new QHBoxLayout( containerWidget, 4, 4 );
+ h->addStretch();
+
+ d->btnReadPrev = new KPushButton( i18n( "<< Prev" ), containerWidget );
+ connect( d->btnReadPrev, SIGNAL( pressed() ), this, SLOT( slotReadPrev() ) );
+ h->addWidget( d->btnReadPrev, 0, Qt::AlignRight | Qt::AlignVCenter );
+ d->btnReadPrev->setEnabled( false );
+
+ d->btnReadNext = new KPushButton( i18n( "(0) Next >>" ), containerWidget );
+ connect( d->btnReadNext, SIGNAL( pressed() ), this, SLOT( slotReadNext() ) );
+ h->addWidget( d->btnReadNext, 0, Qt::AlignRight | Qt::AlignVCenter );
+
+ d->btnReplySend = new KPushButton( containerWidget );
+ connect( d->btnReplySend, SIGNAL( pressed() ), this, SLOT( slotReplySend() ) );
+ h->addWidget( d->btnReplySend, 0, Qt::AlignRight | Qt::AlignVCenter );
+
+ initActions();
+ setWFlags(Qt::WDestructiveClose);
+
+ d->showingMessage = false;
+
+ if( foreignMessage )
+ toggleMode( Read );
+ else
+ toggleMode( Send );
+
+ KConfig *config = KGlobal::config();
+ applyMainWindowSettings( config, QString::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
+ KConfig *config = KGlobal::config();
+ saveMainWindowSettings( config, QString::fromLatin1( "KopeteEmailWindow" ) );
+ config->sync();
+
+ delete d;
+}
+
+void KopeteEmailWindow::initActions(void)
+{
+ KActionCollection *coll = actionCollection();
+
+ d->chatSend = new KAction( i18n( "&Send Message" ), QString::fromLatin1( "mail_send" ), 0,
+ this, SLOT( slotReplySend() ), coll, "chat_send" );
+ //Default to 'Return' for sending messages
+ d->chatSend->setShortcut( QKeySequence( Key_Return ) );
+
+ KStdAction::quit ( this, SLOT( slotCloseView() ), coll );
+
+ KStdAction::cut( d->editPart->widget(), SLOT( cut() ), coll );
+ KStdAction::copy( this, SLOT(slotCopy()), coll);
+ KStdAction::paste( d->editPart->widget(), SLOT( paste() ), coll );
+
+ new KAction( i18n( "&Set Font..." ), QString::fromLatin1( "charset" ), 0,
+ d->editPart, SLOT( setFont() ), coll, "format_font" );
+ new KAction( i18n( "Set Text &Color..." ), QString::fromLatin1( "pencil" ), 0,
+ d->editPart, SLOT( setFgColor() ), coll, "format_color" );
+ new KAction( i18n( "Set &Background Color..." ), QString::fromLatin1( "fill" ), 0,
+ d->editPart, SLOT( setBgColor() ), coll, "format_bgcolor" );
+
+ KStdAction::showMenubar( this, SLOT( slotViewMenuBar() ), coll );
+ setStandardToolBarMenuEnabled( true );
+
+ d->actionSmileyMenu = new KopeteEmoticonAction( coll, "format_smiley" );
+ d->actionSmileyMenu->setDelayed( false );
+ connect(d->actionSmileyMenu, SIGNAL(activated(const QString &)), this, SLOT(slotSmileyActivated(const QString &)));
+
+ // add configure key bindings menu item
+ KStdAction::keyBindings( guiFactory(), SLOT( configureShortcuts() ), coll );
+ KStdAction::configureToolbars(this, SLOT( slotConfToolbar() ), coll);
+ //FIXME: no longer works?
+ KopeteStdAction::preferences( coll , "settings_prefs" );
+
+ // The animated toolbarbutton
+ d->normalIcon = QPixmap( BarIcon( QString::fromLatin1( "kopete" ) ) );
+ d->animIcon = KGlobal::iconLoader()->loadMovie( QString::fromLatin1( "newmessage" ), KIcon::Toolbar);
+ d->animIcon.pause();
+
+ d->anim = new QLabel( 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( QString::fromLatin1( "kopeteemailwindow.rc" ) );
+ createGUI( d->editPart );
+ //createGUI( QString::fromLatin1( "kopeteemailwindow.rc" ) );
+ guiFactory()->addClient(m_manager);
+}
+
+void KopeteEmailWindow::closeEvent( QCloseEvent *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 QString &sm )
+{
+ if ( !sm.isNull() )
+ d->editPart->addText( sm );
+}
+
+void KopeteEmailWindow::slotConfToolbar()
+{
+ saveMainWindowSettings(KGlobal::config(), QString::fromLatin1( "KopeteEmailWindow" ));
+ KEditToolbar *dlg = new KEditToolbar(actionCollection(), QString::fromLatin1("kopeteemailwindow.rc") );
+ if (dlg->exec())
+ {
+ createGUI( d->editPart );
+ applyMainWindowSettings(KGlobal::config(), QString::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( QColor("red") );
+ updateNextButton();
+ }
+
+ d->unreadMessageFrom = message.from()->metaContact() ?
+ message.from()->metaContact()->displayName() : message.from()->contactId();
+ QTimer::singleShot( 1000, this, SLOT(slotMarkMessageRead()) );
+ }
+}
+
+void KopeteEmailWindow::slotMarkMessageRead()
+{
+ d->unreadMessageFrom = QString::null;
+}
+
+void KopeteEmailWindow::updateNextButton()
+{
+ if( d->queuePosition == d->messageQueue.count() )
+ {
+ d->btnReadNext->setEnabled( false );
+
+ d->btnReadNext->setPaletteForegroundColor( KGlobalSettings::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 )
+ {
+ QString shortCaption = caption();
+ if( shortCaption.length() > 40 )
+ shortCaption = shortCaption.left( 40 ) + QString::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"), QString::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"), QString::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"), QString::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:
+ QValueList<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() );
+
+ KMainWindow::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:
+