00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "kmcommands.h"
00044
00045 #include <unistd.h>
00046 #include <errno.h>
00047 #include <mimelib/enum.h>
00048 #include <mimelib/field.h>
00049 #include <mimelib/mimepp.h>
00050 #include <mimelib/string.h>
00051
00052
00053 #include <QMenu>
00054 #include <QByteArray>
00055 #include <kprogressdialog.h>
00056
00057 #include <QApplication>
00058 #include <QDesktopWidget>
00059 #include <QList>
00060 #include <QTextCodec>
00061 #include <QProgressBar>
00062
00063 #include <kpimutils/email.h>
00064 #include <kdbusservicestarter.h>
00065 #include <kdebug.h>
00066 #include <kfiledialog.h>
00067 #include <kabc/stdaddressbook.h>
00068 #include <kabc/addresseelist.h>
00069 #include <klocale.h>
00070 #include <kmessagebox.h>
00071 #include <kmimetypetrader.h>
00072 #include <kparts/browserextension.h>
00073 #include <krun.h>
00074 #include <kbookmarkmanager.h>
00075 #include <kstandarddirs.h>
00076 #include <ktemporaryfile.h>
00077
00078 #include <kio/job.h>
00079 #include <kio/jobuidelegate.h>
00080 #include <kio/netaccess.h>
00081
00082 #include <kpimidentities/identitymanager.h>
00083
00084 #include "actionscheduler.h"
00085 using KMail::ActionScheduler;
00086 #include "mailinglist-magic.h"
00087 #include "kmaddrbook.h"
00088 #include <kaddrbookexternal.h>
00089 #include "composer.h"
00090 #include "kmfiltermgr.h"
00091 #include "kmfoldermbox.h"
00092 #include "kmfolderimap.h"
00093 #include "kmfoldermgr.h"
00094 #include "kmheaders.h"
00095 #include "headeritem.h"
00096 #include "kmmainwidget.h"
00097 #include "kmmsgdict.h"
00098 #include "messagesender.h"
00099 #include "kmmsgpartdlg.h"
00100 #include "undostack.h"
00101 #include "kcursorsaver.h"
00102 #include "partNode.h"
00103 #include "objecttreeparser.h"
00104 using KMail::ObjectTreeParser;
00105 using KMail::FolderJob;
00106 #include "chiasmuskeyselector.h"
00107 #include "mailsourceviewer.h"
00108 using KMail::MailSourceViewer;
00109 #include "kmreadermainwin.h"
00110 #include "secondarywindow.h"
00111 using KMail::SecondaryWindow;
00112 #include "redirectdialog.h"
00113 using KMail::RedirectDialog;
00114 #include "util.h"
00115 #include "templateparser.h"
00116 using KMail::TemplateParser;
00117 #include "editorwatcher.h"
00118 #include "korghelper.h"
00119
00120 #include "broadcaststatus.h"
00121 #include "globalsettings.h"
00122
00123 #include <kpimutils/kfileio.h>
00124 #include "calendarinterface.h"
00125 #include "interfaces/htmlwriter.h"
00126
00127 #include "progressmanager.h"
00128 using KPIM::ProgressManager;
00129 using KPIM::ProgressItem;
00130 #include <kmime/kmime_mdn.h>
00131 using namespace KMime;
00132
00133 #include "kleo/specialjob.h"
00134 #include "kleo/cryptobackend.h"
00135 #include "kleo/cryptobackendfactory.h"
00136
00137 #include <gpgme++/error.h>
00138
00139 #include <QClipboard>
00140 #include <QDBusMessage>
00141 #include <QDBusConnection>
00142
00143 #include <memory>
00144
00145 class LaterDeleterWithCommandCompletion : public KMail::Util::LaterDeleter
00146 {
00147 public:
00148 LaterDeleterWithCommandCompletion( KMCommand* command )
00149 :LaterDeleter( command ), m_result( KMCommand::Failed )
00150 {
00151 }
00152 ~LaterDeleterWithCommandCompletion()
00153 {
00154 setResult( m_result );
00155 KMCommand *command = static_cast<KMCommand*>( m_object );
00156 emit command->completed( command );
00157 }
00158 void setResult( KMCommand::Result v ) { m_result = v; }
00159 private:
00160 KMCommand::Result m_result;
00161 };
00162
00163
00164 KMCommand::KMCommand( QWidget *parent )
00165 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00166 mEmitsCompletedItself( false ), mParent( parent )
00167 {
00168 }
00169
00170 KMCommand::KMCommand( QWidget *parent, const QList<KMMsgBase*> &msgList )
00171 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00172 mEmitsCompletedItself( false ), mParent( parent ), mMsgList( msgList )
00173 {
00174 }
00175
00176 KMCommand::KMCommand( QWidget *parent, KMMsgBase *msgBase )
00177 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00178 mEmitsCompletedItself( false ), mParent( parent )
00179 {
00180 mMsgList.append( msgBase );
00181 }
00182
00183 KMCommand::KMCommand( QWidget *parent, KMMessage *msg )
00184 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00185 mEmitsCompletedItself( false ), mParent( parent )
00186 {
00187 if ( msg ) {
00188 mMsgList.append( &msg->toMsgBase() );
00189 }
00190 }
00191
00192 KMCommand::~KMCommand()
00193 {
00194 QList<QPointer<KMFolder> >::Iterator fit;
00195 for ( fit = mFolders.begin(); fit != mFolders.end(); ++fit ) {
00196 if ( !(*fit) ) {
00197 continue;
00198 }
00199 (*fit)->close( "kmcommand" );
00200 }
00201 }
00202
00203 KMCommand::Result KMCommand::result() const
00204 {
00205 if ( mResult == Undefined ) {
00206 kDebug(5006) <<"mResult is Undefined";
00207 }
00208 return mResult;
00209 }
00210
00211 void KMCommand::start()
00212 {
00213 QTimer::singleShot( 0, this, SLOT( slotStart() ) );
00214 }
00215
00216
00217 const QList<KMMessage*> KMCommand::retrievedMsgs() const
00218 {
00219 return mRetrievedMsgs;
00220 }
00221
00222 KMMessage *KMCommand::retrievedMessage() const
00223 {
00224 return *(mRetrievedMsgs.begin());
00225 }
00226
00227 QWidget *KMCommand::parentWidget() const
00228 {
00229 return mParent;
00230 }
00231
00232 int KMCommand::mCountJobs = 0;
00233
00234 void KMCommand::slotStart()
00235 {
00236 connect( this, SIGNAL( messagesTransfered( KMCommand::Result ) ),
00237 this, SLOT( slotPostTransfer( KMCommand::Result ) ) );
00238 kmkernel->filterMgr()->ref();
00239
00240 if ( mMsgList.contains(0) ) {
00241 emit messagesTransfered( Failed );
00242 return;
00243 }
00244
00245 KMMsgBase *mb = *(mMsgList.begin());
00246 if ( (mMsgList.count() == 1) && ( mb->isMessage() ) &&
00247 ( mb->parent() == 0 ) )
00248 {
00249
00250 mRetrievedMsgs.append((KMMessage*)mMsgList.takeFirst());
00251 emit messagesTransfered( OK );
00252 return;
00253 }
00254
00255 QList<KMMsgBase*>::const_iterator it;
00256 for ( it = mMsgList.begin(); it != mMsgList.end(); ++it )
00257 if ( !( (*it)->parent() ) ) {
00258 emit messagesTransfered( Failed );
00259 return;
00260 } else {
00261 keepFolderOpen( (*it)->parent() );
00262 }
00263
00264
00265 transferSelectedMsgs();
00266 }
00267
00268 void KMCommand::slotPostTransfer( KMCommand::Result result )
00269 {
00270 disconnect( this, SIGNAL( messagesTransfered( KMCommand::Result ) ),
00271 this, SLOT( slotPostTransfer( KMCommand::Result ) ) );
00272 if ( result == OK )
00273 result = execute();
00274 mResult = result;
00275 KMMessage* msg;
00276 foreach( msg, mRetrievedMsgs ) {
00277 if ( msg && msg->parent() )
00278 msg->setTransferInProgress(false);
00279 }
00280 kmkernel->filterMgr()->deref();
00281 if ( !emitsCompletedItself() )
00282 emit completed( this );
00283 if ( !deletesItself() )
00284 deleteLater();
00285 }
00286
00287 void KMCommand::transferSelectedMsgs()
00288 {
00289
00290 if (KMCommand::mCountJobs > 0) {
00291 emit messagesTransfered( Failed );
00292 return;
00293 }
00294
00295 bool complete = true;
00296 KMCommand::mCountJobs = 0;
00297 mCountMsgs = 0;
00298 mRetrievedMsgs.clear();
00299 mCountMsgs = mMsgList.count();
00300 uint totalSize = 0;
00301
00302
00303
00304
00305 if ( mCountMsgs > 0 ) {
00306 mProgressDialog = new KProgressDialog(mParent,
00307 i18n("Please wait"),
00308 i18np("Please wait while the message is transferred",
00309 "Please wait while the %1 messages are transferred", mMsgList.count()));
00310 mProgressDialog->setModal(true);
00311 mProgressDialog->setMinimumDuration(1000);
00312 }
00313 QList<KMMsgBase*>::const_iterator it;
00314 for ( it = mMsgList.begin(); it != mMsgList.end(); ++it )
00315 {
00316 KMMsgBase *mb = (*it);
00317
00318 KMMessage *thisMsg = 0;
00319 if ( mb->isMessage() )
00320 thisMsg = static_cast<KMMessage*>(mb);
00321 else
00322 {
00323 KMFolder *folder = mb->parent();
00324 int idx = folder->find(mb);
00325 if (idx < 0) continue;
00326 thisMsg = folder->getMsg(idx);
00327 }
00328 if (!thisMsg) continue;
00329 if ( thisMsg->transferInProgress() &&
00330 thisMsg->parent()->folderType() == KMFolderTypeImap )
00331 {
00332 thisMsg->setTransferInProgress( false, true );
00333 thisMsg->parent()->ignoreJobsForMessage( thisMsg );
00334 }
00335
00336 if ( thisMsg->parent() && !thisMsg->isComplete() &&
00337 ( !mProgressDialog || !mProgressDialog->wasCancelled() ) )
00338 {
00339 kDebug(5006)<<"### INCOMPLETE";
00340
00341 complete = false;
00342 KMCommand::mCountJobs++;
00343 FolderJob *job = thisMsg->parent()->createJob(thisMsg);
00344 job->setCancellable( false );
00345 totalSize += thisMsg->msgSizeServer();
00346
00347 connect(job, SIGNAL(messageRetrieved(KMMessage*)),
00348 this, SLOT(slotMsgTransfered(KMMessage*)));
00349
00350 connect(job, SIGNAL(finished()),
00351 this, SLOT(slotJobFinished()));
00352 connect(job, SIGNAL(progress(unsigned long, unsigned long)),
00353 this, SLOT(slotProgress(unsigned long, unsigned long)));
00354
00355 thisMsg->setTransferInProgress(true);
00356 job->start();
00357 } else {
00358 thisMsg->setTransferInProgress(true);
00359 mRetrievedMsgs.append(thisMsg);
00360 }
00361 }
00362
00363 if (complete)
00364 {
00365 delete mProgressDialog;
00366 mProgressDialog = 0;
00367 emit messagesTransfered( OK );
00368 } else {
00369
00370 if ( mProgressDialog ) {
00371 connect(mProgressDialog, SIGNAL(cancelClicked()),
00372 this, SLOT(slotTransferCancelled()));
00373 mProgressDialog->progressBar()->setMaximum(totalSize);
00374 }
00375 }
00376 }
00377
00378 void KMCommand::slotMsgTransfered(KMMessage* msg)
00379 {
00380 if ( mProgressDialog && mProgressDialog->wasCancelled() ) {
00381 emit messagesTransfered( Canceled );
00382 return;
00383 }
00384
00385
00386 mRetrievedMsgs.append(msg);
00387 }
00388
00389 void KMCommand::slotProgress( unsigned long done, unsigned long )
00390 {
00391 mProgressDialog->progressBar()->setValue( done );
00392 }
00393
00394 void KMCommand::slotJobFinished()
00395 {
00396
00397 KMCommand::mCountJobs--;
00398
00399 if ( mProgressDialog && mProgressDialog->wasCancelled() ) return;
00400
00401 if ( (mCountMsgs - static_cast<int>(mRetrievedMsgs.count())) > KMCommand::mCountJobs )
00402 {
00403
00404 if ( mProgressDialog )
00405 mProgressDialog->hide();
00406 slotTransferCancelled();
00407 return;
00408 }
00409
00410 if ( mProgressDialog ) {
00411 mProgressDialog->setLabelText(i18np("Please wait while the message is transferred",
00412 "Please wait while the %1 messages are transferred", KMCommand::mCountJobs));
00413 }
00414 if (KMCommand::mCountJobs == 0)
00415 {
00416
00417 delete mProgressDialog;
00418 mProgressDialog = 0;
00419 emit messagesTransfered( OK );
00420 }
00421 }
00422
00423 void KMCommand::slotTransferCancelled()
00424 {
00425
00426 QList<QPointer<KMFolder> >::Iterator fit;
00427 for ( fit = mFolders.begin(); fit != mFolders.end(); ++fit ) {
00428 if (!(*fit))
00429 continue;
00430 KMFolder *folder = *fit;
00431 KMFolderImap *imapFolder = dynamic_cast<KMFolderImap*>(folder);
00432 if (imapFolder && imapFolder->account()) {
00433 imapFolder->account()->killAllJobs();
00434 }
00435 }
00436
00437 KMCommand::mCountJobs = 0;
00438 mCountMsgs = 0;
00439
00440 QList<KMMessage*>::const_iterator it;
00441 for ( it = mRetrievedMsgs.constBegin(); it != mRetrievedMsgs.constEnd(); ++it ) {
00442 KMMessage* msg = (*it);
00443 KMFolder *folder = msg->parent();
00444 ++it;
00445 if (!folder)
00446 continue;
00447 msg->setTransferInProgress(false);
00448 int idx = folder->find(msg);
00449 if (idx > 0) folder->unGetMsg(idx);
00450 }
00451 mRetrievedMsgs.clear();
00452 emit messagesTransfered( Canceled );
00453 }
00454
00455 void KMCommand::keepFolderOpen( KMFolder *folder )
00456 {
00457 folder->open( "kmcommand" );
00458 mFolders.append( folder );
00459 }
00460
00461 KMMailtoComposeCommand::KMMailtoComposeCommand( const KUrl &url,
00462 KMMessage *msg )
00463 :mUrl( url ), mMessage( msg )
00464 {
00465 }
00466
00467 KMCommand::Result KMMailtoComposeCommand::execute()
00468 {
00469 KMMessage *msg = new KMMessage;
00470 uint id = 0;
00471
00472 if ( mMessage && mMessage->parent() )
00473 id = mMessage->parent()->identity();
00474
00475 msg->initHeader(id);
00476 msg->setCharset("utf-8");
00477 msg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00478
00479 KMail::Composer * win = KMail::makeComposer( msg, id );
00480 win->setCharset("", true);
00481 win->setFocusToSubject();
00482 win->show();
00483
00484 return OK;
00485 }
00486
00487
00488 KMMailtoReplyCommand::KMMailtoReplyCommand( QWidget *parent,
00489 const KUrl &url, KMMessage *msg, const QString &selection )
00490 :KMCommand( parent, msg ), mUrl( url ), mSelection( selection )
00491 {
00492 }
00493
00494 KMCommand::Result KMMailtoReplyCommand::execute()
00495 {
00496
00497 KMMessage *msg = retrievedMessage();
00498 if ( !msg || !msg->codec() ) {
00499 return Failed;
00500 }
00501 KMMessage *rmsg = msg->createReply( KMail::ReplyNone, mSelection );
00502 rmsg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00503
00504 KMail::Composer * win = KMail::makeComposer( rmsg, 0 );
00505 win->setCharset( msg->codec()->name(), true );
00506 win->setReplyFocus();
00507 win->show();
00508
00509 return OK;
00510 }
00511
00512
00513 KMMailtoForwardCommand::KMMailtoForwardCommand( QWidget *parent,
00514 const KUrl &url, KMMessage *msg )
00515 :KMCommand( parent, msg ), mUrl( url )
00516 {
00517 }
00518
00519 KMCommand::Result KMMailtoForwardCommand::execute()
00520 {
00521
00522 KMMessage *msg = retrievedMessage();
00523 if ( !msg || !msg->codec() ) {
00524 return Failed;
00525 }
00526 KMMessage *fmsg = msg->createForward();
00527 fmsg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00528
00529 KMail::Composer * win = KMail::makeComposer( fmsg );
00530 win->setCharset( msg->codec()->name(), true );
00531 win->show();
00532
00533 return OK;
00534 }
00535
00536
00537 KMAddBookmarksCommand::KMAddBookmarksCommand( const KUrl &url, QWidget *parent )
00538 : KMCommand( parent ), mUrl( url )
00539 {
00540 }
00541
00542 KMCommand::Result KMAddBookmarksCommand::execute()
00543 {
00544 QString filename = KStandardDirs::locateLocal( "data", QString::fromLatin1("konqueror/bookmarks.xml") );
00545 KBookmarkManager *bookManager = KBookmarkManager::managerForFile( filename, "konqueror" );
00546 KBookmarkGroup group = bookManager->root();
00547 group.addBookmark( mUrl.path(), KUrl( mUrl ) );
00548 if( bookManager->save() ) {
00549 bookManager->emitChanged( group );
00550 }
00551
00552 return OK;
00553 }
00554
00555 KMMailtoAddAddrBookCommand::KMMailtoAddAddrBookCommand( const KUrl &url,
00556 QWidget *parent )
00557 : KMCommand( parent ), mUrl( url )
00558 {
00559 }
00560
00561 KMCommand::Result KMMailtoAddAddrBookCommand::execute()
00562 {
00563 KPIM::KAddrBookExternal::addEmail( KMMessage::decodeMailtoUrl( mUrl.path() ),
00564 parentWidget() );
00565
00566 return OK;
00567 }
00568
00569
00570 KMMailtoOpenAddrBookCommand::KMMailtoOpenAddrBookCommand( const KUrl &url,
00571 QWidget *parent )
00572 : KMCommand( parent ), mUrl( url )
00573 {
00574 }
00575
00576 KMCommand::Result KMMailtoOpenAddrBookCommand::execute()
00577 {
00578 QString addr = KMMessage::decodeMailtoUrl( mUrl.path() );
00579 KPIM::KAddrBookExternal::openEmail( KPIMUtils::extractEmailAddress(addr),
00580 addr, parentWidget() );
00581
00582 return OK;
00583 }
00584
00585
00586 KMUrlCopyCommand::KMUrlCopyCommand( const KUrl &url, KMMainWidget *mainWidget )
00587 :mUrl( url ), mMainWidget( mainWidget )
00588 {
00589 }
00590
00591 KMCommand::Result KMUrlCopyCommand::execute()
00592 {
00593 QClipboard* clip = QApplication::clipboard();
00594
00595 if (mUrl.protocol() == "mailto") {
00596
00597 QString address = KMMessage::decodeMailtoUrl( mUrl.path() );
00598 clip->setText( address, QClipboard::Clipboard );
00599 clip->setText( address, QClipboard::Selection );
00600 KPIM::BroadcastStatus::instance()->setStatusMsg( i18n( "Address copied to clipboard." ));
00601 } else {
00602
00603 clip->setText( mUrl.url(), QClipboard::Clipboard );
00604 clip->setText( mUrl.url(), QClipboard::Selection );
00605 KPIM::BroadcastStatus::instance()->setStatusMsg( i18n( "URL copied to clipboard." ));
00606 }
00607
00608 return OK;
00609 }
00610
00611
00612 KMUrlOpenCommand::KMUrlOpenCommand( const KUrl &url, KMReaderWin *readerWin )
00613 :mUrl( url ), mReaderWin( readerWin )
00614 {
00615 }
00616
00617 KMCommand::Result KMUrlOpenCommand::execute()
00618 {
00619 if ( !mUrl.isEmpty() )
00620 mReaderWin->slotUrlOpen( mUrl, KParts::OpenUrlArguments(), KParts::BrowserArguments() );
00621
00622 return OK;
00623 }
00624
00625
00626 KMUrlSaveCommand::KMUrlSaveCommand( const KUrl &url, QWidget *parent )
00627 : KMCommand( parent ), mUrl( url )
00628 {
00629 }
00630
00631 KMCommand::Result KMUrlSaveCommand::execute()
00632 {
00633 if ( mUrl.isEmpty() )
00634 return OK;
00635 KUrl saveUrl = KFileDialog::getSaveUrl(mUrl.fileName(), QString(),
00636 parentWidget() );
00637 if ( saveUrl.isEmpty() )
00638 return Canceled;
00639 if ( KIO::NetAccess::exists( saveUrl, KIO::NetAccess::DestinationSide, parentWidget() ) )
00640 {
00641 if (KMessageBox::warningContinueCancel(0,
00642 i18nc("@info", "File <filename>%1</filename> exists.<nl/>Do you want to replace it?",
00643 saveUrl.pathOrUrl()), i18n("Save to File"), KGuiItem(i18n("&Replace")))
00644 != KMessageBox::Continue)
00645 return Canceled;
00646 }
00647 KIO::Job *job = KIO::file_copy(mUrl, saveUrl, -1, KIO::Overwrite);
00648 connect(job, SIGNAL(result(KJob*)), SLOT(slotUrlSaveResult(KJob*)));
00649 setEmitsCompletedItself( true );
00650 return OK;
00651 }
00652
00653 void KMUrlSaveCommand::slotUrlSaveResult( KJob *job )
00654 {
00655 if ( job->error() ) {
00656 static_cast<KIO::Job*>(job)->ui()->showErrorMessage();
00657 setResult( Failed );
00658 emit completed( this );
00659 }
00660 else {
00661 setResult( OK );
00662 emit completed( this );
00663 }
00664 }
00665
00666
00667 KMEditMsgCommand::KMEditMsgCommand( QWidget *parent, KMMessage *msg )
00668 :KMCommand( parent, msg )
00669 {
00670 }
00671
00672 KMCommand::Result KMEditMsgCommand::execute()
00673 {
00674 KMMessage *msg = retrievedMessage();
00675 if (!msg || !msg->parent() ||
00676 ( !kmkernel->folderIsDraftOrOutbox( msg->parent() ) &&
00677 !kmkernel->folderIsTemplates( msg->parent() ) ) ) {
00678 return Failed;
00679 }
00680
00681
00682
00683
00684 KMFolder *parent = msg->parent();
00685 if ( parent ) {
00686 parent->take( parent->find( msg ) );
00687 }
00688
00689 KMail::Composer *win = KMail::makeComposer();
00690 msg->setTransferInProgress( false );
00691 win->setMsg( msg, false, true );
00692 win->setFolder( parent );
00693 win->show();
00694
00695 return OK;
00696 }
00697
00698 KMUseTemplateCommand::KMUseTemplateCommand( QWidget *parent, KMMessage *msg )
00699 :KMCommand( parent, msg )
00700 {
00701 }
00702
00703 KMCommand::Result KMUseTemplateCommand::execute()
00704 {
00705 KMMessage *msg = retrievedMessage();
00706 if ( !msg || !msg->parent() ||
00707 !kmkernel->folderIsTemplates( msg->parent() ) ) {
00708 return Failed;
00709 }
00710
00711
00712 KMMessage *newMsg = new KMMessage( new DwMessage( *msg->asDwMessage() ) );
00713 newMsg->setComplete( msg->isComplete() );
00714
00715
00716 newMsg->removeHeaderField("Date");
00717 newMsg->removeHeaderField("Message-ID");
00718
00719 KMail::Composer *win = KMail::makeComposer();
00720 newMsg->setTransferInProgress( false );
00721 win->setMsg( newMsg, false, true );
00722 win->show();
00723
00724 return OK;
00725 }
00726
00727 KMShowMsgSrcCommand::KMShowMsgSrcCommand( QWidget *parent,
00728 KMMessage *msg, bool fixedFont )
00729 :KMCommand( parent, msg ), mFixedFont( fixedFont )
00730 {
00731
00732 mMsgWasComplete = msg->isComplete();
00733 }
00734
00735 KMCommand::Result KMShowMsgSrcCommand::execute()
00736 {
00737 KMMessage *msg = retrievedMessage();
00738 if ( !msg ) {
00739 return Failed;
00740 }
00741 if ( msg->isComplete() && !mMsgWasComplete ) {
00742 msg->notify();
00743 }
00744 QString str = msg->codec()->toUnicode( msg->asString() );
00745
00746 MailSourceViewer *viewer = new MailSourceViewer();
00747 viewer->setWindowTitle( i18n("Message as Plain Text") );
00748 viewer->setText( str );
00749 if( mFixedFont ) {
00750 viewer->setFont( KGlobalSettings::fixedFont() );
00751 }
00752
00753
00754
00755
00756 if ( QApplication::desktop()->isVirtualDesktop() ) {
00757 int scnum = QApplication::desktop()->screenNumber( QCursor::pos() );
00758 viewer->resize( QApplication::desktop()->screenGeometry( scnum ).width()/2,
00759 2 * QApplication::desktop()->screenGeometry( scnum ).height()/3);
00760 } else {
00761 viewer->resize( QApplication::desktop()->geometry().width()/2,
00762 2 * QApplication::desktop()->geometry().height()/3);
00763 }
00764 viewer->show();
00765
00766 return OK;
00767 }
00768
00769 static KUrl subjectToUrl( const QString &subject ) {
00770
00771 return KFileDialog::getSaveUrl( KUrl::fromPath( subject.trimmed()
00772 .replace( QDir::separator(), '_' ) ),
00773 "*.mbox" );
00774 }
00775
00776 KMSaveMsgCommand::KMSaveMsgCommand( QWidget *parent, KMMessage *msg )
00777 : KMCommand( parent ),
00778 mMsgListIndex( 0 ),
00779 mStandAloneMessage( 0 ),
00780 mOffset( 0 ),
00781 mTotalSize( msg ? msg->msgSize() : 0 )
00782 {
00783 if ( !msg ) {
00784 return;
00785 }
00786 setDeletesItself( true );
00787
00788
00789
00790
00791 if ( msg->getMsgSerNum() != 0 ) {
00792 mMsgList.append( msg->getMsgSerNum() );
00793 } else {
00794 mStandAloneMessage = msg;
00795 }
00796 mUrl = subjectToUrl( msg->cleanSubject() );
00797 }
00798
00799 KMSaveMsgCommand::KMSaveMsgCommand( QWidget *parent,
00800 const QList<KMMsgBase*> &msgList )
00801 : KMCommand( parent ),
00802 mMsgListIndex( 0 ),
00803 mStandAloneMessage( 0 ),
00804 mOffset( 0 ),
00805 mTotalSize( 0 )
00806 {
00807 if ( msgList.empty() ) {
00808 return;
00809 }
00810 setDeletesItself( true );
00811
00812
00813
00814 QList<KMMsgBase*>::const_iterator it;
00815 for ( it = msgList.begin(); it != msgList.end(); ++it ) {
00816 mMsgList.append( (*it)->getMsgSerNum() );
00817 mTotalSize += (*it)->msgSize();
00818 if ( (*it)->parent() != 0 ) {
00819 (*it)->parent()->open( "kmcommand" );
00820 }
00821 }
00822 mMsgListIndex = 0;
00823 KMMsgBase *msgBase = *(msgList.begin());
00824 mUrl = subjectToUrl( msgBase->cleanSubject() );
00825 }
00826
00827 KUrl KMSaveMsgCommand::url()
00828 {
00829 return mUrl;
00830 }
00831
00832 KMCommand::Result KMSaveMsgCommand::execute()
00833 {
00834 mJob = KIO::put( mUrl, S_IRUSR|S_IWUSR );
00835 #ifdef __GNUC__
00836 #warning Port me!
00837 #endif
00838
00839 mJob->setAsyncDataEnabled( true );
00840 mJob->setReportDataSent( true );
00841 connect(mJob, SIGNAL(dataReq(KIO::Job*, QByteArray &)),
00842 SLOT(slotSaveDataReq()));
00843 connect(mJob, SIGNAL(result(KJob*)),
00844 SLOT(slotSaveResult(KJob*)));
00845 setEmitsCompletedItself( true );
00846 return OK;
00847 }
00848
00849 void KMSaveMsgCommand::slotSaveDataReq()
00850 {
00851 int remainingBytes = mData.size() - mOffset;
00852 if ( remainingBytes > 0 ) {
00853
00854 if ( remainingBytes > MAX_CHUNK_SIZE )
00855 remainingBytes = MAX_CHUNK_SIZE;
00856
00857 QByteArray data;
00858 data = QByteArray( mData.data() + mOffset, remainingBytes );
00859 mJob->sendAsyncData( data );
00860 mOffset += remainingBytes;
00861 return;
00862 }
00863
00864 if ( mMsgListIndex < static_cast<unsigned int>( mMsgList.size() ) ) {
00865 KMMessage *msg = 0;
00866 int idx = -1;
00867 KMFolder * p = 0;
00868 KMMsgDict::instance()->getLocation( mMsgList[mMsgListIndex], &p, &idx );
00869 assert( p );
00870 assert( idx >= 0 );
00871 msg = p->getMsg(idx);
00872
00873 if ( msg ) {
00874 if ( msg->transferInProgress() ) {
00875 QByteArray data = QByteArray();
00876 mJob->sendAsyncData( data );
00877 }
00878 msg->setTransferInProgress( true );
00879 if ( msg->isComplete() ) {
00880 slotMessageRetrievedForSaving( msg );
00881 } else {
00882
00883 if ( msg->parent() && !msg->isComplete() ) {
00884 FolderJob *job = msg->parent()->createJob( msg );
00885 job->setCancellable( false );
00886 connect(job, SIGNAL( messageRetrieved( KMMessage* ) ),
00887 this, SLOT( slotMessageRetrievedForSaving( KMMessage* ) ) );
00888 job->start();
00889 }
00890 }
00891 } else {
00892 mJob->slotError( KIO::ERR_ABORTED,
00893 i18n("The message was removed while saving it. "
00894 "It has not been saved.") );
00895 }
00896 } else {
00897 if ( mStandAloneMessage ) {
00898
00899 slotMessageRetrievedForSaving( mStandAloneMessage );
00900 mStandAloneMessage = 0;
00901 } else {
00902
00903 QByteArray data = QByteArray();
00904 mJob->sendAsyncData( data );
00905 }
00906 }
00907 }
00908
00909 void KMSaveMsgCommand::slotMessageRetrievedForSaving(KMMessage *msg)
00910 {
00911 if ( msg ) {
00912 QByteArray str( msg->mboxMessageSeparator() );
00913 str += KMFolderMbox::escapeFrom( msg->asDwString() );
00914 str += '\n';
00915 msg->setTransferInProgress(false);
00916
00917 mData = str;
00918 mData.resize(mData.size() - 1);
00919 mOffset = 0;
00920 QByteArray data;
00921 int size;
00922
00923 if( mData.size() > MAX_CHUNK_SIZE )
00924 size = MAX_CHUNK_SIZE;
00925 else
00926 size = mData.size();
00927
00928 data = QByteArray( mData, size );
00929 mJob->sendAsyncData( data );
00930 mOffset += size;
00931 }
00932 ++mMsgListIndex;
00933
00934 if ( msg && msg->parent() && msg->getMsgSerNum() ) {
00935 int idx = -1;
00936 KMFolder * p = 0;
00937 KMMsgDict::instance()->getLocation( msg, &p, &idx );
00938 assert( p == msg->parent() ); assert( idx >= 0 );
00939 p->unGetMsg( idx );
00940 p->close( "kmcommand" );
00941 }
00942 }
00943
00944 void KMSaveMsgCommand::slotSaveResult(KJob *job)
00945 {
00946 if (job->error())
00947 {
00948 if (job->error() == KIO::ERR_FILE_ALREADY_EXIST)
00949 {
00950 if (KMessageBox::warningContinueCancel(0,
00951 i18n("File %1 exists.\nDo you want to replace it?",
00952 mUrl.prettyUrl()), i18n("Save to File"), KGuiItem(i18n("&Replace")))
00953 == KMessageBox::Continue) {
00954 mOffset = 0;
00955
00956 mJob = KIO::put( mUrl, S_IRUSR|S_IWUSR, KIO::Overwrite );
00957 #ifdef __GNUC__
00958 #warning Port me!
00959 #endif
00960
00961 mJob->setAsyncDataEnabled( true );
00962 mJob->setReportDataSent( true );
00963 connect(mJob, SIGNAL(dataReq(KIO::Job*, QByteArray &)),
00964 SLOT(slotSaveDataReq()));
00965 connect(mJob, SIGNAL(result(KJob*)),
00966 SLOT(slotSaveResult(KJob*)));
00967 }
00968 }
00969 else
00970 {
00971 static_cast<KIO::Job*>(job)->ui()->showErrorMessage();
00972 setResult( Failed );
00973 emit completed( this );
00974 deleteLater();
00975 }
00976 } else {
00977 setResult( OK );
00978 emit completed( this );
00979 deleteLater();
00980 }
00981 }
00982
00983
00984
00985 KMOpenMsgCommand::KMOpenMsgCommand( QWidget *parent, const KUrl & url,
00986 const QString & encoding )
00987 : KMCommand( parent ),
00988 mUrl( url ),
00989 mEncoding( encoding )
00990 {
00991 setDeletesItself( true );
00992 }
00993
00994 KMCommand::Result KMOpenMsgCommand::execute()
00995 {
00996 if ( mUrl.isEmpty() ) {
00997 mUrl = KFileDialog::getOpenUrl( KUrl( ":OpenMessage" ),
00998 "message/rfc822 application/mbox",
00999