[prev in list] [next in list] [prev in thread] [next in thread]
List: kmail-devel
Subject: KMCommands
From: Don Sanders <sanders () trolltech ! com>
Date: 2002-07-29 5:44:06
[Download RAW message or body]
Attached are the kmcommand header and implementation files I have been
working on.
The files contain various classes I have been working on based on the
command pattern. These classes are based on an asynchronous version
of the command pattern so instead of having only a virtual execute
method the base command class has a non-virtual start method that is
responsible for performing necessary async operations and then
calling the virtual execute method.
The force behind implementing these classes is to make message
operations independent of the kmmainwin gui class. This will enable
these operations to be performed by other main windows that show
messages, such as top level reader windows, the search window and
possibly the composer window (for the list of attachments)
These commands classes may also be useful for improving undo/redo.
Some commands may be undone by implementing an undo() or unExecute()
method. Then undo and redo stacks can be kept, this technique has
been used to good effect in KAddressBook.
Another possible use is for disconnected imap operation. When offline
commands that require a connection to the imap server may be kept in
a queue so that they can be executed when the connection to the
server is reestablished.
I have modified other files but only included kmcommands.*, the other
files are not ready for public display yet. As an example commands
may be used like so:
KMAsyncCommand *command = new KMForwardAttachedCommand(this,
*mHeaders->selectMsgs(), mFolder);
command->start();
In the kmcommands.* files, I've currently called the base class
KMAsyncCommand, but I've decided this verbosity is unnecessary and
intend to rename the class KMCommand.
Because KMAsyncCommand based classes are asynchronous I've decided
it's best if they delete themselves. Hence no explicit deletion is
required and KMAsyncCommands should not be created on the stack.
There are three different types of commands defined in kmcommands.*:
1) Synchronous commands, these don't really even need start(), as
execute() could be called directly.
2) Async commands that retrieve a single message then operate on it.
3) Async commands that retrieve multiple messsages then operate on
them.
Currently KMAsyncCommand has 3 different constructors one to handle
each of the above cases. In the future I might split things up into 3
different classes.
KMAsyncCommand is implemented in terms of transferSelectedMsgs and
related methods that previously were implemented in kmmainwin.cpp.
I have several concerns about this transferSelectedMsgs code.
I suspect the code is buggy and won't handle multiple main windows
(File->"New Mail Client") correctly. For instance if I select
messages on an imap server, forward them as attachments and while
that operation is in progress open up an additional main window and
read messages that have been selected for forwarding I expect
dangling pointers to be created and KMail to crash. To fix this
transferSelectedMsgs and related methods should be modified to use
serial numbers instead of KMMsgBase*, but we need a reliable serial
number dict before this change should be made.
Even when working with a list of messages to be retrieved
transferSelectedMsgs works with the concept of a single folder. This
is restrictive because in the search dialog messages shown may come
from multiple folders.
transferSelectedMsgs shows a toplevel progress dialog (which is why
KMAsyncCommand constructors take a mainWin argument, to use as a
parent for the dialog). Instead it would be better to show the
progress in the mainWin status bar. If other status bar using
operations are in progress then the combined progress for all pending
operations related to that main window should be shown in the status
bar.
transferSelectedMsgs checks for protocol == "imap", and if so creates
KMImapJobs as necessary. I would prefer it if the KMImapJob helper
class was based on a virtual base class that was implemented by all
folder classes. Then the non-imap branch in transferSelectedMsgs
would be eliminated and all folders would be treated the same as imap
folders currently are.
transferSelectedMsgs loads all messages operated on into memory at
once. This is a problem that cannot be easily fixed due to
limitations in mimelib. I'll attempt to fix mimelib after I'm
satisfied with kmcommands.*
I have not yet completed implementing commands. The delete, move and
copy commands have yet to be completed.
Currently commands are indepedent of KActions. I may add static
factory methods to commands to generate a KAction related to the
command. I would do this to avoid duplication of some action strings
(specifically the name and accel key strings). For a substantial
amount of time I tried to make KMCommands a factory class for
KActions. This would mean client classes like KMMainWin would not
have to define slots for each action. Instead each KMCommand class
would create an action and connect the action to a slot of its own.
I've given up this idea finding it required to much rigidity in the
command container classes.
The commands are not fully tested. I have tested all the commands but
have made signficant changes to the base class KMAsyncCommand since
then.
Some commands (AddrAddrBook, OpenAddrBook, urlOpen, toggleFixedFont,
setStatus) are trivial and exist only for the sake of consistency.
The source code is not currently commented. I'll do that before
committing. I also haven't bothered making parameters that should be
constant const or using references where appropriate.
Don.
["kmcommands.h" (text/x-chdr)]
#ifndef KMCommands_h
#define KMCommands_h
#include <qptrlist.h>
#include <kio/job.h>
#include "kmmsgbase.h" // for KMMsgStatus
class QTextCodec;
class KIO::Job;
class KMainWindow;
class KProgressDialog;
class KMFolder;
class KMHeaders;
class KMMessage;
class KMMsgBase;
class KMMainWin;
class KMReaderWin;
class KMAsyncCommand : public QObject
{
Q_OBJECT
public:
KMAsyncCommand( QWidget *parent = 0 );
KMAsyncCommand( QWidget *parent, QPtrList<KMMsgBase> msgList,
KMFolder *folder );
KMAsyncCommand( QWidget *parent, KMMsgBase *msgBase );
virtual ~KMAsyncCommand();
void start();
protected:
QPtrList<KMMessage> *retrievedMsgs();
KMMessage *retrievedMessage();
private:
virtual void execute() = 0;
void preTransfer();
void transferSelectedMsgs();
private slots:
void slotPostTransfer(bool);
void slotMsgTransfered(KMMessage* msg);
void slotJobFinished();
void slotTransferCancelled();
signals:
void messagesTransfered(bool);
private:
// ProgressDialog for transfering messages
KProgressDialog* mProgressDialog;
//Currently only one async command allowed at a time
static int mCountJobs;
int mCountMsgs;
QWidget *mParent;
QPtrList<KMMessage> mRetrievedMsgs;
QPtrList<KMMsgBase> mMsgList;
KMFolder *mFolder;
};
class KMMailtoComposeCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMMailtoComposeCommand( KURL url, KMMsgBase *msgBase = 0 );
private:
virtual void execute();
KURL mUrl;
KMMsgBase *mMsgBase;
};
class KMMailtoReplyCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMMailtoReplyCommand( KMainWindow *parent, KURL url, KMMsgBase *msgBase,
QString selection );
private:
virtual void execute();
KURL mUrl;
QString mSelection;
};
class KMMailtoForwardCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMMailtoForwardCommand( KMainWindow *parent, KURL url, KMMsgBase *msgBase );
private:
virtual void execute();
KURL mUrl;
};
class KMMailtoAddAddrBookCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMMailtoAddAddrBookCommand( KURL url, QWidget *parent );
private:
virtual void execute();
KURL mUrl;
QWidget *mParent;
};
class KMMailtoOpenAddrBookCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMMailtoOpenAddrBookCommand( KURL url, QWidget *parent );
private:
virtual void execute();
KURL mUrl;
QWidget *mParent;
};
class KMUrlCopyCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMUrlCopyCommand( KURL url, KMMainWin *mainWin = 0 );
private:
virtual void execute();
KURL mUrl;
KMMainWin *mMainWin;
};
class KMUrlOpenCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMUrlOpenCommand( KURL url, KMReaderWin *readerWin );
private:
virtual void execute();
KURL mUrl;
KMReaderWin *mReaderWin;
};
class KMUrlSaveCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMUrlSaveCommand( KURL url, QWidget *parent );
private slots:
void slotUrlSaveResult( KIO::Job *job );
private:
virtual void execute();
KURL mUrl;
QWidget *mParent;
};
class KMEditMsgCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMEditMsgCommand( KMainWindow *parent, KMMsgBase *msgBase );
private:
virtual void execute();
};
class KMShowMsgSrcCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMShowMsgSrcCommand( KMainWindow *parent, KMMsgBase *msgBase,
QTextCodec *codec, bool fixedFont );
virtual void execute();
private:
QTextCodec *mCodec;
bool mFixedFont;
};
class KMSaveMsgCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMSaveMsgCommand( KMainWindow *parent, QPtrList<KMMsgBase> msgList,
KMFolder *folder );
KURL url();
private:
virtual void execute();
private:
KURL mUrl;
};
class KMDeleteMsgCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMDeleteMsgCommand( KMMsgBase *msgBase );
virtual void execute();
private:
KMMsgBase *mMsgBase;
};
class KMReplyToCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMReplyToCommand( KMainWindow *parent, KMMsgBase *msgBase,
QString selection );
private:
virtual void execute();
private:
QString mSelection;
};
class KMReplyToAllCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMReplyToAllCommand( KMainWindow *parent, KMMsgBase *msgBase,
QString selection );
private:
virtual void execute();
private:
QString mSelection;
};
class KMForwardCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMForwardCommand( KMainWindow *parent, QPtrList<KMMsgBase> msgList,
KMFolder *folder );
private:
virtual void execute();
private:
QWidget *mParent;
KMFolder *mFolder;
};
class KMForwardAttachedCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMForwardAttachedCommand( KMainWindow *parent, QPtrList<KMMsgBase> msgList,
KMFolder *folder );
private:
virtual void execute();
KMFolder *mFolder;
};
class KMRedirectCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMRedirectCommand( KMainWindow *parent, KMMsgBase *msgBase );
private:
virtual void execute();
};
class KMBounceCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMBounceCommand( KMainWindow *parent, KMMsgBase *msgBase );
private:
virtual void execute();
};
class KMToggleFixedCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMToggleFixedCommand( KMReaderWin *readerWin );
private:
virtual void execute();
KMReaderWin *mReaderWin;
};
class KMPrintCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMPrintCommand( KMainWindow *parent, KMMsgBase *msgBase );
private:
virtual void execute();
};
class KMSetStatusCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMSetStatusCommand( KMMsgStatus status, QValueList<int> ids,
KMFolder *folder );
private:
virtual void execute();
KMMsgStatus mStatus;
QValueList<int> mIds;
KMFolder *mFolder;
};
class KMFilterCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMFilterCommand( QCString field, QString value );
private:
virtual void execute();
QCString mField;
QString mValue;
};
class KMMailingListFilterCommand : public KMAsyncCommand
{
Q_OBJECT
public:
KMMailingListFilterCommand( KMMainWin *win, KMMsgBase *msgBase );
private:
virtual void execute();
};
/*
delete
move
copy
*/
#endif /*KMCommands_h*/
["kmcommands.cpp" (text/x-c++src)]
#include <mimelib/enum.h>
#include <mimelib/field.h>
#include <mimelib/mimepp.h>
#include <qptrlist.h>
#include <qregexp.h>
#include <qtextcodec.h>
#include <kfiledialog.h>
#include <kio/netaccess.h>
#include <kio/job.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kparts/browserextension.h>
#include <kprogress.h>
#include "kbusyptr.h"
#include "mailinglist-magic.h"
#include "kmaddrbook.h"
#include "kmcomposewin.h"
#include "kmfiltermgr.h"
#include "kmfolder.h"
#include "kmfolderimap.h"
#include "kmheaders.h"
#include "kmkernel.h"
#include "kmmainwin.h"
#include "kmmessage.h"
#include "kmreaderwin.h"
#include "kmsender.h"
#include "kmcommands.h"
#include "kmcommands.moc"
#define IDENTITY_UOIDs
KMAsyncCommand::KMAsyncCommand( QWidget *parent )
:mParent( parent ), mFolder( 0 )
{
}
KMAsyncCommand::KMAsyncCommand( QWidget *parent, QPtrList<KMMsgBase> msgList,
KMFolder *folder )
:mParent( parent ), mMsgList( msgList ), mFolder( folder )
{
}
KMAsyncCommand::KMAsyncCommand( QWidget *parent, KMMsgBase *msgBase )
:mParent( parent ), mFolder( msgBase->parent() )
{
QPtrList< KMMsgBase > msgList;
msgList.append( msgBase );
mMsgList = msgList;
}
KMAsyncCommand::~KMAsyncCommand()
{
}
void KMAsyncCommand::start()
{
preTransfer();
}
QPtrList<KMMessage> *KMAsyncCommand::retrievedMsgs()
{
return &mRetrievedMsgs;
}
KMMessage *KMAsyncCommand::retrievedMessage()
{
return mRetrievedMsgs.getFirst();
}
int KMAsyncCommand::mCountJobs = 0;
void KMAsyncCommand::preTransfer()
{
connect(this, SIGNAL(messagesTransfered(bool)),
this, SLOT(slotPostTransfer(bool)));
if ( (mMsgList.count() > 0) && !mFolder) {
emit messagesTransfered(false);
return;
}
// transfer the selected messages first
transferSelectedMsgs();
}
void KMAsyncCommand::slotPostTransfer(bool success)
{
disconnect(this, SIGNAL(messagesTransfered(bool)),
this, SLOT(slotPostTransfer(bool)));
if (success)
execute();
delete this;
}
void KMAsyncCommand::transferSelectedMsgs()
{
// make sure no other transfer is active
if (KMAsyncCommand::mCountJobs > 0) {
emit messagesTransfered(false);
return;
}
bool complete = true;
KMAsyncCommand::mCountJobs = 0;
mCountMsgs = 0;
mRetrievedMsgs.clear();
mCountMsgs = mMsgList.count();
// the KProgressDialog for the user-feedback
mProgressDialog = new KProgressDialog(mParent, "transferProgress",
i18n("Please wait"),
i18n("Please wait while the message is transferred",
"Please wait while the %n messages are transferred", mMsgList.count()),
true);
mProgressDialog->setMinimumDuration(1000);
for (KMMsgBase *mb = mMsgList.first(); mb; mb = mMsgList.next())
{
// check if all messages are complete
int idx = mFolder->find(mb);
if (idx < 0) continue;
KMMessage *thisMsg = mFolder->getMsg(idx);
if (!thisMsg) continue;
if (thisMsg->parent() && thisMsg->parent()->protocol() == "imap" &&
!thisMsg->isComplete() && !mProgressDialog->wasCancelled())
{
qDebug( "2" );
// the message needs to be transferred first
complete = false;
KMAsyncCommand::mCountJobs++;
KMImapJob *imapJob = new KMImapJob(thisMsg);
// emitted when the message was transferred successfully
connect(imapJob, SIGNAL(messageRetrieved(KMMessage*)),
this, SLOT(slotMsgTransfered(KMMessage*)));
// emitted when the job is destroyed
connect(imapJob, SIGNAL(finished()),
this, SLOT(slotJobFinished()));
// msg musn't be deleted
thisMsg->setTransferInProgress(true);
} else {
mRetrievedMsgs.append(thisMsg);
}
}
if (complete)
{
qDebug( "1" );
delete mProgressDialog;
emit messagesTransfered(true);
} else {
// wait for the transfer and tell the progressBar the necessary steps
connect(mProgressDialog, SIGNAL(cancelClicked()),
this, SLOT(slotTransferCancelled()));
mProgressDialog->progressBar()->setTotalSteps(KMAsyncCommand::mCountJobs);
}
}
void KMAsyncCommand::slotMsgTransfered(KMMessage* msg)
{
msg->setTransferInProgress(false);
if (mProgressDialog->wasCancelled()) {
emit messagesTransfered(false);
return;
}
// save the complete messages
mRetrievedMsgs.append(msg);
}
void KMAsyncCommand::slotJobFinished()
{
// the job is finished (with / without error)
KMAsyncCommand::mCountJobs--;
if (mProgressDialog->wasCancelled()) return;
if ( (mCountMsgs - static_cast<int>(mRetrievedMsgs.count())) > KMAsyncCommand::mCountJobs )
{
// the message wasn't retrieved before => error
mProgressDialog->hide();
slotTransferCancelled();
return;
}
// update the progressbar
mProgressDialog->progressBar()->advance(1);
mProgressDialog->setLabel(i18n("Please wait while the message is transferred",
"Please wait while the %n messages are transferred", KMAsyncCommand::mCountJobs));
if (KMAsyncCommand::mCountJobs == 0)
{
// all done
delete mProgressDialog;
emit messagesTransfered(true);
}
}
void KMAsyncCommand::slotTransferCancelled()
{
if (mFolder->protocol() != "imap") {
emit messagesTransfered(false);
return;
}
// kill the pending jobs
KMAcctImap* acct = static_cast<KMFolderImap*>(mFolder)->account();
if (acct)
{
acct->killAllJobs();
acct->setIdle(true);
}
KMAsyncCommand::mCountJobs = 0;
mCountMsgs = 0;
// unget the transfered messages
QPtrListIterator<KMMessage> it( mRetrievedMsgs );
KMMessage* msg;
while ( (msg = it.current()) != 0 )
{
++it;
int idx = mFolder->find(msg);
if (idx > 0) mFolder->unGetMsg(idx);
}
mRetrievedMsgs.clear();
// unget the selected messages
for (KMMsgBase *mb = mMsgList.first(); mb; mb = mMsgList.next())
{
if (mb->isMessage())
{
int idx = mFolder->find(mb);
if (idx > 0) mFolder->unGetMsg(idx);
}
}
emit messagesTransfered(false);
}
KMMailtoComposeCommand::KMMailtoComposeCommand( KURL url, KMMsgBase *msgBase )
:mUrl( url ), mMsgBase( msgBase )
{
}
void KMMailtoComposeCommand::execute()
{
KMComposeWin *win;
KMMessage *msg = new KMMessage;
#ifdef IDENTITY_UOIDs
uint id = 0;
#else
QString id = "";
#endif
if ( mMsgBase && mMsgBase->parent() )
id = mMsgBase->parent()->identity();
msg->initHeader(id);
msg->setCharset("utf-8");
msg->setTo(mUrl.path());
win = new KMComposeWin(msg, id);
win->setCharset("", TRUE);
win->show();
}
KMMailtoReplyCommand::KMMailtoReplyCommand( KMainWindow *parent, KURL url,
KMMsgBase *msgBase, QString selection )
:KMAsyncCommand( parent, msgBase ), mUrl( url ), mSelection( selection )
{
}
void KMMailtoReplyCommand::execute()
{
//TODO : consider factoring createReply into this method.
KMMessage *msg = retrievedMessage();
KMComposeWin *win;
KMMessage *rmsg = msg->createReply(FALSE, FALSE, mSelection );
rmsg->setTo(mUrl.path());
#ifdef IDENTITY_UOIDs
win = new KMComposeWin(rmsg, 0);
#else
win = new KMComposeWin(rmsg, QString::null);
#endif
win->setCharset(msg->codec()->mimeName(), TRUE);
win->setReplyFocus();
win->show();
}
KMMailtoForwardCommand::KMMailtoForwardCommand( KMainWindow *parent, KURL url,
KMMsgBase *msgBase )
:KMAsyncCommand( parent, msgBase ), mUrl( url )
{
}
void KMMailtoForwardCommand::execute()
{
//TODO : consider factoring createForward into this method.
KMMessage *msg = retrievedMessage();
KMComposeWin *win;
KMMessage *fmsg = msg->createForward();
fmsg->setTo(mUrl.path());
win = new KMComposeWin(fmsg);
win->setCharset(msg->codec()->mimeName(), TRUE);
win->show();
}
KMMailtoAddAddrBookCommand::KMMailtoAddAddrBookCommand( KURL url,
QWidget *parent )
:mUrl( url ), mParent( parent )
{
}
void KMMailtoAddAddrBookCommand::execute()
{
KMAddrBookExternal::addEmail(mUrl.path(), mParent );
}
KMMailtoOpenAddrBookCommand::KMMailtoOpenAddrBookCommand( KURL url,
QWidget *parent )
:mUrl( url ), mParent( parent )
{
}
void KMMailtoOpenAddrBookCommand::execute()
{
KMAddrBookExternal::openEmail(mUrl.path(), mParent );
}
KMUrlCopyCommand::KMUrlCopyCommand( KURL url, KMMainWin *mainWin )
:mUrl( url ), mMainWin( mainWin )
{
}
void KMUrlCopyCommand::execute()
{
QClipboard* clip = QApplication::clipboard();
if (mUrl.protocol() == "mailto") {
// put the url into the mouse selection and the clipboard
clip->setSelectionMode( true );
clip->setText( mUrl.path() );
clip->setSelectionMode( false );
clip->setText( mUrl.path() );
if (mMainWin)
mMainWin->statusMsg( i18n( "Address copied to clipboard." ));
} else {
// put the url into the mouse selection and the clipboard
clip->setSelectionMode( true );
clip->setText( mUrl.url() );
clip->setSelectionMode( false );
clip->setText( mUrl.url() );
if ( mMainWin )
mMainWin->statusMsg( i18n( "URL copied to clipboard." ));
}
}
KMUrlOpenCommand::KMUrlOpenCommand( KURL url, KMReaderWin *readerWin )
:mUrl( url ), mReaderWin( readerWin )
{
}
void KMUrlOpenCommand::execute()
{
if (mUrl.isEmpty()) return;
mReaderWin->slotUrlOpen( mUrl, KParts::URLArgs() );
}
KMUrlSaveCommand::KMUrlSaveCommand( KURL url, QWidget *parent )
:mUrl( url ), mParent( parent )
{
}
void KMUrlSaveCommand::execute()
{
if (mUrl.isEmpty()) return;
KURL saveUrl = KFileDialog::getSaveURL(mUrl.fileName(), QString::null,
mParent);
if (saveUrl.isEmpty()) return;
if (KIO::NetAccess::exists(saveUrl))
{
if (KMessageBox::warningContinueCancel(0,
i18n("File %1 exists.\nDo you want to replace it?")
.arg(saveUrl.prettyURL()), i18n("Save to File"), i18n("&Replace"))
!= KMessageBox::Continue)
return;
}
KIO::Job *job = KIO::file_copy(mUrl, saveUrl, -1, true);
connect(job, SIGNAL(result(KIO::Job*)), SLOT(slotUrlSaveResult(KIO::Job*)));
}
void KMUrlSaveCommand::slotUrlSaveResult( KIO::Job *job )
{
if (job->error()) job->showErrorDialog();
}
KMEditMsgCommand::KMEditMsgCommand( KMainWindow *parent, KMMsgBase *msgBase )
:KMAsyncCommand( parent, msgBase )
{
}
void KMEditMsgCommand::execute()
{
KMMessage *msg = retrievedMessage();
if (!msg || !msg->parent() ||
!kernel->folderIsDraftOrOutbox( msg->parent() ))
return;
msg->parent()->removeMsg(msg);
#if 0
// Useful?
mHeaders->setSelected(mHeaders->currentItem(), TRUE);
mHeaders->highlightMessage(mHeaders->currentItem(), true);
#endif
KMComposeWin *win = new KMComposeWin();
#if 0
// FIXME: Poor solution, won't work for multiple readerwins should use kmkernel as an observer
QObject::connect( win, SIGNAL( messageQueuedOrDrafted()),
this, SLOT( slotMessageQueuedOrDrafted()) );
#endif
win->setMsg(msg, FALSE, TRUE);
win->setFolder( msg->parent() );
win->show();
}
KMShowMsgSrcCommand::KMShowMsgSrcCommand( KMainWindow *parent,
KMMsgBase *msgBase, QTextCodec *codec, bool fixedFont )
:KMAsyncCommand( parent, msgBase ), mCodec( codec ), mFixedFont( fixedFont )
{
}
void KMShowMsgSrcCommand::execute()
{
//TODO: move KMMessage::viewSource to here
KMMessage *msg = retrievedMessage();
if (!mCodec) //this is Auto setting
{
QCString cset = msg->charset();
if (!cset.isEmpty())
mCodec = KMMsgBase::codecForName( cset );
}
msg->viewSource( i18n("Message as Plain Text"), mCodec,
mFixedFont );
}
KMSaveMsgCommand::KMSaveMsgCommand( KMainWindow *parent,
QPtrList<KMMsgBase> msgList, KMFolder *folder )
:KMAsyncCommand( parent, msgList, folder )
{
if (!msgList.getFirst())
return;
KMMsgBase *msgBase = msgList.getFirst();
QString subject = msgBase->subject();
while (subject.find(':') != -1)
subject = subject.mid(subject.find(':') + 1).stripWhiteSpace();
subject.replace(QRegExp(QChar(QDir::separator())), "_");
mUrl = KFileDialog::getSaveURL(subject, QString::null);
}
KURL KMSaveMsgCommand::url()
{
return mUrl;
}
void KMSaveMsgCommand::execute()
{
//TODO: Handle messages one by one
QPtrList<KMMessage> *msgList = retrievedMsgs();
QCString str;
for (KMMessage *msg = msgList->first(); msg; msg = msgList->next()) {
str += "From " + msg->fromEmail() + " " + msg->dateShortStr() + "\n";
str += msg->asString();
str += "\n";
}
QByteArray ba = str;
ba.resize(ba.size() - 1);
kernel->byteArrayToRemoteFile(ba, mUrl);
}
KMDeleteMsgCommand::KMDeleteMsgCommand( KMMsgBase *msgBase )
:mMsgBase( msgBase )
{
}
void KMDeleteMsgCommand::execute()
{
}
KMReplyToCommand::KMReplyToCommand( KMainWindow *parent, KMMsgBase *msgBase,
QString selection )
: KMAsyncCommand( parent, msgBase ), mSelection( selection )
{
}
void KMReplyToCommand::execute()
{
kernel->kbp()->busy();
KMMessage *msg = retrievedMessage();
KMMessage *reply = msg->createReply( FALSE, FALSE, mSelection );
KMComposeWin *win = new KMComposeWin( reply );
win->setCharset( msg->codec()->mimeName(), TRUE );
win->setReplyFocus();
win->show();
kernel->kbp()->idle();
}
KMReplyToAllCommand::KMReplyToAllCommand( KMainWindow *parent,
KMMsgBase *msgBase, QString selection )
:KMAsyncCommand( parent, msgBase ), mSelection( selection )
{
}
void KMReplyToAllCommand::execute()
{
kernel->kbp()->busy();
KMMessage *msg = retrievedMessage();
KMMessage *reply = msg->createReply( TRUE, FALSE, mSelection );
KMComposeWin *win = new KMComposeWin( reply );
win->setCharset( msg->codec()->mimeName(), TRUE );
win->setReplyFocus();
win->show();
kernel->kbp()->idle();
}
KMForwardCommand::KMForwardCommand( KMainWindow *parent,
QPtrList<KMMsgBase> msgList, KMFolder *folder )
: KMAsyncCommand( parent, msgList, folder ),
mParent( parent ), mFolder( folder )
{
}
void KMForwardCommand::execute()
{
KMComposeWin *win;
QPtrList<KMMessage> *msgList = retrievedMsgs();
if (msgList->count() >= 2) {
// ask if they want a mime digest forward
if (KMessageBox::questionYesNo(mParent, i18n("Forward selected messages as"
" a MIME digest?"))
== KMessageBox::Yes) {
// we default to the first identity to save prompting the user
// (the messages could have different identities)
uint id = 0;
KMMessage *fwdMsg = new KMMessage;
KMMessagePart *msgPart = new KMMessagePart;
QString msgPartText;
int msgCnt = 0; // incase there are some we can't forward for some reason
fwdMsg->initHeader(id);
fwdMsg->setAutomaticFields(true);
fwdMsg->mMsg->Headers().ContentType().CreateBoundary(1);
msgPartText = i18n("\nThis is a MIME digest forward. The content of the"
" message is contained in the attachment(s).\n\n\n"
"--\n");
// iterate through all the messages to be forwarded
for (KMMessage *msg = msgList->first(); msg; msg = msgList->next()) {
// set the identity
if (id == 0)
id = msg->headerField("X-KMail-Identity").stripWhiteSpace().toUInt();
// set the part header
msgPartText += "--";
msgPartText += fwdMsg->mMsg->Headers().ContentType().Boundary().c_str();
msgPartText += "\nContent-Type: MESSAGE/RFC822";
msgPartText += QString("; CHARSET=%1").arg(msg->charset());
msgPartText += "\n";
DwHeaders dwh;
dwh.MessageId().CreateDefault();
msgPartText += QString("Content-ID: %1\n").arg(dwh.MessageId().AsString().c_str());
msgPartText += QString("Content-Description: %1").arg(msg->subject());
if (!msg->subject().contains("(fwd)"))
msgPartText += " (fwd)";
msgPartText += "\n\n";
// set the part
msgPartText += msg->headerAsString();
msgPartText += "\n";
msgPartText += msg->body();
msgPartText += "\n"; // eot
msgCnt++;
fwdMsg->link(msg, KMMsgStatusForwarded);
}
QCString tmp;
msgPart->setTypeStr("MULTIPART");
tmp.sprintf( "Digest; boundary=\"%s\"",
fwdMsg->mMsg->Headers().ContentType().Boundary().c_str() );
msgPart->setSubtypeStr( tmp );
msgPart->setName("unnamed");
msgPart->setCte(DwMime::kCte7bit); // does it have to be 7bit?
msgPart->setContentDescription(QString("Digest of %1 messages.").arg(msgCnt));
// THIS HAS TO BE AFTER setCte()!!!!
msgPart->setBodyEncoded(QCString(msgPartText.ascii()));
kernel->kbp()->busy();
win = new KMComposeWin(fwdMsg, id);
win->addAttach(msgPart);
win->show();
kernel->kbp()->idle();
return;
} else { // NO MIME DIGEST, Multiple forward
uint id = 0;
QCString msgText = "";
QPtrList<KMMessage> linklist;
for (KMMessage *msg = msgList->first(); msg; msg = msgList->next()) {
// set the identity
if (id == 0)
id = msg->headerField("X-KMail-Identity").stripWhiteSpace().toUInt();
msgText += msg->createForwardBody();
linklist.append(msg);
}
KMMessage *fwdMsg = new KMMessage;
fwdMsg->initHeader(id);
fwdMsg->setAutomaticFields(true);
fwdMsg->setCharset("utf-8");
fwdMsg->setBody(msgText);
for (KMMessage *msg = linklist.first(); msg; msg = linklist.next())
fwdMsg->link(msg, KMMsgStatusForwarded);
kernel->kbp()->busy();
win = new KMComposeWin(fwdMsg, id);
win->setCharset("");
win->show();
kernel->kbp()->idle();
return;
}
}
// forward a single message at most.
KMMessage *msg = msgList->getFirst();
if (!msg || !msg->codec()) return;
kernel->kbp()->busy();
win = new KMComposeWin(msg->createForward());
win->setCharset(msg->codec()->mimeName(), TRUE);
win->show();
kernel->kbp()->idle();
}
KMForwardAttachedCommand::KMForwardAttachedCommand( KMainWindow *parent,
QPtrList<KMMsgBase> msgList, KMFolder *folder )
: KMAsyncCommand( parent, msgList, folder ), mFolder( folder )
{
}
void KMForwardAttachedCommand::execute()
{
QPtrList<KMMessage> *msgList = retrievedMsgs();
KMComposeWin *win;
uint id = 0;
KMMessage *fwdMsg = new KMMessage;
if (msgList->count() >= 2) {
// don't respect X-KMail-Identity headers because they might differ for
// the selected mails
id = mFolder->identity();
fwdMsg->initHeader(id);
}
else if (msgList->count() == 1) {
KMMessage *msg = msgList->getFirst();
fwdMsg->initFromMessage(msg);
}
fwdMsg->setAutomaticFields(true);
kernel->kbp()->busy();
win = new KMComposeWin(fwdMsg, id);
// iterate through all the messages to be forwarded
for (KMMessage *msg = msgList->first(); msg; msg = msgList->next()) {
// set the part
KMMessagePart *msgPart = new KMMessagePart;
msgPart->setTypeStr("message");
msgPart->setSubtypeStr("rfc822");
msgPart->setCharset(msg->charset());
msgPart->setName("forwarded message");
msgPart->setCte(DwMime::kCte8bit); // is 8bit O.K.?
msgPart->setContentDescription(msg->from()+": "+msg->subject());
// THIS HAS TO BE AFTER setCte()!!!!
msgPart->setBodyEncoded(msg->asString());
msgPart->setCharset("");
fwdMsg->link(msg, KMMsgStatusForwarded);
win->addAttach(msgPart);
}
win->show();
kernel->kbp()->idle();
}
KMRedirectCommand::KMRedirectCommand( KMainWindow *parent,
KMMsgBase *msgBase )
: KMAsyncCommand( parent, msgBase )
{
}
void KMRedirectCommand::execute()
{
//TODO: move KMMessage::createRedirect to here
KMComposeWin *win;
KMMessage *msg = retrievedMessage();
if (!msg || !msg->codec()) return;
kernel->kbp()->busy();
win = new KMComposeWin();
win->setMsg(msg->createRedirect(), FALSE);
win->setCharset(msg->codec()->mimeName());
win->show();
kernel->kbp()->idle();
}
KMBounceCommand::KMBounceCommand( KMainWindow *parent,
KMMsgBase *msgBase )
: KMAsyncCommand( parent, msgBase )
{
}
void KMBounceCommand::execute()
{
KMMessage *msg = retrievedMessage();
KMMessage *newMsg = msg->createBounce( TRUE /* with UI */);
if (newMsg)
kernel->msgSender()->send(newMsg, kernel->msgSender()->sendImmediate());
}
KMToggleFixedCommand::KMToggleFixedCommand( KMReaderWin *readerWin )
: KMAsyncCommand(), mReaderWin( readerWin )
{
}
void KMToggleFixedCommand::execute()
{
mReaderWin->slotToggleFixedFont();
}
KMPrintCommand::KMPrintCommand( KMainWindow *parent,
KMMsgBase *msgBase )
: KMAsyncCommand( parent, msgBase)
{
}
void KMPrintCommand::execute()
{
KMReaderWin printWin;
printWin.setPrinting(TRUE);
printWin.readConfig();
printWin.setMsg(retrievedMessage(), TRUE);
printWin.printMsg();
}
//TODO: Use serial numbers
KMSetStatusCommand::KMSetStatusCommand( KMMsgStatus status,
QValueList<int> ids, KMFolder *folder )
: mStatus( status ), mIds( ids ), mFolder( folder )
{
}
void KMSetStatusCommand::execute()
{
mFolder->setStatus( mIds, mStatus );
}
KMFilterCommand::KMFilterCommand( QCString field, QString value )
: mField( field ), mValue( value )
{
}
void KMFilterCommand::execute()
{
kernel->filterMgr()->createFilter( mField, mValue );
}
KMMailingListFilterCommand::KMMailingListFilterCommand( KMMainWin *win,
KMMsgBase *msgBase )
: KMAsyncCommand( win, msgBase )
{
}
void KMMailingListFilterCommand::execute()
{
QCString name;
QString value;
KMMessage *msg = retrievedMessage();
if (!msg)
return;
if (!KMMLInfo::name( msg, name, value ).isNull())
kernel->filterMgr()->createFilter( name, value );
}
_______________________________________________
KMail Developers mailing list
kmail@mail.kde.org
http://mail.kde.org/mailman/listinfo/kmail
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic