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 #include "kmcommands.h"
00030
00031 #ifdef HAVE_CONFIG_H
00032 #include <config.h>
00033 #endif
00034
00035 #include <errno.h>
00036 #include <mimelib/enum.h>
00037 #include <mimelib/field.h>
00038 #include <mimelib/mimepp.h>
00039 #include <mimelib/string.h>
00040 #include <kapplication.h>
00041 #include <dcopclient.h>
00042
00043 #include <qtextcodec.h>
00044
00045 #include <libkdepim/email.h>
00046 #include <kdebug.h>
00047 #include <kencodingfiledialog.h>
00048 #include <kio/netaccess.h>
00049 #include <kabc/stdaddressbook.h>
00050 #include <kabc/addresseelist.h>
00051 #include <klocale.h>
00052 #include <kmessagebox.h>
00053 #include <kparts/browserextension.h>
00054 #include <kprogress.h>
00055 #include <krun.h>
00056 #include <kbookmarkmanager.h>
00057 #include <kstandarddirs.h>
00058 #include <ktempfile.h>
00059 #if !KDE_IS_VERSION( 3, 3, 0 )
00060 # include <storedtransferjob.h>
00061 #endif
00062 #include "actionscheduler.h"
00063 using KMail::ActionScheduler;
00064 #include "mailinglist-magic.h"
00065 #include "kmaddrbook.h"
00066 #include <kaddrbook.h>
00067 #include "kmcomposewin.h"
00068 #include "kmfiltermgr.h"
00069 #include "kmfoldermbox.h"
00070 #include "kmfolderimap.h"
00071 #include "kmfoldermgr.h"
00072 #include "kmheaders.h"
00073 #include "kmmainwidget.h"
00074 #include "kmmsgdict.h"
00075 #include "messagesender.h"
00076 #include "undostack.h"
00077 #include "kcursorsaver.h"
00078 #include "partNode.h"
00079 #include "objecttreeparser.h"
00080 using KMail::ObjectTreeParser;
00081 using KMail::FolderJob;
00082 #include "mailsourceviewer.h"
00083 using KMail::MailSourceViewer;
00084 #include "kmreadermainwin.h"
00085 #include "secondarywindow.h"
00086 using KMail::SecondaryWindow;
00087 #include "kimproxy.h"
00088
00089 #include "progressmanager.h"
00090 using KPIM::ProgressManager;
00091 using KPIM::ProgressItem;
00092
00093 #include "broadcaststatus.h"
00094
00095 #include "headerstrategy.h"
00096 using KMail::HeaderStrategy;
00097 #include "headerstyle.h"
00098 using KMail::HeaderStyle;
00099
00100 #include "kmcommands.moc"
00101
00102 KMCommand::KMCommand( QWidget *parent )
00103 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00104 mEmitsCompletedItself( false ), mParent( parent )
00105 {
00106 }
00107
00108 KMCommand::KMCommand( QWidget *parent, const QPtrList<KMMsgBase> &msgList )
00109 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00110 mEmitsCompletedItself( false ), mParent( parent ), mMsgList( msgList )
00111 {
00112 }
00113
00114 KMCommand::KMCommand( QWidget *parent, KMMsgBase *msgBase )
00115 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00116 mEmitsCompletedItself( false ), mParent( parent )
00117 {
00118 mMsgList.append( msgBase );
00119 }
00120
00121 KMCommand::KMCommand( QWidget *parent, KMMessage *msg )
00122 : mProgressDialog( 0 ), mResult( Undefined ), mDeletesItself( false ),
00123 mEmitsCompletedItself( false ), mParent( parent )
00124 {
00125 mMsgList.append( &msg->toMsgBase() );
00126 }
00127
00128 KMCommand::~KMCommand()
00129 {
00130 QValueListIterator<QGuardedPtr<KMFolder> > fit;
00131 for ( fit = mFolders.begin(); fit != mFolders.end(); ++fit ) {
00132 if (!(*fit))
00133 continue;
00134 (*fit)->close();
00135 }
00136 }
00137
00138 KMCommand::Result KMCommand::result()
00139 {
00140 if ( mResult == Undefined )
00141 kdDebug(5006) << k_funcinfo << "mResult is Undefined" << endl;
00142 return mResult;
00143 }
00144
00145 void KMCommand::start()
00146 {
00147 QTimer::singleShot( 0, this, SLOT( slotStart() ) );
00148 }
00149
00150
00151 const QPtrList<KMMessage> KMCommand::retrievedMsgs() const
00152 {
00153 return mRetrievedMsgs;
00154 }
00155
00156 KMMessage *KMCommand::retrievedMessage() const
00157 {
00158 return mRetrievedMsgs.getFirst();
00159 }
00160
00161 QWidget *KMCommand::parentWidget() const
00162 {
00163 return mParent;
00164 }
00165
00166 int KMCommand::mCountJobs = 0;
00167
00168 void KMCommand::slotStart()
00169 {
00170 connect( this, SIGNAL( messagesTransfered( KMCommand::Result ) ),
00171 this, SLOT( slotPostTransfer( KMCommand::Result ) ) );
00172 kmkernel->filterMgr()->ref();
00173
00174 if (mMsgList.find(0) != -1) {
00175 emit messagesTransfered( Failed );
00176 return;
00177 }
00178
00179 if ((mMsgList.count() == 1) &&
00180 (mMsgList.getFirst()->isMessage()) &&
00181 (mMsgList.getFirst()->parent() == 0))
00182 {
00183
00184 mRetrievedMsgs.append((KMMessage*)mMsgList.getFirst());
00185 emit messagesTransfered( OK );
00186 return;
00187 }
00188
00189 for (KMMsgBase *mb = mMsgList.first(); mb; mb = mMsgList.next())
00190 if (!mb->parent()) {
00191 emit messagesTransfered( Failed );
00192 return;
00193 } else {
00194 mFolders.append( mb->parent() );
00195 mb->parent()->open();
00196 }
00197
00198
00199 transferSelectedMsgs();
00200 }
00201
00202 void KMCommand::slotPostTransfer( KMCommand::Result result )
00203 {
00204 disconnect( this, SIGNAL( messagesTransfered( KMCommand::Result ) ),
00205 this, SLOT( slotPostTransfer( KMCommand::Result ) ) );
00206 if ( result == OK )
00207 result = execute();
00208 mResult = result;
00209 QPtrListIterator<KMMessage> it( mRetrievedMsgs );
00210 KMMessage* msg;
00211 while ( (msg = it.current()) != 0 )
00212 {
00213 ++it;
00214 if (msg->parent())
00215 msg->setTransferInProgress(false);
00216 }
00217 kmkernel->filterMgr()->deref();
00218 if ( !emitsCompletedItself() )
00219 emit completed( this );
00220 if ( !deletesItself() )
00221 deleteLater();
00222 }
00223
00224 void KMCommand::transferSelectedMsgs()
00225 {
00226
00227 if (KMCommand::mCountJobs > 0) {
00228 emit messagesTransfered( Failed );
00229 return;
00230 }
00231
00232 bool complete = true;
00233 KMCommand::mCountJobs = 0;
00234 mCountMsgs = 0;
00235 mRetrievedMsgs.clear();
00236 mCountMsgs = mMsgList.count();
00237 uint totalSize = 0;
00238
00239
00240
00241
00242 if ( mCountMsgs > 0 ) {
00243 mProgressDialog = new KProgressDialog(mParent, "transferProgress",
00244 i18n("Please wait"),
00245 i18n("Please wait while the message is transferred",
00246 "Please wait while the %n messages are transferred", mMsgList.count()),
00247 true);
00248 mProgressDialog->setMinimumDuration(1000);
00249 }
00250 for (KMMsgBase *mb = mMsgList.first(); mb; mb = mMsgList.next())
00251 {
00252
00253 KMMessage *thisMsg = 0;
00254 if ( mb->isMessage() )
00255 thisMsg = static_cast<KMMessage*>(mb);
00256 else
00257 {
00258 KMFolder *folder = mb->parent();
00259 int idx = folder->find(mb);
00260 if (idx < 0) continue;
00261 thisMsg = folder->getMsg(idx);
00262 }
00263 if (!thisMsg) continue;
00264 if ( thisMsg->transferInProgress() &&
00265 thisMsg->parent()->folderType() == KMFolderTypeImap )
00266 {
00267 thisMsg->setTransferInProgress( false, true );
00268 thisMsg->parent()->ignoreJobsForMessage( thisMsg );
00269 }
00270
00271 if ( thisMsg->parent() && !thisMsg->isComplete() &&
00272 ( !mProgressDialog || !mProgressDialog->wasCancelled() ) )
00273 {
00274 kdDebug(5006)<<"### INCOMPLETE\n";
00275
00276 complete = false;
00277 KMCommand::mCountJobs++;
00278 FolderJob *job = thisMsg->parent()->createJob(thisMsg);
00279 job->setCancellable( false );
00280 totalSize += thisMsg->msgSizeServer();
00281
00282 connect(job, SIGNAL(messageRetrieved(KMMessage*)),
00283 this, SLOT(slotMsgTransfered(KMMessage*)));
00284
00285 connect(job, SIGNAL(finished()),
00286 this, SLOT(slotJobFinished()));
00287 connect(job, SIGNAL(progress(unsigned long, unsigned long)),
00288 this, SLOT(slotProgress(unsigned long, unsigned long)));
00289
00290 thisMsg->setTransferInProgress(true);
00291 job->start();
00292 } else {
00293 thisMsg->setTransferInProgress(true);
00294 mRetrievedMsgs.append(thisMsg);
00295 }
00296 }
00297
00298 if (complete)
00299 {
00300 delete mProgressDialog;
00301 mProgressDialog = 0;
00302 emit messagesTransfered( OK );
00303 } else {
00304
00305 if ( mProgressDialog ) {
00306 connect(mProgressDialog, SIGNAL(cancelClicked()),
00307 this, SLOT(slotTransferCancelled()));
00308 mProgressDialog->progressBar()->setTotalSteps(totalSize);
00309 }
00310 }
00311 }
00312
00313 void KMCommand::slotMsgTransfered(KMMessage* msg)
00314 {
00315 if ( mProgressDialog && mProgressDialog->wasCancelled() ) {
00316 emit messagesTransfered( Canceled );
00317 return;
00318 }
00319
00320
00321 mRetrievedMsgs.append(msg);
00322 }
00323
00324 void KMCommand::slotProgress( unsigned long done, unsigned long )
00325 {
00326 mProgressDialog->progressBar()->setProgress( done );
00327 }
00328
00329 void KMCommand::slotJobFinished()
00330 {
00331
00332 KMCommand::mCountJobs--;
00333
00334 if ( mProgressDialog && mProgressDialog->wasCancelled() ) return;
00335
00336 if ( (mCountMsgs - static_cast<int>(mRetrievedMsgs.count())) > KMCommand::mCountJobs )
00337 {
00338
00339 if ( mProgressDialog )
00340 mProgressDialog->hide();
00341 slotTransferCancelled();
00342 return;
00343 }
00344
00345 if ( mProgressDialog ) {
00346 mProgressDialog->setLabel(i18n("Please wait while the message is transferred",
00347 "Please wait while the %n messages are transferred", KMCommand::mCountJobs));
00348 }
00349 if (KMCommand::mCountJobs == 0)
00350 {
00351
00352 delete mProgressDialog;
00353 mProgressDialog = 0;
00354 emit messagesTransfered( OK );
00355 }
00356 }
00357
00358 void KMCommand::slotTransferCancelled()
00359 {
00360
00361 QValueListIterator<QGuardedPtr<KMFolder> > fit;
00362 for ( fit = mFolders.begin(); fit != mFolders.end(); ++fit ) {
00363 if (!(*fit))
00364 continue;
00365 KMFolder *folder = *fit;
00366 KMFolderImap *imapFolder = dynamic_cast<KMFolderImap*>(folder);
00367 if (imapFolder && imapFolder->account()) {
00368 imapFolder->account()->killAllJobs();
00369 }
00370 }
00371
00372 KMCommand::mCountJobs = 0;
00373 mCountMsgs = 0;
00374
00375 QPtrListIterator<KMMessage> it( mRetrievedMsgs );
00376 KMMessage* msg;
00377 while ( (msg = it.current()) != 0 )
00378 {
00379 KMFolder *folder = msg->parent();
00380 ++it;
00381 if (!folder)
00382 continue;
00383 msg->setTransferInProgress(false);
00384 int idx = folder->find(msg);
00385 if (idx > 0) folder->unGetMsg(idx);
00386 }
00387 mRetrievedMsgs.clear();
00388 emit messagesTransfered( Canceled );
00389 }
00390
00391 void KMCommand::keepFolderOpen( KMFolder *folder )
00392 {
00393 folder->open();
00394 mFolders.append( folder );
00395 }
00396
00397 KMMailtoComposeCommand::KMMailtoComposeCommand( const KURL &url,
00398 KMMessage *msg )
00399 :mUrl( url ), mMessage( msg )
00400 {
00401 }
00402
00403 KMCommand::Result KMMailtoComposeCommand::execute()
00404 {
00405 KMComposeWin *win;
00406 KMMessage *msg = new KMMessage;
00407 uint id = 0;
00408
00409 if ( mMessage && mMessage->parent() )
00410 id = mMessage->parent()->identity();
00411
00412 msg->initHeader(id);
00413 msg->setCharset("utf-8");
00414 msg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00415
00416 win = new KMComposeWin(msg, id);
00417 win->setCharset("", TRUE);
00418 win->setFocusToSubject();
00419 win->show();
00420
00421 return OK;
00422 }
00423
00424
00425 KMMailtoReplyCommand::KMMailtoReplyCommand( QWidget *parent,
00426 const KURL &url, KMMessage *msg, const QString &selection )
00427 :KMCommand( parent, msg ), mUrl( url ), mSelection( selection )
00428 {
00429 }
00430
00431 KMCommand::Result KMMailtoReplyCommand::execute()
00432 {
00433
00434 KMMessage *msg = retrievedMessage();
00435 KMComposeWin *win;
00436 KMMessage *rmsg = msg->createReply( KMail::ReplyNone, mSelection );
00437 rmsg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00438
00439 win = new KMComposeWin(rmsg, 0);
00440 win->setCharset(msg->codec()->mimeName(), TRUE);
00441 win->setReplyFocus();
00442 win->show();
00443
00444 return OK;
00445 }
00446
00447
00448 KMMailtoForwardCommand::KMMailtoForwardCommand( QWidget *parent,
00449 const KURL &url, KMMessage *msg )
00450 :KMCommand( parent, msg ), mUrl( url )
00451 {
00452 }
00453
00454 KMCommand::Result KMMailtoForwardCommand::execute()
00455 {
00456
00457 KMMessage *msg = retrievedMessage();
00458 KMComposeWin *win;
00459 KMMessage *fmsg = msg->createForward();
00460 fmsg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
00461
00462 win = new KMComposeWin(fmsg);
00463 win->setCharset(msg->codec()->mimeName(), TRUE);
00464 win->show();
00465
00466 return OK;
00467 }
00468
00469
00470 KMAddBookmarksCommand::KMAddBookmarksCommand( const KURL &url, QWidget *parent )
00471 : KMCommand( parent ), mUrl( url )
00472 {
00473 }
00474
00475 KMCommand::Result KMAddBookmarksCommand::execute()
00476 {
00477 QString filename = locateLocal( "data", QString::fromLatin1("konqueror/bookmarks.xml") );
00478 KBookmarkManager *bookManager = KBookmarkManager::managerForFile( filename,
00479 false );
00480 KBookmarkGroup group = bookManager->root();
00481 group.addBookmark( bookManager, mUrl.path(), KURL( mUrl ) );
00482 if( bookManager->save() ) {
00483 bookManager->emitChanged( group );
00484 }
00485
00486 return OK;
00487 }
00488
00489 KMMailtoAddAddrBookCommand::KMMailtoAddAddrBookCommand( const KURL &url,
00490 QWidget *parent )
00491 : KMCommand( parent ), mUrl( url )
00492 {
00493 }
00494
00495 KMCommand::Result KMMailtoAddAddrBookCommand::execute()
00496 {
00497 KAddrBookExternal::addEmail( KMMessage::decodeMailtoUrl( mUrl.path() ),
00498 parentWidget() );
00499
00500 return OK;
00501 }
00502
00503
00504 KMMailtoOpenAddrBookCommand::KMMailtoOpenAddrBookCommand( const KURL &url,
00505 QWidget *parent )
00506 : KMCommand( parent ), mUrl( url )
00507 {
00508 }
00509
00510 KMCommand::Result KMMailtoOpenAddrBookCommand::execute()
00511 {
00512 QString addr = KMMessage::decodeMailtoUrl( mUrl.path() );
00513 KAddrBookExternal::openEmail( KPIM::getEmailAddr(addr), addr ,
00514 parentWidget() );
00515
00516 return OK;
00517 }
00518
00519
00520 KMUrlCopyCommand::KMUrlCopyCommand( const KURL &url, KMMainWidget *mainWidget )
00521 :mUrl( url ), mMainWidget( mainWidget )
00522 {
00523 }
00524
00525 KMCommand::Result KMUrlCopyCommand::execute()
00526 {
00527 QClipboard* clip = QApplication::clipboard();
00528
00529 if (mUrl.protocol() == "mailto") {
00530
00531 QString address = KMMessage::decodeMailtoUrl( mUrl.path() );
00532 clip->setSelectionMode( true );
00533 clip->setText( address );
00534 clip->setSelectionMode( false );
00535 clip->setText( address );
00536 KPIM::BroadcastStatus::instance()->setStatusMsg( i18n( "Address copied to clipboard." ));
00537 } else {
00538
00539 clip->setSelectionMode( true );
00540 clip->setText( mUrl.url() );
00541 clip->setSelectionMode( false );
00542 clip->setText( mUrl.url() );
00543 KPIM::BroadcastStatus::instance()->setStatusMsg( i18n( "URL copied to clipboard." ));
00544 }
00545
00546 return OK;
00547 }
00548
00549
00550 KMUrlOpenCommand::KMUrlOpenCommand( const KURL &url, KMReaderWin *readerWin )
00551 :mUrl( url ), mReaderWin( readerWin )
00552 {
00553 }
00554
00555 KMCommand::Result KMUrlOpenCommand::execute()
00556 {
00557 if ( !mUrl.isEmpty() )
00558 mReaderWin->slotUrlOpen( mUrl, KParts::URLArgs() );
00559
00560 return OK;
00561 }
00562
00563
00564 KMUrlSaveCommand::KMUrlSaveCommand( const KURL &url, QWidget *parent )
00565 : KMCommand( parent ), mUrl( url )
00566 {
00567 }
00568
00569 KMCommand::Result KMUrlSaveCommand::execute()
00570 {
00571 if ( mUrl.isEmpty() )
00572 return OK;
00573 KURL saveUrl = KFileDialog::getSaveURL(mUrl.fileName(), QString::null,
00574 parentWidget() );
00575 if ( saveUrl.isEmpty() )
00576 return Canceled;
00577 if ( KIO::NetAccess::exists( saveUrl, false, parentWidget() ) )
00578 {
00579 if (KMessageBox::warningContinueCancel(0,
00580 i18n("<qt>File <b>%1</b> exists.<br>Do you want to replace it?</qt>")
00581 .arg(saveUrl.prettyURL()), i18n("Save to File"), i18n("&Replace"))
00582 != KMessageBox::Continue)
00583 return Canceled;
00584 }
00585 KIO::Job *job = KIO::file_copy(mUrl, saveUrl, -1, true);
00586 connect(job, SIGNAL(result(KIO::Job*)), SLOT(slotUrlSaveResult(KIO::Job*)));
00587 setEmitsCompletedItself( true );
00588 return OK;
00589 }
00590
00591 void KMUrlSaveCommand::slotUrlSaveResult( KIO::Job *job )
00592 {
00593 if ( job->error() ) {
00594 job->showErrorDialog();
00595 setResult( Failed );
00596 emit completed( this );
00597 }
00598 else {
00599 setResult( OK );
00600 emit completed( this );
00601 }
00602 }
00603
00604 #if KDE_IS_VERSION( 3, 3, 0 )
00605 # define KIO_STORED_PUT KIO::storedPut
00606 #else
00607
00608 # define KIO_STORED_PUT KIOext::put
00609 #endif
00610
00611 KMail::SaveTextAsCommand::SaveTextAsCommand( const QString & txt, QWidget * parent )
00612 : KMCommand( parent ), mText( txt ) {}
00613
00614 KMCommand::Result KMail::SaveTextAsCommand::execute() {
00615 if ( mText.isEmpty() )
00616 return OK;
00617
00618 const KEncodingFileDialog::Result res = KEncodingFileDialog::getSaveURLAndEncoding( QString::null, QString::null, QString::null, parentWidget() );
00619 if ( res.URLs.empty() )
00620 return Canceled;
00621 const KURL saveUrl = res.URLs.front();
00622 if ( !saveUrl.isValid() )
00623 return Canceled;
00624 if ( KIO::NetAccess::exists( saveUrl, false, parentWidget() ) ) {
00625 if (KMessageBox::warningContinueCancel(0,
00626 i18n("<qt>File <b>%1</b> exists.<br>Do you want to replace it?</qt>")
00627 .arg(saveUrl.prettyURL()), i18n("Save to File"), i18n("&Replace"))
00628 != KMessageBox::Continue)
00629 return Canceled;
00630 }
00631 const QTextCodec * codec = QTextCodec::codecForName( res.encoding.latin1() );
00632 Q_ASSERT( codec );
00633 if ( !codec )
00634 return Canceled;
00635 int len = -1;
00636 QByteArray data = codec->fromUnicode( mText, len );
00637 data.resize( len );
00638 KIO::Job * uploadJob = KIO_STORED_PUT( data, saveUrl, -1, true , false );
00639 uploadJob->setWindow( parentWidget() );
00640 connect( uploadJob, SIGNAL(result(KIO::Job*)), SLOT(slotResult(KIO::Job*)) );
00641 setEmitsCompletedItself( true );
00642 return OK;
00643 }
00644
00645 #undef KIO_STORED_PUT
00646
00647 void KMail::SaveTextAsCommand::slotResult( KIO::Job * job ) {
00648 if ( job->error() ) {
00649 job->showErrorDialog();
00650 setResult( Failed );
00651 } else {
00652 setResult( OK );
00653 }
00654 emit completed( this );
00655 }
00656
00657 KMEditMsgCommand::KMEditMsgCommand( QWidget *parent, KMMessage *msg )
00658 :KMCommand( parent, msg )
00659 {
00660 }
00661
00662 KMCommand::Result KMEditMsgCommand::execute()
00663 {
00664 KMMessage *msg = retrievedMessage();
00665 if (!msg || !msg->parent() ||
00666 !kmkernel->folderIsDraftOrOutbox( msg->parent() ))
00667 return Failed;
00668
00669
00670
00671
00672 KMFolder *parent = msg->parent();
00673 if ( parent )
00674 parent->take( parent->find( msg ) );
00675
00676 KMComposeWin *win = new KMComposeWin();
00677 msg->setTransferInProgress(false);
00678 win->setMsg(msg, FALSE, TRUE);
00679 win->setFolder( parent );
00680 win->show();
00681
00682 return OK;
00683 }
00684
00685 KMShowMsgSrcCommand::KMShowMsgSrcCommand( KMMessage *msg, bool fixedFont )
00686 : mFixedFont( fixedFont ), mMsg ( msg )
00687 {
00688 }
00689
00690 void KMShowMsgSrcCommand::start()
00691 {
00692 QString str = mMsg->codec()->toUnicode( mMsg->asString() );
00693
00694 MailSourceViewer *viewer = new MailSourceViewer();
00695 viewer->setCaption( i18n("Message as Plain Text") );
00696 viewer->setText(str);
00697 if( mFixedFont )
00698 viewer->setFont(KGlobalSettings::fixedFont());
00699
00700
00701
00702
00703 if (QApplication::desktop()->isVirtualDesktop()) {
00704 int scnum = QApplication::desktop()->screenNumber(QCursor::pos());
00705 viewer->resize(QApplication::desktop()->screenGeometry(scnum).width()/2,
00706 2*QApplication::desktop()->screenGeometry(scnum).height()/3);
00707 } else {
00708 viewer->resize(QApplication::desktop()->geometry().width()/2,
00709 2*QApplication::desktop()->geometry().height()/3);
00710 }
00711 viewer->show();
00712 }
00713
00714 static KURL subjectToUrl( const QString & subject ) {
00715 return KFileDialog::getSaveURL( subject.stripWhiteSpace()
00716 .replace( QDir::separator(), '_' ),
00717 "*.mbox" );
00718 }
00719
00720 KMSaveMsgCommand::KMSaveMsgCommand( QWidget *parent, KMMessage * msg )
00721 : KMCommand( parent ),
00722 mMsgListIndex( 0 ),
00723 mOffset( 0 ),
00724 mTotalSize( msg ? msg->msgSize() : 0 )
00725 {
00726 if ( !msg ) return;
00727 setDeletesItself( true );
00728 mMsgList.append( msg->getMsgSerNum() );
00729 mUrl = subjectToUrl( msg->cleanSubject() );
00730 }
00731
00732 KMSaveMsgCommand::KMSaveMsgCommand( QWidget *parent,
00733 const QPtrList<KMMsgBase> &msgList )
00734 : KMCommand( parent ),
00735 mMsgListIndex( 0 ),
00736 mOffset( 0 ),
00737 mTotalSize( 0 )
00738 {
00739 if (!msgList.getFirst())
00740 return;
00741 setDeletesItself( true );
00742 KMMsgBase *msgBase = msgList.getFirst();
00743
00744
00745
00746
00747 QPtrListIterator<KMMsgBase> it(msgList);
00748 while ( it.current() ) {
00749 mMsgList.append( (*it)->getMsgSerNum() );
00750 mTotalSize += (*it)->msgSize();
00751 if ((*it)->parent() != 0)
00752 (*it)->parent()->open();
00753 ++it;
00754 }
00755 mMsgListIndex = 0;
00756 mUrl = subjectToUrl( msgBase->cleanSubject() );
00757 }
00758
00759 KURL KMSaveMsgCommand::url()
00760 {
00761 return mUrl;
00762 }
00763
00764 KMCommand::Result KMSaveMsgCommand::execute()
00765 {
00766 mJob = KIO::put( mUrl, S_IRUSR|S_IWUSR, false, false );
00767 mJob->slotTotalSize( mTotalSize );
00768 mJob->setAsyncDataEnabled( true );
00769 mJob->setReportDataSent( true );
00770 connect(mJob, SIGNAL(dataReq(KIO::Job*, QByteArray &)),
00771 SLOT(slotSaveDataReq()));
00772 connect(mJob, SIGNAL(result(KIO::Job*)),
00773 SLOT(slotSaveResult(KIO::Job*)));
00774 setEmitsCompletedItself( true );
00775 return OK;
00776 }
00777
00778 void KMSaveMsgCommand::slotSaveDataReq()
00779 {
00780 int remainingBytes = mData.size() - mOffset;
00781 if ( remainingBytes > 0 ) {
00782
00783 if ( remainingBytes > MAX_CHUNK_SIZE )
00784 remainingBytes = MAX_CHUNK_SIZE;
00785
00786 QByteArray data;
00787 data.duplicate( mData.data() + mOffset, remainingBytes );
00788 mJob->sendAsyncData( data );
00789 mOffset += remainingBytes;
00790 return;
00791 }
00792
00793 if ( mMsgListIndex < mMsgList.size() ) {
00794 KMMessage *msg = 0;
00795 int idx = -1;
00796 KMFolder * p = 0;
00797 kmkernel->msgDict()->getLocation( mMsgList[mMsgListIndex], &p, &idx );
00798 assert( p );
00799 assert( idx >= 0 );
00800 msg = p->getMsg(idx);
00801
00802 if (msg->transferInProgress()) {
00803 QByteArray data = QByteArray();
00804 mJob->sendAsyncData( data );
00805 }
00806 msg->setTransferInProgress( true );
00807 if (msg->isComplete() ) {
00808 slotMessageRetrievedForSaving(msg);
00809 } else {
00810
00811 if (msg->parent() && !msg->isComplete() ) {
00812 FolderJob *job = msg->parent()->createJob(msg);
00813 job->setCancellable( false );
00814 connect(job, SIGNAL(messageRetrieved(KMMessage*)),
00815 this, SLOT(slotMessageRetrievedForSaving(KMMessage*)));
00816 job->start();
00817 }
00818 }
00819 } else {
00820
00821 QByteArray data = QByteArray();
00822 mJob->sendAsyncData( data );
00823 }
00824 }
00825
00826 void KMSaveMsgCommand::slotMessageRetrievedForSaving(KMMessage *msg)
00827 {
00828 QCString str( msg->mboxMessageSeparator() );
00829 str += KMFolderMbox::escapeFrom( msg->asString() );
00830 str += "\n";
00831 msg->setTransferInProgress(false);
00832
00833 mData = str;
00834 mData.resize(mData.size() - 1);
00835 mOffset = 0;
00836 QByteArray data;
00837 int size;
00838
00839 if( mData.size() > (unsigned int) MAX_CHUNK_SIZE )
00840 size = MAX_CHUNK_SIZE;
00841 else
00842 size = mData.size();
00843
00844 data.duplicate( mData, size );
00845 mJob->sendAsyncData( data );
00846 mOffset += size;
00847 ++mMsgListIndex;
00848
00849 if (msg->parent()) {
00850 int idx = -1;
00851 KMFolder * p = 0;
00852 kmkernel->msgDict()->getLocation( msg, &p, &idx );
00853 assert( p == msg->parent() ); assert( idx >= 0 );
00854 p->unGetMsg( idx );
00855 p->close();
00856 }
00857 }
00858
00859 void KMSaveMsgCommand::slotSaveResult(KIO::Job *job)
00860 {
00861 if (job->error())
00862 {
00863 if (job->error() == KIO::ERR_FILE_ALREADY_EXIST)
00864 {
00865 if (KMessageBox::warningContinueCancel(0,
00866 i18n("File %1 exists.\nDo you want to replace it?")
00867 .arg(mUrl.prettyURL()), i18n("Save to File"), i18n("&Replace"))
00868 == KMessageBox::Continue) {
00869 mOffset = 0;
00870
00871 mJob = KIO::put( mUrl, S_IRUSR|S_IWUSR, true, false );
00872 mJob->slotTotalSize( mTotalSize );
00873 mJob->setAsyncDataEnabled( true );
00874 mJob->setReportDataSent( true );
00875 connect(mJob, SIGNAL(dataReq(KIO::Job*, QByteArray &)),
00876 SLOT(slotSaveDataReq()));
00877 connect(mJob, SIGNAL(result(KIO::Job*)),
00878 SLOT(slotSaveResult(KIO::Job*)));
00879 }
00880 }
00881 else
00882 {
00883 job->showErrorDialog();
00884 setResult( Failed );
00885 emit completed( this );
00886 deleteLater();
00887 }
00888 } else {
00889 setResult( OK );
00890 emit completed( this );
00891 deleteLater();
00892 }
00893 }
00894
00895
00896
00897 KMOpenMsgCommand::KMOpenMsgCommand( QWidget *parent, const KURL & url,
00898 const QString & encoding )
00899 : KMCommand( parent ),
00900 mUrl( url ),
00901 mEncoding( encoding )
00902 {
00903 setDeletesItself( true );
00904 }
00905
00906 KMCommand::Result KMOpenMsgCommand::execute()
00907 {
00908 if ( mUrl.isEmpty() ) {
00909 mUrl = KFileDialog::getOpenURL( ":OpenMessage", "message/rfc822",
00910 parentWidget(), i18n("Open Message") );
00911 }
00912 if ( mUrl.isEmpty() ) {
00913 setDeletesItself( false );
00914 return Canceled;
00915 }
00916 mJob = KIO::get( mUrl, false, false );
00917 mJob->setReportDataSent( true );
00918 connect( mJob, SIGNAL( data( KIO::Job *, const QByteArray & ) ),
00919 this, SLOT( slotDataArrived( KIO::Job*, const QByteArray & ) ) );
00920 connect( mJob, SIGNAL( result( KIO::Job * ) ),
00921 SLOT( slotResult( KIO::Job * ) ) );
00922 setEmitsCompletedItself( true );
00923 return OK;
00924 }
00925
00926 void KMOpenMsgCommand::slotDataArrived( KIO::Job *, const QByteArray & data )
00927 {
00928 if ( data.isEmpty() )
00929 return;
00930
00931 mMsgString.append( data.data(), data.size() );
00932 }
00933
00934 void KMOpenMsgCommand::slotResult( KIO::Job *job )
00935 {
00936 if ( job->error() ) {
00937
00938 job->showErrorDialog();
00939 setResult( Failed );
00940 emit completed( this );
00941 }
00942 else {
00943 int startOfMessage = 0;
00944 if ( mMsgString.compare( 0, 5, "From ", 5 ) == 0 ) {
00945 startOfMessage = mMsgString.find( '\n' );
00946 if ( startOfMessage == -1 ) {
00947 KMessageBox::sorry( parentWidget(),
00948 i18n( "The file doesn't contain a message." ) );
00949 setResult( Failed );
00950 emit completed( this );
00951
00952
00953
00954 SecondaryWindow *win = new SecondaryWindow();
00955 win->close();
00956 win->deleteLater();
00957 deleteLater();
00958 return;
00959 }
00960 startOfMessage += 1;
00961 }
00962
00963 bool multipleMessages = true;
00964 int endOfMessage = mMsgString.find( "\nFrom " );
00965 if ( endOfMessage == -1 ) {
00966 endOfMessage = mMsgString.length();
00967 multipleMessages = false;
00968 }
00969 DwMessage *dwMsg = new DwMessage;
00970 dwMsg->FromString( mMsgString.substr( startOfMessage,
00971 endOfMessage - startOfMessage ) );
00972 dwMsg->Parse();
00973
00974 if ( dwMsg->Headers().NumFields() == 0 ) {
00975 KMessageBox::sorry( parentWidget(),
00976 i18n( "The file doesn't contain a message." ) );
00977 delete dwMsg; dwMsg = 0;
00978 setResult( Failed );
00979 emit completed( this );
00980
00981 SecondaryWindow *win = new SecondaryWindow();
00982 win->close();
00983 win->deleteLater();
00984 deleteLater();
00985 return;
00986 }
00987 KMMessage *msg = new KMMessage( dwMsg );
00988 msg->setComplete( true );
00989 msg->setReadyToShow( true );
00990 KMReaderMainWin *win = new KMReaderMainWin();
00991 win->showMsg( mEncoding, msg );
00992 win->show();
00993 if ( multipleMessages )
00994 KMessageBox::information( win,
00995 i18n( "The file contains multiple messages. "
00996 "Only the first message is shown." ) );
00997 setResult( OK );
00998 emit completed( this );
00999 }
01000 deleteLater();
01001 }
01002
01003
01004
01005
01006
01007 KMReplyToCommand::KMReplyToCommand( QWidget *parent, KMMessage *msg,
01008 const QString &selection )
01009 : KMCommand( parent, msg ), mSelection( selection )
01010 {
01011 }
01012
01013 KMCommand::Result KMReplyToCommand::execute()
01014 {
01015 KCursorSaver busy(KBusyPtr::busy());
01016 KMMessage *msg = retrievedMessage();
01017 KMMessage *reply = msg->createReply( KMail::ReplySmart, mSelection );
01018 KMComposeWin *win = new KMComposeWin( reply );
01019 win->setCharset( msg->codec()->mimeName(), TRUE );
01020 win->setReplyFocus();
01021 win->show();
01022
01023 return OK;
01024 }
01025
01026
01027 KMNoQuoteReplyToCommand::KMNoQuoteReplyToCommand( QWidget *parent,
01028 KMMessage *msg )
01029 : KMCommand( parent, msg )
01030 {
01031 }
01032
01033 KMCommand::Result KMNoQuoteReplyToCommand::execute()
01034 {
01035 KCursorSaver busy(KBusyPtr::busy());
01036 KMMessage *msg = retrievedMessage();
01037 KMMessage *reply = msg->createReply( KMail::ReplySmart, "", TRUE);
01038 KMComposeWin *win = new KMComposeWin( reply );
01039 win->setCharset(msg->codec()->mimeName(), TRUE);
01040 win->setReplyFocus(false);
01041 win->show();
01042
01043 return OK;
01044 }
01045
01046
01047 KMReplyListCommand::KMReplyListCommand( QWidget *parent,
01048 KMMessage *msg, const QString &selection )
01049 : KMCommand( parent, msg ), mSelection( selection )
01050 {
01051 }
01052
01053 KMCommand::Result KMReplyListCommand::execute()
01054 {
01055 KCursorSaver busy(KBusyPtr::busy());
01056 KMMessage *msg = retrievedMessage();
01057 KMMessage *reply = msg->createReply( KMail::ReplyList, mSelection);
01058 KMComposeWin *win = new KMComposeWin( reply );
01059 win->setCharset(msg->codec()->mimeName(), TRUE);
01060 win->setReplyFocus(false);
01061 win->show();
01062
01063 return OK;
01064 }
01065
01066
01067 KMReplyToAllCommand::KMReplyToAllCommand( QWidget *parent,
01068 KMMessage *msg, const QString &selection )
01069 :KMCommand( parent, msg ), mSelection( selection )
01070 {
01071 }
01072
01073 KMCommand::Result KMReplyToAllCommand::execute()
01074 {
01075 KCursorSaver busy(KBusyPtr::busy());
01076 KMMessage *msg = retrievedMessage();
01077 KMMessage *reply = msg->createReply( KMail::ReplyAll, mSelection );
01078 KMComposeWin *win = new KMComposeWin( reply );
01079 win->setCharset( msg->codec()->mimeName(), TRUE );
01080 win->setReplyFocus();
01081 win->show();
01082
01083 return OK;
01084 }
01085
01086
01087 KMReplyAuthorCommand::KMReplyAuthorCommand( QWidget *parent, KMMessage *msg,
01088 const QString &selection )
01089 : KMCommand( parent, msg ), mSelection( selection )
01090 {
01091 }
01092
01093 KMCommand::Result KMReplyAuthorCommand::execute()
01094 {
01095 KCursorSaver busy(KBusyPtr::busy());
01096 KMMessage *msg = retrievedMessage();
01097 KMMessage *reply = msg->createReply( KMail::ReplyAuthor, mSelection );
01098 KMComposeWin *win = new KMComposeWin( reply );
01099 win->setCharset( msg->codec()->mimeName(), TRUE );
01100 win->setReplyFocus();
01101 win->show();
01102
01103 return OK;
01104 }
01105
01106
01107 KMForwardCommand::KMForwardCommand( QWidget *parent,
01108 const QPtrList<KMMsgBase> &msgList, uint identity )
01109 : KMCommand( parent, msgList ),
01110 mIdentity( identity )
01111 {
01112 }
01113
01114 KMForwardCommand::KMForwardCommand( QWidget *parent, KMMessage *msg,
01115 uint identity )
01116 : KMCommand( parent, msg ),
01117 mIdentity( identity )
01118 {
01119 }
01120
01121 KMCommand::Result KMForwardCommand::execute()
01122 {
01123 KMComposeWin *win;
01124 QPtrList<KMMessage> msgList = retrievedMsgs();
01125
01126 if (msgList.count() >= 2) {
01127
01128
01129 if (KMessageBox::questionYesNo( parentWidget(),
01130 i18n("Forward selected messages as "
01131 "a MIME digest?") )
01132 == KMessageBox::Yes) {
01133 uint id = 0;
01134 KMMessage *fwdMsg = new KMMessage;
01135 KMMessagePart *msgPart = new KMMessagePart;
01136 QString msgPartText;
01137 int msgCnt = 0;
01138
01139
01140
01141 fwdMsg->initHeader(id);
01142 fwdMsg->setAutomaticFields(true);
01143 fwdMsg->mMsg->Headers().ContentType().CreateBoundary(1);
01144 QCString boundary( fwdMsg->mMsg->Headers().ContentType().Boundary().c_str() );
01145 msgPartText = i18n("\nThis is a MIME digest forward. The content of the"
01146 " message is contained in the attachment(s).\n\n\n");
01147
01148 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next()) {
01149
01150 if (id == 0)
01151 id = msg->headerField("X-KMail-Identity").stripWhiteSpace().toUInt();
01152
01153 msgPartText += "--";
01154 msgPartText += QString::fromLatin1( boundary );
01155 msgPartText += "\nContent-Type: MESSAGE/RFC822";
01156 msgPartText += QString("; CHARSET=%1").arg(msg->charset());
01157 msgPartText += "\n";
01158 DwHeaders dwh;
01159 dwh.MessageId().CreateDefault();
01160 msgPartText += QString("Content-ID: %1\n").arg(dwh.MessageId().AsString().c_str());
01161 msgPartText += QString("Content-Description: %1").arg(msg->subject());
01162 if (!msg->subject().contains("(fwd)"))
01163 msgPartText += " (fwd)";
01164 msgPartText += "\n\n";
01165
01166 msg->removePrivateHeaderFields();
01167 msg->removeHeaderField("BCC");
01168
01169 msgPartText += msg->headerAsString();
01170 msgPartText += "\n";
01171 msgPartText += msg->body();
01172 msgPartText += "\n";
01173 msgCnt++;
01174 fwdMsg->link(msg, KMMsgStatusForwarded);
01175 }
01176 if ( id == 0 )
01177 id = mIdentity;
01178 fwdMsg->initHeader(id);
01179 msgPartText += "--";
01180 msgPartText += QString::fromLatin1( boundary );
01181 msgPartText += "--\n";
01182 QCString tmp;
01183 msgPart->setTypeStr("MULTIPART");
01184 tmp.sprintf( "Digest; boundary=\"%s\"", boundary.data() );
01185 msgPart->setSubtypeStr( tmp );
01186 msgPart->setName("unnamed");
01187 msgPart->setCte(DwMime::kCte7bit);
01188 msgPart->setContentDescription(QString("Digest of %1 messages.").arg(msgCnt));
01189
01190 msgPart->setBodyEncoded(QCString(msgPartText.ascii()));
01191 KCursorSaver busy(KBusyPtr::busy());
01192 win = new KMComposeWin(fwdMsg, id);
01193 win->addAttach(msgPart);
01194 win->show();
01195 return OK;
01196 } else {
01197 uint id = 0;
01198 QCString msgText = "";
01199 QPtrList<KMMessage> linklist;
01200 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next()) {
01201
01202 if (id == 0)
01203 id = msg->headerField("X-KMail-Identity").stripWhiteSpace().toUInt();
01204
01205 msgText += msg->createForwardBody();
01206 linklist.append(msg);
01207 }
01208 if ( id == 0 )
01209 id = mIdentity;
01210 KMMessage *fwdMsg = new KMMessage;
01211 fwdMsg->initHeader(id);
01212 fwdMsg->setAutomaticFields(true);
01213 fwdMsg->setCharset("utf-8");
01214 fwdMsg->setBody(msgText);
01215
01216 for (KMMessage *msg = linklist.first(); msg; msg = linklist.next())
01217 fwdMsg->link(msg, KMMsgStatusForwarded);
01218
01219 KCursorSaver busy(KBusyPtr::busy());
01220 win = new KMComposeWin(fwdMsg, id);
01221 win->setCharset("");
01222 win->show();
01223 return OK;
01224 }
01225 }
01226
01227
01228 KMMessage *msg = msgList.getFirst();
01229 if ( !msg || !msg->codec() )
01230 return Failed;
01231
01232 KCursorSaver busy(KBusyPtr::busy());
01233 KMMessage *fwdMsg = msg->createForward();
01234
01235 win = new KMComposeWin( fwdMsg );
01236 win->setCharset( fwdMsg->codec()->mimeName(), true );
01237 win->setBody( QString::fromUtf8( msg->createForwardBody() ) );
01238 win->show();
01239
01240 return OK;
01241 }
01242
01243
01244 KMForwardAttachedCommand::KMForwardAttachedCommand( QWidget *parent,
01245 const QPtrList<KMMsgBase> &msgList, uint identity, KMComposeWin *win )
01246 : KMCommand( parent, msgList ), mIdentity( identity ),
01247 mWin( QGuardedPtr< KMComposeWin >( win ))
01248 {
01249 }
01250
01251 KMForwardAttachedCommand::KMForwardAttachedCommand( QWidget *parent,
01252 KMMessage * msg, uint identity, KMComposeWin *win )
01253 : KMCommand( parent, msg ), mIdentity( identity ),
01254 mWin( QGuardedPtr< KMComposeWin >( win ))
01255 {
01256 }
01257
01258 KMCommand::Result KMForwardAttachedCommand::execute()
01259 {
01260 QPtrList<KMMessage> msgList = retrievedMsgs();
01261 KMMessage *fwdMsg = new KMMessage;
01262
01263 if (msgList.count() >= 2) {
01264
01265
01266 fwdMsg->initHeader(mIdentity);
01267 }
01268 else if (msgList.count() == 1) {
01269 KMMessage *msg = msgList.getFirst();
01270 fwdMsg->initFromMessage(msg);
01271 fwdMsg->setSubject( msg->forwardSubject() );
01272 }
01273
01274 fwdMsg->setAutomaticFields(true);
01275
01276 KCursorSaver busy(KBusyPtr::busy());
01277 if (!mWin)
01278 mWin = new KMComposeWin(fwdMsg, mIdentity);
01279
01280
01281 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next()) {
01282
01283 msg->removePrivateHeaderFields();
01284 msg->removeHeaderField("BCC");
01285
01286 KMMessagePart *msgPart = new KMMessagePart;
01287 msgPart->setTypeStr("message");
01288 msgPart->setSubtypeStr("rfc822");
01289 msgPart->setCharset(msg->charset());
01290 msgPart->setName("forwarded message");
01291 msgPart->setContentDescription(msg->from()+": "+msg->subject());
01292 msgPart->setContentDisposition( "inline" );
01293
01294 msgPart->setMessageBody( msg->asString() );
01295 msgPart->setCharset("");
01296
01297 fwdMsg->link(msg, KMMsgStatusForwarded);
01298 mWin->addAttach(msgPart);
01299 }
01300
01301 mWin->show();
01302
01303 return OK;
01304 }
01305
01306
01307 KMRedirectCommand::KMRedirectCommand( QWidget *parent,
01308 KMMessage *msg )
01309 : KMCommand( parent, msg )
01310 {
01311 }
01312
01313 KMCommand::Result KMRedirectCommand::execute()
01314 {
01315
01316 KMComposeWin *win;
01317 KMMessage *msg = retrievedMessage();
01318 if ( !msg || !msg->codec() )
01319 return Failed;
01320
01321 KCursorSaver busy(KBusyPtr::busy());
01322 win = new KMComposeWin();
01323 win->setMsg(msg->createRedirect(), FALSE);
01324 win->setCharset(msg->codec()->mimeName());
01325 win->show();
01326
01327 return OK;
01328 }
01329
01330
01331 KMBounceCommand::KMBounceCommand( QWidget *parent,
01332 KMMessage *msg )
01333 : KMCommand( parent, msg )
01334 {
01335 }
01336
01337 KMCommand::Result KMBounceCommand::execute()
01338 {
01339 KMMessage *msg = retrievedMessage();
01340 KMMessage *newMsg = msg->createBounce( TRUE );
01341 if (newMsg)
01342 kmkernel->msgSender()->send(newMsg, kmkernel->msgSender()->sendImmediate());
01343
01344 return OK;
01345 }
01346
01347
01348 KMPrintCommand::KMPrintCommand( QWidget *parent,
01349 KMMessage *msg, bool htmlOverride, const QString & encoding,
01350 const HeaderStyle * style,
01351 const HeaderStrategy * strategy )
01352 : KMCommand( parent, msg ), mHtmlOverride( htmlOverride ), mEncoding( encoding ),
01353 mStyle( style ), mStrategy( strategy )
01354 {
01355 }
01356
01357 KMCommand::Result KMPrintCommand::execute()
01358 {
01359 KMReaderWin printWin( 0, 0, 0 );
01360 printWin.setPrinting(TRUE);
01361 printWin.readConfig();
01362 if( mStyle != 0 && mStrategy != 0 )
01363 printWin.setHeaderStyleAndStrategy( mStyle, mStrategy );
01364 printWin.setHtmlOverride( mHtmlOverride );
01365 printWin.setOverrideEncoding( mEncoding );
01366 printWin.setMsg(retrievedMessage(), TRUE);
01367 printWin.printMsg();
01368
01369 return OK;
01370 }
01371
01372
01373 KMSetStatusCommand::KMSetStatusCommand( KMMsgStatus status,
01374 const QValueList<Q_UINT32> &serNums, bool toggle )
01375 : mStatus( status ), mSerNums( serNums ), mToggle( toggle )
01376 {
01377 }
01378
01379 KMCommand::Result KMSetStatusCommand::execute()
01380 {
01381 QValueListIterator<Q_UINT32> it;
01382 int idx = -1;
01383 KMFolder *folder = 0;
01384 bool parentStatus = false;
01385
01386
01387
01388 if (mToggle) {
01389 KMMsgBase *msg;
01390 kmkernel->msgDict()->getLocation( *mSerNums.begin(), &folder, &idx );
01391 if (folder) {
01392 msg = folder->getMsgBase(idx);
01393 if (msg && (msg->status()&mStatus))
01394 parentStatus = true;
01395 else
01396 parentStatus = false;
01397 }
01398 }
01399 QMap< KMFolder*, QValueList<int> > folderMap;
01400 for ( it = mSerNums.begin(); it != mSerNums.end(); ++it ) {
01401 kmkernel->msgDict()->getLocation( *it, &folder, &idx );
01402 if (folder) {
01403 if (mToggle) {
01404 KMMsgBase *msg = folder->getMsgBase(idx);
01405
01406 if (msg) {
01407 bool myStatus;
01408 if (msg->status()&mStatus)
01409 myStatus = true;
01410 else
01411 myStatus = false;
01412 if (myStatus != parentStatus)
01413 continue;
01414 }
01415 }
01416
01417
01418 folderMap[folder].append(idx);
01419 }
01420 }
01421 QMapIterator< KMFolder*, QValueList<int> > it2 = folderMap.begin();
01422 while ( it2 != folderMap.end() ) {
01423 KMFolder *f = it2.key();
01424 f->setStatus( (*it2), mStatus, mToggle );
01425 ++it2;
01426 }
01427
01428
01429 return OK;
01430 }
01431
01432
01433 KMFilterCommand::KMFilterCommand( const QCString &field, const QString &value )
01434 : mField( field ), mValue( value )
01435 {
01436 }
01437
01438 KMCommand::Result KMFilterCommand::execute()
01439 {
01440 kmkernel->filterMgr()->createFilter( mField, mValue );
01441
01442 return OK;
01443 }
01444
01445
01446 KMFilterActionCommand::KMFilterActionCommand( QWidget *parent,
01447 const QPtrList<KMMsgBase> &msgList,
01448 KMFilter *filter )
01449 : KMCommand( parent, msgList ), mFilter( filter )
01450 {
01451 }
01452
01453 KMCommand::Result KMFilterActionCommand::execute()
01454 {
01455 QPtrList<KMMessage> msgList = retrievedMsgs();
01456
01457 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next())
01458 if( msg->parent() )
01459 kmkernel->filterMgr()->tempOpenFolder(msg->parent());
01460
01461 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next()) {
01462 msg->setTransferInProgress(false);
01463
01464 int filterResult = kmkernel->filterMgr()->process(msg, mFilter);
01465 if (filterResult == 2) {
01466
01467 perror("Critical error");
01468 kmkernel->emergencyExit( i18n("Not enough free disk space?" ));
01469 }
01470 msg->setTransferInProgress(true);
01471 }
01472
01473 return OK;
01474 }
01475
01476
01477 KMMetaFilterActionCommand::KMMetaFilterActionCommand( KMFilter *filter,
01478 KMHeaders *headers,
01479 KMMainWidget *main )
01480 : QObject( main ),
01481 mFilter( filter ), mHeaders( headers ), mMainWidget( main )
01482 {
01483 }
01484
01485 void KMMetaFilterActionCommand::start()
01486 {
01487 #if 0 // use action scheduler
01488 KMFilterMgr::FilterSet set = KMFilterMgr::All;
01489 QPtrList<KMFilter> filters;
01490 filters.append( mFilter );
01491 ActionScheduler *scheduler = new ActionScheduler( set, filters, mHeaders );
01492 scheduler->setAlwaysMatch( true );
01493 scheduler->setAutoDestruct( true );
01494
01495 int contentX, contentY;
01496 KMHeaderItem *nextItem = mHeaders->prepareMove( &contentX, &contentY );
01497 QPtrList<KMMsgBase> msgList = *mHeaders->selectedMsgs(true);
01498 mHeaders->finalizeMove( nextItem, contentX, contentY );
01499
01500
01501 for (KMMsgBase *msg = msgList.first(); msg; msg = msgList.next())
01502 scheduler->execFilters( msg );
01503 #else
01504 KMCommand *filterCommand = new KMFilterActionCommand( mMainWidget,
01505 *mHeaders->selectedMsgs(), mFilter);
01506 filterCommand->start();
01507 int contentX, contentY;
01508 KMHeaderItem *item = mHeaders->prepareMove( &contentX, &contentY );
01509 mHeaders->finalizeMove( item, contentX, contentY );
01510 #endif
01511 }
01512
01513
01514 KMMailingListFilterCommand::KMMailingListFilterCommand( QWidget *parent,
01515 KMMessage *msg )
01516 : KMCommand( parent, msg )
01517 {
01518 }
01519
01520 KMCommand::Result KMMailingListFilterCommand::execute()
01521 {
01522 QCString name;
01523 QString value;
01524 KMMessage *msg = retrievedMessage();
01525 if (!msg)
01526 return Failed;
01527
01528 if ( !MailingList::name( msg, name, value ).isEmpty() ) {
01529 kmkernel->filterMgr()->createFilter( name, value );
01530 return OK;
01531 }
01532 else
01533 return Failed;
01534 }
01535
01536
01537 void KMMenuCommand::folderToPopupMenu(bool move,
01538 QObject *receiver, KMMenuToFolder *aMenuToFolder, QPopupMenu *menu )
01539 {
01540 while ( menu->count() )
01541 {
01542 QPopupMenu *popup = menu->findItem( menu->idAt( 0 ) )->popup();
01543 if (popup)
01544 delete popup;
01545 else
01546 menu->removeItemAt( 0 );
01547 }
01548
01549 if (!kmkernel->imapFolderMgr()->dir().first() &&
01550 !kmkernel->dimapFolderMgr()->dir().first())
01551 {
01552 makeFolderMenu( &kmkernel->folderMgr()->dir(), move,
01553 receiver, aMenuToFolder, menu );
01554 } else {
01555
01556 QPopupMenu* subMenu = new QPopupMenu(menu);
01557 makeFolderMenu( &kmkernel->folderMgr()->dir(),
01558 move, receiver, aMenuToFolder, subMenu );
01559 menu->insertItem( i18n( "Local Folders" ), subMenu );
01560 KMFolderDir* fdir = &kmkernel->imapFolderMgr()->dir();
01561 for (KMFolderNode *node = fdir->first(); node; node = fdir->next()) {
01562 if (node->isDir())
01563 continue;
01564 subMenu = new QPopupMenu(menu);
01565 makeFolderMenu( node, move, receiver, aMenuToFolder, subMenu );
01566 menu->insertItem( node->label(), subMenu );
01567 }
01568 fdir = &kmkernel->dimapFolderMgr()->dir();
01569 for (KMFolderNode *node = fdir->first(); node; node = fdir->next()) {
01570 if (node->isDir())
01571 continue;
01572 subMenu = new QPopupMenu(menu);
01573 makeFolderMenu( node, move, receiver, aMenuToFolder, subMenu );
01574 menu->insertItem( node->label(), subMenu );
01575 }
01576 }
01577 }
01578
01579 void KMMenuCommand::makeFolderMenu(KMFolderNode* node, bool move,
01580 QObject *receiver, KMMenuToFolder *aMenuToFolder, QPopupMenu *menu )
01581 {
01582
01583 if (move)
01584 {
01585 disconnect(menu, SIGNAL(activated(int)), receiver,
01586 SLOT(moveSelectedToFolder(int)));
01587 connect(menu, SIGNAL(activated(int)), receiver,
01588 SLOT(moveSelectedToFolder(int)));
01589 } else {
01590 disconnect(menu, SIGNAL(activated(int)), receiver,
01591 SLOT(copySelectedToFolder(int)));
01592 connect(menu, SIGNAL(activated(int)), receiver,
01593 SLOT(copySelectedToFolder(int)));
01594 }
01595
01596 KMFolder *folder = 0;
01597 KMFolderDir *folderDir = 0;
01598 if (node->isDir()) {
01599 folderDir = static_cast<KMFolderDir*>(node);
01600 } else {
01601 folder = static_cast<KMFolder*>(node);
01602 folderDir = folder->child();
01603 }
01604
01605 if (folder && !folder->noContent())
01606 {
01607 int menuId;
01608 if (move)
01609 menuId = menu->insertItem(i18n("Move to This Folder"));
01610 else
01611 menuId = menu->insertItem(i18n("Copy to This Folder"));
01612 aMenuToFolder->insert( menuId, folder );
01613 menu->setItemEnabled( menuId, !folder->isReadOnly() );
01614 menu->insertSeparator();
01615 }
01616
01617 if (!folderDir)
01618 return;
01619
01620 for (KMFolderNode *it = folderDir->first(); it; it = folderDir->next() ) {
01621 if (it->isDir())
01622 continue;
01623 KMFolder *child = static_cast<KMFolder*>(it);
01624 QString label = child->label();
01625 label.replace("&","&&");
01626 if (child->child() && child->child()->first()) {
01627
01628 QPopupMenu *subMenu = new QPopupMenu(menu, "subMenu");
01629 makeFolderMenu( child, move, receiver,
01630 aMenuToFolder, subMenu );
01631 menu->insertItem( label, subMenu );
01632 } else {
01633
01634 int menuId = menu->insertItem( label );
01635 aMenuToFolder->insert( menuId, child );
01636 menu->setItemEnabled( menuId, !child->isReadOnly() );
01637 }
01638 }
01639 return;
01640 }
01641
01642
01643 KMCopyCommand::KMCopyCommand( KMFolder* destFolder,
01644 const QPtrList<KMMsgBase> &msgList )
01645 :mDestFolder( destFolder ), mMsgList( msgList )
01646 {
01647 }
01648
01649 KMCopyCommand::KMCopyCommand( KMFolder* destFolder, KMMessage * msg )
01650 :mDestFolder( destFolder )
01651 {
01652 mMsgList.append( &msg->toMsgBase() );
01653 }
01654
01655 KMCommand::Result KMCopyCommand::execute()
01656 {
01657 KMMsgBase *msgBase;
01658 KMMessage *msg, *newMsg;
01659 int idx = -1;
01660 bool isMessage;
01661 QPtrList<KMMessage> list;
01662
01663 if (mDestFolder && mDestFolder->open() != 0)
01664 return Failed;
01665
01666 KCursorSaver busy(KBusyPtr::busy());
01667
01668 for (msgBase = mMsgList.first(); msgBase; msgBase = mMsgList.next() )
01669 {
01670 KMFolder *srcFolder = msgBase->parent();
01671 if (isMessage = msgBase->isMessage())
01672 {
01673 msg = static_cast<KMMessage*>(msgBase);
01674 } else {
01675 idx = srcFolder->find(msgBase);
01676 assert(idx != -1);
01677 msg = srcFolder->getMsg(idx);
01678 }
01679
01680 if (srcFolder &&
01681 (srcFolder->folderType()== KMFolderTypeImap) &&
01682 (mDestFolder->folderType() == KMFolderTypeImap) &&
01683 (static_cast<KMFolderImap*>(srcFolder->storage())->account() ==
01684 static_cast<KMFolderImap*>(mDestFolder->storage())->account()))
01685 {
01686 list.append(msg);
01687 } else {
01688 newMsg = new KMMessage;
01689 newMsg->setComplete(msg->isComplete());
01690
01691 if (!newMsg->isComplete())
01692 newMsg->setReadyToShow(false);
01693 newMsg->fromString(msg->asString());
01694 newMsg->setStatus(msg->status());
01695
01696 if (srcFolder && !newMsg->isComplete())
01697 {
01698 newMsg->setParent(msg->parent());
01699 FolderJob *job = srcFolder->createJob(newMsg);
01700 job->setCancellable( false );
01701 connect(job, SIGNAL(messageRetrieved(KMMessage*)),
01702 mDestFolder, SLOT(reallyAddCopyOfMsg(KMMessage*)));
01703
01704 newMsg->setTransferInProgress(true);
01705 job->start();
01706 } else {
01707 int rc, index;
01708 mDestFolder->open();
01709 rc = mDestFolder->addMsg(newMsg, &index);
01710 if (rc == 0 && index != -1)
01711 mDestFolder->unGetMsg( mDestFolder->count() - 1 );
01712 mDestFolder->close();
01713 }
01714 }
01715
01716 if (!isMessage && list.isEmpty())
01717 {
01718 assert(idx != -1);
01719 srcFolder->unGetMsg( idx );
01720 }
01721
01722 }
01723 mDestFolder->close();
01724
01725
01726
01727
01728 if (!list.isEmpty())
01729 {
01730
01731 KMFolderImap *imapDestFolder = static_cast<KMFolderImap*>(mDestFolder->storage());
01732 imapDestFolder->copyMsg(list);
01733 imapDestFolder->getFolder();
01734 }
01735
01736 return OK;
01737 }
01738
01739
01740 KMMoveCommand::KMMoveCommand( KMFolder* destFolder,
01741 const QPtrList<KMMsgBase> &msgList)
01742 :mDestFolder( destFolder ), mMsgList( msgList ), mProgressItem( 0 )
01743 {
01744 setDeletesItself( true );
01745 }
01746
01747 KMMoveCommand::KMMoveCommand( KMFolder* destFolder,
01748 KMMessage *msg )
01749 :mDestFolder( destFolder ), mProgressItem( 0 )
01750 {
01751 setDeletesItself( true );
01752 mMsgList.append( &msg->toMsgBase() );
01753 }
01754
01755 KMMoveCommand::KMMoveCommand( KMFolder* destFolder,
01756 KMMsgBase *msgBase )
01757 :mDestFolder( destFolder ), mProgressItem( 0 )
01758 {
01759 setDeletesItself( true );
01760 mMsgList.append( msgBase );
01761 }
01762
01763 KMMoveCommand::KMMoveCommand( Q_UINT32 )
01764 :mProgressItem( 0 )
01765 {
01766 setDeletesItself( true );
01767 }
01768
01769 KMCommand::Result KMMoveCommand::execute()
01770 {
01771 setEmitsCompletedItself( true );
01772 typedef QMap< KMFolder*, QPtrList<KMMessage>* > FolderToMessageListMap;
01773 FolderToMessageListMap folderDeleteList;
01774
01775 if (mDestFolder && mDestFolder->open() != 0) {
01776 completeMove( Failed );
01777 return Failed;
01778 }
01779 KCursorSaver busy(KBusyPtr::busy());
01780
01781
01782 Q_ASSERT( !mProgressItem );
01783 mProgressItem =
01784 ProgressManager::createProgressItem (
01785 "move"+ProgressManager::getUniqueID(),
01786 mDestFolder ? i18n( "Moving messages" ) : i18n( "Deleting messages" ) );
01787 connect( mProgressItem, SIGNAL( progressItemCanceled( ProgressItem* ) ),
01788 this, SLOT( slotMoveCanceled() ) );
01789
01790 KMMessage *msg;
01791 KMMsgBase *msgBase;
01792 int rc = 0;
01793 int index;
01794 QPtrList<KMMessage> list;
01795 int undoId = -1;
01796
01797 if (mDestFolder) {
01798 connect (mDestFolder, SIGNAL(msgAdded(KMFolder*, Q_UINT32)),
01799 this, SLOT(slotMsgAddedToDestFolder(KMFolder*, Q_UINT32)));
01800
01801 }
01802 for ( msgBase=mMsgList.first(); msgBase; msgBase=mMsgList.next() ) {
01803 mLostBoys.append( msgBase->getMsgSerNum() );
01804 }
01805 mProgressItem->setTotalItems( mMsgList.count() );
01806
01807 for (msgBase=mMsgList.first(); msgBase && !rc; msgBase=mMsgList.next()) {
01808 KMFolder *srcFolder = msgBase->parent();
01809 if (srcFolder == mDestFolder)
01810 continue;
01811 bool undo = msgBase->enableUndo();
01812 int idx = srcFolder->find(msgBase);
01813 assert(idx != -1);
01814 if ( msgBase->isMessage() )
01815 msg = static_cast<KMMessage*>(msgBase);
01816 else
01817 msg = srcFolder->getMsg(idx);
01818
01819 if ( msg->transferInProgress() &&
01820 srcFolder->folderType() == KMFolderTypeImap )
01821 {
01822
01823 msg->setTransferInProgress( false, true );
01824 static_cast<KMFolderImap*>(srcFolder->storage())->ignoreJobsForMessage( msg );
01825 }
01826
01827 if (mDestFolder) {
01828 if (mDestFolder->folderType() == KMFolderTypeImap) {
01829
01830
01831
01832 KMFolderImap *imapFolder = static_cast<KMFolderImap*> ( mDestFolder->storage() );
01833 disconnect (imapFolder, SIGNAL(folderComplete( KMFolderImap*, bool )),
01834 this, SLOT(slotImapFolderCompleted( KMFolderImap*, bool )));
01835
01836 connect (imapFolder, SIGNAL(folderComplete( KMFolderImap*, bool )),
01837 this, SLOT(slotImapFolderCompleted( KMFolderImap*, bool )));
01838 list.append(msg);
01839 } else {
01840
01841 mDestFolder->open();
01842 rc = mDestFolder->moveMsg(msg, &index);
01843 if (rc == 0 && index != -1) {
01844 KMMsgBase *mb = mDestFolder->unGetMsg( mDestFolder->count() - 1 );
01845 if (undo && mb)
01846 {
01847 if ( undoId == -1 )
01848 undoId = kmkernel->undoStack()->newUndoAction( srcFolder, mDestFolder );
01849 kmkernel->undoStack()->addMsgToAction( undoId, mb->getMsgSerNum() );
01850 }
01851 mDestFolder->close();
01852 } else if (rc != 0) {
01853
01854
01855 completeMove( Failed );
01856 mDestFolder->close();
01857 return Failed;
01858 }
01859 }
01860 } else {
01861
01862
01863 if (srcFolder->folderType() == KMFolderTypeImap) {
01864 if (!folderDeleteList[srcFolder])
01865 folderDeleteList[srcFolder] = new QPtrList<KMMessage>;
01866 folderDeleteList[srcFolder]->append( msg );
01867 } else {
01868 srcFolder->removeMsg(idx);
01869 delete msg;
01870 }
01871 }
01872 }
01873 if (!list.isEmpty() && mDestFolder) {
01874 mDestFolder->moveMsg(list, &index);
01875 } else {
01876 FolderToMessageListMap::Iterator it;
01877 for ( it = folderDeleteList.begin(); it != folderDeleteList.end(); ++it ) {
01878 it.key()->removeMsg(*it.data());
01879 delete it.data();
01880 }
01881
01882
01883
01884 KMFolder *srcFolder = 0;
01885 if ( mMsgList.first() ) {
01886 srcFolder = mMsgList.first()->parent();
01887 if ( mDestFolder && mDestFolder == srcFolder ) {
01888 completeMove( OK );
01889 }
01890 }
01891 if ( !mDestFolder ) {
01892 completeMove( OK );
01893 }
01894 }
01895
01896 return OK;
01897 }
01898
01899 void KMMoveCommand::slotImapFolderCompleted(KMFolderImap *, bool success)
01900 {
01901 if ( success ) {
01902
01903
01904
01905
01906
01907
01908 if ( !mLostBoys.isEmpty() ) {
01909 kdDebug(5006) << "### Not all moved messages reported back that they were " << endl
01910 << "### added to the target folder. Did uidValidity change? " << endl;
01911 }
01912 completeMove( OK );
01913 } else {
01914
01915 completeMove( Failed );
01916 }
01917 }
01918
01919 void KMMoveCommand::slotMsgAddedToDestFolder(KMFolder *folder, Q_UINT32 serNum)
01920 {
01921 if (folder != mDestFolder || !mLostBoys.contains( serNum ) ) {
01922 kdDebug(5006) << "KMMoveCommand::msgAddedToDestFolder different "
01923 "folder or invalid serial number." << endl;
01924 return;
01925 }
01926 mLostBoys.remove(serNum);
01927 if ( mLostBoys.isEmpty() ) {
01928
01929 if (mDestFolder && mDestFolder->folderType() != KMFolderTypeImap) {
01930 mDestFolder->sync();
01931 }
01932 completeMove( OK );
01933 } else {
01934 mProgressItem->incCompletedItems();
01935 mProgressItem->updateProgress();
01936 }
01937 }
01938
01939 void KMMoveCommand::completeMove( Result result )
01940 {
01941 if ( mDestFolder )
01942 mDestFolder->close();
01943 while ( !mOpenedFolders.empty() ) {
01944 KMFolder *folder = mOpenedFolders.back();
01945 mOpenedFolders.pop_back();
01946 folder->close();
01947 }
01948 if ( mProgressItem )
01949 mProgressItem->setComplete();
01950 setResult( result );
01951 emit completed( this );
01952 deleteLater();
01953 }
01954
01955 void KMMoveCommand::slotMoveCanceled()
01956 {
01957 completeMove( Canceled );
01958 }
01959
01960
01961 KMDeleteMsgCommand::KMDeleteMsgCommand( KMFolder* srcFolder,
01962 const QPtrList<KMMsgBase> &msgList )
01963 :KMMoveCommand( findTrashFolder( srcFolder ), msgList)
01964 {
01965 srcFolder->open();
01966 mOpenedFolders.push_back( srcFolder );
01967 }
01968
01969 KMDeleteMsgCommand::KMDeleteMsgCommand( KMFolder* srcFolder, KMMessage * msg )
01970 :KMMoveCommand( findTrashFolder( srcFolder ), msg)
01971 {
01972 srcFolder->open();
01973 mOpenedFolders.push_back( srcFolder );
01974 }
01975
01976 KMDeleteMsgCommand::KMDeleteMsgCommand( Q_UINT32 sernum )
01977 :KMMoveCommand( sernum )
01978 {
01979 KMFolder *srcFolder;
01980 int idx;
01981 kmkernel->msgDict()->getLocation( sernum, &srcFolder, &idx );
01982 KMMsgBase *msg = srcFolder->getMsgBase( idx );
01983 srcFolder->open();
01984 mOpenedFolders.push_back( srcFolder );
01985 addMsg( msg );
01986 setDestFolder( findTrashFolder( srcFolder ) );
01987 }
01988
01989 KMFolder * KMDeleteMsgCommand::findTrashFolder( KMFolder * folder )
01990 {
01991 KMFolder* trash = folder->trashFolder();
01992 if( !trash )
01993 trash = kmkernel->trashFolder();
01994 if( trash != folder )
01995 return trash;
01996 return 0;
01997 }
01998
01999
02000 KMUrlClickedCommand::KMUrlClickedCommand( const KURL &url, uint identity,
02001 KMReaderWin *readerWin, bool htmlPref, KMMainWidget *mainWidget )
02002 :mUrl( url ), mIdentity( identity ), mReaderWin( readerWin ),
02003 mHtmlPref( htmlPref ), mMainWidget( mainWidget )
02004 {
02005 }
02006
02007 KMCommand::Result KMUrlClickedCommand::execute()
02008 {
02009 KMComposeWin *win;
02010 KMMessage* msg;
02011
02012 if (mUrl.protocol() == "mailto")
02013 {
02014 msg = new KMMessage;
02015 msg->initHeader(mIdentity);
02016 msg->setCharset("utf-8");
02017 msg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
02018 QString query=mUrl.query();
02019 while (!query.isEmpty()) {
02020 QString queryPart;
02021 int secondQuery = query.find('?',1);
02022 if (secondQuery != -1)
02023 queryPart = query.left(secondQuery);
02024 else
02025 queryPart = query;
02026 query = query.mid(queryPart.length());
02027
02028 if (queryPart.left(9) == "?subject=")
02029 msg->setSubject( KURL::decode_string(queryPart.mid(9)) );
02030 else if (queryPart.left(6) == "?body=")
02031
02032
02033 msg->setBody( KURL::decode_string(queryPart.mid(6)).latin1() );
02034 else if (queryPart.left(4) == "?cc=")
02035 msg->setCc( KURL::decode_string(queryPart.mid(4)) );
02036 }
02037
02038 win = new KMComposeWin(msg, mIdentity);
02039 win->setCharset("", TRUE);
02040 win->show();
02041 }
02042 else if ( mUrl.protocol() == "im" )
02043 {
02044 kmkernel->imProxy()->chatWithContact( mUrl.path() );
02045 }
02046 else if ((mUrl.protocol() == "http") || (mUrl.protocol() == "https") ||
02047 (mUrl.protocol() == "ftp") || (mUrl.protocol() == "file") ||
02048 (mUrl.protocol() == "ftps") || (mUrl.protocol() == "sftp" ) ||
02049 (mUrl.protocol() == "help") || (mUrl.protocol() == "vnc") ||
02050 (mUrl.protocol() == "smb"))
02051 {
02052 KPIM::BroadcastStatus::instance()->setStatusMsg( i18n("Opening URL..."));
02053 KMimeType::Ptr mime = KMimeType::findByURL( mUrl );
02054 if (mime->name() == "application/x-desktop" ||
02055 mime->name() == "application/x-executable" ||
02056 mime->name() == "application/x-msdos-program" ||
02057 mime->name() == "application/x-shellscript" )
02058 {
02059 if (KMessageBox::warningYesNo( 0, i18n( "<qt>Do you really want to execute <b>%1</b>?</qt>" )
02060 .arg( mUrl.prettyURL() ) ) != KMessageBox::Yes)
02061 return Canceled;
02062 }
02063 (void) new KRun( mUrl );
02064 }
02065 else
02066 return Failed;
02067
02068 return OK;
02069 }
02070
02071 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, KMMessage *msg )
02072 : KMCommand( parent, msg ), mImplicitAttachments( true ), mEncoded( false )
02073 {
02074 }
02075
02076 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, const QPtrList<KMMsgBase>& msgs )
02077 : KMCommand( parent, msgs ), mImplicitAttachments( true ), mEncoded( false )
02078 {
02079 }
02080
02081 KMSaveAttachmentsCommand::KMSaveAttachmentsCommand( QWidget *parent, QPtrList<partNode>& attachments,
02082 KMMessage *msg, bool encoded )
02083 : KMCommand( parent, msg ), mImplicitAttachments( false ),
02084 mEncoded( encoded )
02085 {
02086
02087 msg->setComplete( true );
02088 for ( QPtrListIterator<partNode> it( attachments ); it.current(); ++it ) {
02089 mAttachmentMap.insert( it.current(), msg );
02090 }
02091 }
02092
02093 KMCommand::Result KMSaveAttachmentsCommand::execute()
02094 {
02095 setEmitsCompletedItself( true );
02096 if ( mImplicitAttachments ) {
02097 QPtrList<KMMessage> msgList = retrievedMsgs();
02098 KMMessage *msg;
02099 for ( QPtrListIterator<KMMessage> itr( msgList );
02100 ( msg = itr.current() );
02101 ++itr ) {
02102 partNode *rootNode = partNode::fromMessage( msg );
02103 for ( partNode *child = rootNode; child;
02104 child = child->firstChild() ) {
02105 for ( partNode *node = child; node; node = node->nextSibling() ) {
02106 if ( node->type() != DwMime::kTypeMultipart )
02107 mAttachmentMap.insert( node, msg );
02108 }
02109 }
02110 }
02111 }
02112 setDeletesItself( true );
02113
02114 KMLoadPartsCommand *command = new KMLoadPartsCommand( mAttachmentMap );
02115 connect( command, SIGNAL( partsRetrieved() ),
02116 this, SLOT( slotSaveAll() ) );
02117 command->start();
02118
02119 return OK;
02120 }
02121
02122 void KMSaveAttachmentsCommand::slotSaveAll()
02123 {
02124
02125
02126
02127 if ( mImplicitAttachments ) {
02128 for ( PartNodeMessageMap::iterator it = mAttachmentMap.begin();
02129 it != mAttachmentMap.end(); ) {
02130
02131
02132
02133 if ( it.key()->msgPart().fileName().stripWhiteSpace().isEmpty() &&
02134 ( it.key()->msgPart().name().stripWhiteSpace().isEmpty() ||
02135 !it.key()->parentNode() ) ) {
02136 PartNodeMessageMap::iterator delIt = it;
02137 ++it;
02138 mAttachmentMap.remove( delIt );
02139 }
02140 else
02141 ++it;
02142 }
02143 if ( mAttachmentMap.isEmpty() ) {
02144 KMessageBox::information( 0, i18n("Found no attachments to save.") );
02145 setResult( OK );
02146 emit completed( this );
02147 deleteLater();
02148 return;
02149 }
02150 }
02151
02152 KURL url, dirUrl;
02153 if ( mAttachmentMap.count() > 1 ) {
02154
02155 KFileDialog fdlg( ":saveAttachments", QString::null, parentWidget(),
02156 "save attachments dialog", true );
02157 fdlg.setCaption( i18n("Save Attachments To") );
02158 fdlg.setOperationMode( KFileDialog::Saving );
02159 fdlg.setMode( (unsigned int) KFile::Directory );
02160 if ( fdlg.exec() == QDialog::Rejected || !fdlg.selectedURL().isValid() ) {
02161 setResult( Canceled );
02162 emit completed( this );
02163 deleteLater();
02164 return;
02165 }
02166 dirUrl = fdlg.selectedURL();
02167 }
02168 else {
02169
02170 partNode *node = mAttachmentMap.begin().key();
02171
02172 QString s =
02173 node->msgPart().fileName().stripWhiteSpace().replace( ':', '_' );
02174 if ( s.isEmpty() )
02175 s = node->msgPart().name().stripWhiteSpace().replace( ':', '_' );
02176 if ( s.isEmpty() )
02177 s = i18n("filename for an unnamed attachment", "attachment.1");
02178 url = KFileDialog::getSaveURL( s, QString::null, parentWidget(),
02179 QString::null );
02180 if ( url.isEmpty() ) {
02181 setResult( Canceled );
02182 emit completed( this );
02183 deleteLater();
02184 return;
02185 }
02186 }
02187
02188 Result globalResult = OK;
02189 int unnamedAtmCount = 0;
02190 for ( PartNodeMessageMap::const_iterator it = mAttachmentMap.begin();
02191 it != mAttachmentMap.end();
02192 ++it ) {
02193 KURL curUrl;
02194 if ( !dirUrl.isEmpty() ) {
02195 curUrl = dirUrl;
02196 QString s =
02197 it.key()->msgPart().fileName().stripWhiteSpace().replace( ':', '_' );
02198 if ( s.isEmpty() )
02199 s = it.key()->msgPart().name().stripWhiteSpace().replace( ':', '_' );
02200 if ( s.isEmpty() ) {
02201 ++unnamedAtmCount;
02202 s = i18n("filename for the %1-th unnamed attachment",
02203 "attachment.%1")
02204 .arg( unnamedAtmCount );
02205 }
02206 curUrl.setFileName( s );
02207 } else {
02208 curUrl = url;
02209 }
02210
02211 if ( !curUrl.isEmpty() ) {
02212 if ( KIO::NetAccess::exists( curUrl, false, parentWidget() ) ) {
02213 if ( KMessageBox::warningContinueCancel( parentWidget(),
02214 i18n( "A file named %1 already exists. Do you want to overwrite it?" )
02215 .arg( curUrl.fileName() ),
02216 i18n( "File Already Exists" ), i18n("Overwrite") ) == KMessageBox::Cancel) {
02217 continue;
02218 }
02219 }
02220
02221 const Result result = saveItem( it.key(), curUrl );
02222 if ( result != OK )
02223 globalResult = result;
02224 }
02225 }
02226 setResult( globalResult );
02227 emit completed( this );
02228 deleteLater();
02229 }
02230
02231 KMCommand::Result KMSaveAttachmentsCommand::saveItem( partNode *node,
02232 const KURL& url )
02233 {
02234 bool bSaveEncrypted = false;
02235 bool bEncryptedParts = node->encryptionState() != KMMsgNotEncrypted;
02236 if( bEncryptedParts )
02237 if( KMessageBox::questionYesNo( parentWidget(),
02238 i18n( "The part %1 of the message is encrypted. Do you want to keep the encryption when saving?" ).
02239 arg( url.fileName() ),
02240 i18n( "KMail Question" ) ) ==
02241 KMessageBox::Yes )
02242 bSaveEncrypted = true;
02243
02244 bool bSaveWithSig = true;
02245 if( node->signatureState() != KMMsgNotSigned )
02246 if( KMessageBox::questionYesNo( parentWidget(),
02247 i18n( "The part %1 of the message is signed. Do you want to keep the signature when saving?" ).
02248 arg( url.fileName() ),
02249 i18n( "KMail Question" ) ) !=
02250 KMessageBox::Yes )
02251 bSaveWithSig = false;
02252
02253 QByteArray data;
02254 if ( mEncoded )
02255 {
02256
02257
02258 QCString cstr( node->msgPart().body() );
02259 data = cstr;
02260 data.resize(data.size() - 1);
02261 }
02262 else
02263 {
02264 if( bSaveEncrypted || !bEncryptedParts) {
02265 partNode *dataNode = node;
02266 QCString rawReplyString;
02267 bool gotRawReplyString = false;
02268 if( !bSaveWithSig ) {
02269 if( DwMime::kTypeMultipart == node->type() &&
02270 DwMime::kSubtypeSigned == node->subType() ){
02271
02272 if( node->findType( DwMime::kTypeApplication,
02273 DwMime::kSubtypePgpSignature,
02274 TRUE, false ) ){
02275 dataNode = node->findTypeNot( DwMime::kTypeApplication,
02276 DwMime::kSubtypePgpSignature,
02277 TRUE, false );
02278 }else if( node->findType( DwMime::kTypeApplication,
02279 DwMime::kSubtypePkcs7Mime,
02280 TRUE, false ) ){
02281 dataNode = node->findTypeNot( DwMime::kTypeApplication,
02282 DwMime::kSubtypePkcs7Mime,
02283 TRUE, false );
02284 }else{
02285 dataNode = node->findTypeNot( DwMime::kTypeMultipart,
02286 DwMime::kSubtypeUnknown,
02287 TRUE, false );
02288 }
02289 }else{
02290 ObjectTreeParser otp( 0, 0, false, false, false );
02291
02292
02293 dataNode->setProcessed( false, true );
02294 otp.parseObjectTree( dataNode );
02295
02296 rawReplyString = otp.rawReplyString();
02297 gotRawReplyString = true;
02298 }
02299 }
02300 QByteArray cstr = gotRawReplyString
02301 ? rawReplyString
02302 : dataNode->msgPart().bodyDecodedBinary();
02303 data = cstr;
02304 size_t size = cstr.size();
02305 if ( dataNode->msgPart().type() == DwMime::kTypeText ) {
02306
02307 size = KMFolder::crlf2lf( cstr.data(), size );
02308 }
02309 data.resize( size );
02310 }
02311 }
02312 QDataStream ds;
02313 QFile file;
02314 KTempFile tf;
02315 tf.setAutoDelete( true );
02316 if ( url.isLocalFile() )
02317 {
02318
02319 file.setName( url.path() );
02320 if ( !file.open( IO_WriteOnly ) )
02321 {
02322 KMessageBox::error( parentWidget(),
02323 i18n( "%2 is detailed error description",
02324 "Could not write the file %1:\n%2" )
02325 .arg( file.name() )
02326 .arg( QString::fromLocal8Bit( strerror( errno ) ) ),
02327 i18n( "KMail Error" ) );
02328 return Failed;
02329 }
02330
02331
02332
02333 ds.setDevice( &file );
02334 } else
02335 {
02336
02337 ds.setDevice( tf.file() );
02338 }
02339
02340 ds.writeRawBytes( data.data(), data.size() );
02341 if ( !url.isLocalFile() )
02342 {
02343 tf.close();
02344 if ( !KIO::NetAccess::upload( tf.name(), url, parentWidget() ) )
02345 {
02346 KMessageBox::error( parentWidget(),
02347 i18n( "Could not write the file %1." )
02348 .arg( url.path() ),
02349 i18n( "KMail Error" ) );
02350 return Failed;
02351 }
02352 } else
02353 file.close();
02354 return OK;
02355 }
02356
02357 KMLoadPartsCommand::KMLoadPartsCommand( QPtrList<partNode>& parts, KMMessage *msg )
02358 : mNeedsRetrieval( 0 )
02359 {
02360 for ( QPtrListIterator<partNode> it( parts ); it.current(); ++it ) {
02361 mPartMap.insert( it.current(), msg );
02362 }
02363 }
02364
02365 KMLoadPartsCommand::KMLoadPartsCommand( partNode *node, KMMessage *msg )
02366 : mNeedsRetrieval( 0 )
02367 {
02368 mPartMap.insert( node, msg );
02369 }
02370
02371 KMLoadPartsCommand::KMLoadPartsCommand( PartNodeMessageMap& partMap )
02372 : mNeedsRetrieval( 0 ), mPartMap( partMap )
02373 {
02374 }
02375
02376 void KMLoadPartsCommand::slotStart()
02377 {
02378 for ( PartNodeMessageMap::const_iterator it = mPartMap.begin();
02379 it != mPartMap.end();
02380 ++it ) {
02381 if ( !it.key()->msgPart().isComplete() &&
02382 !it.key()->msgPart().partSpecifier().isEmpty() ) {
02383
02384 ++mNeedsRetrieval;
02385 KMFolder* curFolder = it.data()->parent();
02386 if ( curFolder ) {
02387 FolderJob *job =
02388 curFolder->createJob( it.data(), FolderJob::tGetMessage,
02389 0, it.key()->msgPart().partSpecifier() );
02390 job->setCancellable( false );
02391 connect( job, SIGNAL(messageUpdated(KMMessage*, QString)),
02392 this, SLOT(slotPartRetrieved(KMMessage*, QString)) );
02393 job->start();
02394 } else
02395 kdWarning(5006) << "KMLoadPartsCommand - msg has no parent" << endl;
02396 }
02397 }
02398 if ( mNeedsRetrieval == 0 )
02399 execute();
02400 }
02401
02402 void KMLoadPartsCommand::slotPartRetrieved( KMMessage *msg,
02403 QString partSpecifier )
02404 {
02405 DwBodyPart *part =
02406 msg->findDwBodyPart( msg->getFirstDwBodyPart(), partSpecifier );
02407 if ( part ) {
02408
02409 for ( PartNodeMessageMap::const_iterator it = mPartMap.begin();
02410 it != mPartMap.end();
02411 ++it ) {
02412 if ( it.key()->dwPart()->partId() == part->partId() )
02413 it.key()->setDwPart( part );
02414 }
02415 } else
02416 kdWarning(5006) << "KMLoadPartsCommand::slotPartRetrieved - could not find bodypart!" << endl;
02417 --mNeedsRetrieval;
02418 if ( mNeedsRetrieval == 0 )
02419 execute();
02420 }
02421
02422 KMCommand::Result KMLoadPartsCommand::execute()
02423 {
02424 emit partsRetrieved();
02425 setResult( OK );
02426 emit completed( this );
02427 deleteLater();
02428 return OK;
02429 }
02430
02431 KMResendMessageCommand::KMResendMessageCommand( QWidget *parent,
02432 KMMessage *msg )
02433 :KMCommand( parent, msg )
02434 {
02435 }
02436
02437 KMCommand::Result KMResendMessageCommand::execute()
02438 {
02439 KMComposeWin *win;
02440 KMMessage *msg = retrievedMessage();
02441
02442 KMMessage *newMsg = new KMMessage(*msg);
02443 newMsg->setCharset(msg->codec()->mimeName());
02444
02445 newMsg->removeHeaderField( "Message-Id" );
02446 newMsg->setParent( 0 );
02447
02448
02449 newMsg->removeHeaderField( "Date" );
02450
02451 win = new KMComposeWin();
02452 win->setMsg(newMsg, false, true);
02453 win->show();
02454
02455 return OK;
02456 }
02457
02458 KMMailingListCommand::KMMailingListCommand( QWidget *parent, KMFolder *folder )
02459 : KMCommand( parent ), mFolder( folder )
02460 {
02461 }
02462
02463 KMCommand::Result KMMailingListCommand::execute()
02464 {
02465 KURL::List lst = urls();
02466 QString handler = ( mFolder->mailingList().handler() == MailingList::KMail )
02467 ? "mailto" : "https";
02468
02469 KMCommand *command = 0;
02470 for ( KURL::List::Iterator itr = lst.begin(); itr != lst.end(); ++itr ) {
02471 if ( handler == (*itr).protocol() ) {
02472 command = new KMUrlClickedCommand( *itr, mFolder->identity(), 0, false );
02473 }
02474 }
02475 if ( !command && !lst.empty() ) {
02476 command =
02477 new KMUrlClickedCommand( lst.first(), mFolder->identity(), 0, false );
02478 }
02479 if ( command ) {
02480 connect( command, SIGNAL( completed( KMCommand * ) ),
02481 this, SLOT( commandCompleted( KMCommand * ) ) );
02482 setDeletesItself( true );
02483 setEmitsCompletedItself( true );
02484 command->start();
02485 return OK;
02486 }
02487 return Failed;
02488 }
02489
02490 void KMMailingListCommand::commandCompleted( KMCommand *command )
02491 {
02492 setResult( command->result() );
02493 emit completed( this );
02494 deleteLater();
02495 }
02496
02497 KMMailingListPostCommand::KMMailingListPostCommand( QWidget *parent, KMFolder *folder )
02498 : KMMailingListCommand( parent, folder )
02499 {
02500 }
02501 KURL::List KMMailingListPostCommand::urls() const
02502 {
02503 return mFolder->mailingList().postURLS();
02504 }
02505
02506 KMMailingListSubscribeCommand::KMMailingListSubscribeCommand( QWidget *parent, KMFolder *folder )
02507 : KMMailingListCommand( parent, folder )
02508 {
02509 }
02510 KURL::List KMMailingListSubscribeCommand::urls() const
02511 {
02512 return mFolder->mailingList().subscribeURLS();
02513 }
02514
02515 KMMailingListUnsubscribeCommand::KMMailingListUnsubscribeCommand( QWidget *parent, KMFolder *folder )
02516 : KMMailingListCommand( parent, folder )
02517 {
02518 }
02519 KURL::List KMMailingListUnsubscribeCommand::urls() const
02520 {
02521 return mFolder->mailingList().unsubscribeURLS();
02522 }
02523
02524 KMMailingListArchivesCommand::KMMailingListArchivesCommand( QWidget *parent, KMFolder *folder )
02525 : KMMailingListCommand( parent, folder )
02526 {
02527 }
02528 KURL::List KMMailingListArchivesCommand::urls() const
02529 {
02530 return mFolder->mailingList().archiveURLS();
02531 }
02532
02533 KMMailingListHelpCommand::KMMailingListHelpCommand( QWidget *parent, KMFolder *folder )
02534 : KMMailingListCommand( parent, folder )
02535 {
02536 }
02537 KURL::List KMMailingListHelpCommand::urls() const
02538 {
02539 return mFolder->mailingList().helpURLS();
02540 }
02541
02542 KMIMChatCommand::KMIMChatCommand( const KURL &url, KMMessage *msg )
02543 :mUrl( url ), mMessage( msg )
02544 {
02545 }
02546
02547 KMCommand::Result KMIMChatCommand::execute()
02548 {
02549 kdDebug( 5006 ) << k_funcinfo << " URL is: " << mUrl << endl;
02550
02551 KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
02552 KABC::AddresseeList addresses = addressBook->findByEmail( KPIM::getEmailAddr( mUrl.path() ) ) ;
02553
02554
02555 if( addresses.count() == 1 ) {
02556 kmkernel->imProxy()->chatWithContact( addresses[0].uid() );
02557 return OK;
02558 }
02559 else
02560 {
02561 kdDebug( 5006 ) << "Didn't find exactly one addressee, couldn't tell who to chat to for that email address. Count = " << addresses.count() << endl;
02562
02563 QString apology;
02564 if ( addresses.isEmpty() )
02565 apology = i18n( "There is no Address Book entry for this email address. Add them to the Address Book and then add instant messaging addresses using your preferred messaging client." );
02566 else
02567 {
02568 apology = i18n( "More than one Address Book entry uses this email address:\n %1\n it is not possible to determine who to chat with." );
02569 QStringList nameList;
02570 KABC::AddresseeList::const_iterator it = addresses.begin();
02571 KABC::AddresseeList::const_iterator end = addresses.end();
02572 for ( ; it != end; ++it )
02573 {
02574 nameList.append( (*it).realName() );
02575 }
02576 QString names = nameList.join( QString::fromLatin1( ",\n" ) );
02577 apology = apology.arg( names );
02578 }
02579
02580 KMessageBox::sorry( parentWidget(), apology );
02581 return Failed;
02582 }
02583 }