kmail Library API Documentation

kmkernel.cpp

00001 /* -*- mode: C++; c-file-style: "gnu" -*- */ 00002 #ifdef HAVE_CONFIG_H 00003 #include <config.h> 00004 #endif 00005 00006 #include "config.h" 00007 #include "kmkernel.h" 00008 00009 #include <weaver.h> 00010 #include <weaverlogger.h> 00011 00012 #include "kmstartup.h" 00013 #include "kmmsgindex.h" 00014 #include "kmmainwin.h" 00015 #include "kmcomposewin.h" 00016 #include "kmfoldermgr.h" 00017 #include "kmfoldercachedimap.h" 00018 #include "kmacctcachedimap.h" 00019 #include "kmfiltermgr.h" 00020 #include "kmfilteraction.h" 00021 #include "kmsender.h" 00022 #include "undostack.h" 00023 #include "kmacctmgr.h" 00024 #include "kfileio.h" 00025 #include "kmversion.h" 00026 #include "kmreaderwin.h" 00027 #include "kmmainwidget.h" 00028 #include "recentaddresses.h" 00029 using KRecentAddress::RecentAddresses; 00030 #include "kmmsgdict.h" 00031 #include "kmidentity.h" 00032 #include "identitymanager.h" 00033 #include "configuredialog.h" 00034 // #### disabled for now #include "startupwizard.h" 00035 #include <kwin.h> 00036 #include "kmgroupware.h" 00037 #include "kmailicalifaceimpl.h" 00038 #include "mailserviceimpl.h" 00039 using KMail::MailServiceImpl; 00040 #include "folderIface.h" 00041 using KMail::FolderIface; 00042 #include "cryptplugwrapperlist.h" 00043 00044 #include <kapplication.h> 00045 #include <kaboutdata.h> 00046 #include <kmessagebox.h> 00047 #include <knotifyclient.h> 00048 #include <kstaticdeleter.h> 00049 #include <kstandarddirs.h> 00050 #include <kconfig.h> 00051 #include <kprogress.h> 00052 #include <kpassivepopup.h> 00053 #include <dcopclient.h> 00054 #include <ksystemtray.h> 00055 00056 #include <kdebug.h> 00057 00058 #include <qutf7codec.h> 00059 #include <qvbox.h> 00060 #include <qdir.h> 00061 #include <qobjectlist.h> 00062 00063 #include <sys/types.h> 00064 #include <dirent.h> 00065 #include <sys/stat.h> 00066 #include <unistd.h> 00067 #include <stdio.h> 00068 #include <stdlib.h> 00069 #include <assert.h> 00070 00071 #include <X11/Xlib.h> 00072 #include <fixx11h.h> 00073 #include <kcmdlineargs.h> 00074 #include <kstartupinfo.h> 00075 00076 KMKernel *KMKernel::mySelf = 0; 00077 00078 /********************************************************************/ 00079 /* Constructor and destructor */ 00080 /********************************************************************/ 00081 KMKernel::KMKernel (QObject *parent, const char *name) : 00082 DCOPObject("KMailIface"), QObject(parent, name), 00083 mIdentityManager(0), mProgress(0), mConfigureDialog(0), 00084 mContextMenuShown( false ) 00085 { 00086 //kdDebug(5006) << "KMKernel::KMKernel" << endl; 00087 mySelf = this; 00088 the_startingUp = true; 00089 closed_by_user = true; 00090 the_firstInstance = true; 00091 the_msgDict = 0; 00092 the_msgIndex = 0; 00093 00094 the_inboxFolder = 0; 00095 the_outboxFolder = 0; 00096 the_sentFolder = 0; 00097 the_trashFolder = 0; 00098 the_draftsFolder = 0; 00099 00100 the_folderMgr = 0; 00101 the_imapFolderMgr = 0; 00102 the_dimapFolderMgr = 0; 00103 the_searchFolderMgr = 0; 00104 the_undoStack = 0; 00105 the_acctMgr = 0; 00106 the_filterMgr = 0; 00107 the_popFilterMgr = 0; 00108 the_filterActionDict = 0; 00109 the_msgSender = 0; 00110 mWin = 0; 00111 00112 mGroupware = new KMGroupware( this ); 00113 00114 // Set up DCOP interface 00115 mICalIface = new KMailICalIfaceImpl(); 00116 00117 mXmlGuiInstance = 0; 00118 mDeadLetterTimer = 0; 00119 mDeadLetterInterval = 1000*120; // 2 minutes 00120 allowedToExpire = false; 00121 00122 new Kpgp::Module(); 00123 00124 // register our own (libkdenetwork) utf-7 codec as long as Qt 00125 // doesn't have it's own: 00126 if ( !QTextCodec::codecForName("utf-7") ) { 00127 kdDebug(5006) << "No Qt-native utf-7 codec found; registering QUtf7Codec from libkdenetwork" << endl; 00128 (void) new QUtf7Codec(); 00129 } 00130 00131 // In the case of Japan. Japanese locale name is "eucjp" but 00132 // The Japanese mail systems normally used "iso-2022-jp" of locale name. 00133 // We want to change locale name from eucjp to iso-2022-jp at KMail only. 00134 if ( QCString(QTextCodec::codecForLocale()->name()).lower() == "eucjp" ) 00135 { 00136 netCodec = QTextCodec::codecForName("jis7"); 00137 // QTextCodec *cdc = QTextCodec::codecForName("jis7"); 00138 // QTextCodec::setCodecForLocale(cdc); 00139 // KGlobal::locale()->setEncoding(cdc->mibEnum()); 00140 } else { 00141 netCodec = QTextCodec::codecForLocale(); 00142 } 00143 mMailService = new MailServiceImpl(); 00144 } 00145 00146 KMKernel::~KMKernel () 00147 { 00148 QMap<KIO::Job*, putData>::Iterator it = mPutJobs.begin(); 00149 while ( it != mPutJobs.end() ) 00150 { 00151 KIO::Job *job = it.key(); 00152 mPutJobs.remove( it ); 00153 job->kill(); 00154 it = mPutJobs.begin(); 00155 } 00156 00157 delete mICalIface; 00158 mICalIface = 0L; 00159 00160 delete mMailService; 00161 mySelf = 0; 00162 kdDebug(5006) << "KMKernel::~KMKernel" << endl; 00163 } 00164 00165 bool KMKernel::handleCommandLine( bool noArgsOpensReader ) 00166 { 00167 QString to, cc, bcc, subj, body; 00168 KURL messageFile; 00169 KURL::List attachURLs; 00170 bool mailto = false; 00171 bool checkMail = false; 00172 //bool viewOnly = false; 00173 00174 // process args: 00175 KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); 00176 if (args->getOption("subject")) 00177 { 00178 mailto = true; 00179 subj = QString::fromLocal8Bit(args->getOption("subject")); 00180 } 00181 00182 if (args->getOption("cc")) 00183 { 00184 mailto = true; 00185 cc = QString::fromLocal8Bit(args->getOption("cc")); 00186 } 00187 00188 if (args->getOption("bcc")) 00189 { 00190 mailto = true; 00191 bcc = QString::fromLocal8Bit(args->getOption("bcc")); 00192 } 00193 00194 if (args->getOption("msg")) 00195 { 00196 mailto = true; 00197 messageFile.setPath( QString::fromLocal8Bit(args->getOption("msg")) ); 00198 } 00199 00200 if (args->getOption("body")) 00201 { 00202 mailto = true; 00203 body = QString::fromLocal8Bit(args->getOption("body")); 00204 } 00205 00206 QCStringList attachList = args->getOptionList("attach"); 00207 if (!attachList.isEmpty()) 00208 { 00209 mailto = true; 00210 for ( QCStringList::Iterator it = attachList.begin() ; it != attachList.end() ; ++it ) 00211 if ( !(*it).isEmpty() ) 00212 attachURLs += KURL( QString::fromLocal8Bit( *it ) ); 00213 } 00214 00215 if (args->isSet("composer")) 00216 mailto = true; 00217 00218 if (args->isSet("check")) 00219 checkMail = true; 00220 00221 for(int i= 0; i < args->count(); i++) 00222 { 00223 if (strncasecmp(args->arg(i),"mailto:",7)==0) 00224 to += args->url(i).path() + ", "; 00225 else { 00226 QString tmpArg = QString::fromLocal8Bit( args->arg(i) ); 00227 KURL url( tmpArg ); 00228 if ( url.isValid() ) 00229 attachURLs += url; 00230 else 00231 to += tmpArg + ", "; 00232 } 00233 mailto = true; 00234 } 00235 if ( !to.isEmpty() ) { 00236 // cut off the superfluous trailing ", " 00237 to.truncate( to.length() - 2 ); 00238 } 00239 00240 args->clear(); 00241 00242 if (!noArgsOpensReader && !mailto && !checkMail) 00243 return false; 00244 00245 action (mailto, checkMail, to, cc, bcc, subj, body, messageFile, attachURLs); 00246 return true; 00247 } 00248 00249 /********************************************************************/ 00250 /* DCOP-callable, and command line actions */ 00251 /********************************************************************/ 00252 void KMKernel::checkMail () //might create a new reader but won't show!! 00253 { 00254 kmkernel->acctMgr()->checkMail(false); 00255 } 00256 00257 QStringList KMKernel::accounts() 00258 { 00259 return kmkernel->acctMgr()->getAccounts(); 00260 } 00261 00262 void KMKernel::checkAccount (const QString &account) //might create a new reader but won't show!! 00263 { 00264 kdDebug(5006) << "KMKernel::checkMail called" << endl; 00265 00266 KMAccount* acct = kmkernel->acctMgr()->find(account); 00267 if (acct) 00268 kmkernel->acctMgr()->singleCheckMail(acct, false); 00269 } 00270 00271 void KMKernel::openReader( bool onlyCheck ) 00272 { 00273 KMMainWin *mWin = 0; 00274 KMainWindow *ktmw = 0; 00275 kdDebug(5006) << "KMKernel::openReader called" << endl; 00276 00277 if (KMainWindow::memberList) 00278 for (ktmw = KMainWindow::memberList->first(); ktmw; 00279 ktmw = KMainWindow::memberList->next()) 00280 if (ktmw->isA("KMMainWin")) 00281 break; 00282 00283 bool activate; 00284 if (ktmw) { 00285 mWin = (KMMainWin *) ktmw; 00286 activate = !onlyCheck; // existing window: only activate if not --check 00287 } 00288 else { 00289 mWin = new KMMainWin; 00290 activate = true; // new window: always activate 00291 } 00292 00293 if ( activate ) { 00294 mWin->show(); 00295 // Activate window - doing this instead of KWin::activateWindow(mWin->winId()); 00296 // so that it also works when called from KMailApplication::newInstance() 00297 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00298 KStartupInfo::setNewStartupId( mWin, kapp->startupId() ); 00299 #endif 00300 } 00301 } 00302 00303 int KMKernel::openComposer (const QString &to, const QString &cc, 00304 const QString &bcc, const QString &subject, 00305 const QString &body, int hidden, 00306 const KURL &messageFile, 00307 const KURL::List &attachURLs) 00308 { 00309 kdDebug(5006) << "KMKernel::openComposer called" << endl; 00310 00311 KMMessage *msg = new KMMessage; 00312 msg->initHeader(); 00313 msg->setCharset("utf-8"); 00314 if (!cc.isEmpty()) msg->setCc(cc); 00315 if (!bcc.isEmpty()) msg->setBcc(bcc); 00316 if (!subject.isEmpty()) msg->setSubject(subject); 00317 if (!to.isEmpty()) msg->setTo(to); 00318 00319 if (!messageFile.isEmpty() && messageFile.isLocalFile()) { 00320 QCString str = kFileToString( messageFile.path(), true, false ); 00321 if( !str.isEmpty() ) 00322 msg->setBody( QString::fromLocal8Bit( str ).utf8() ); 00323 } 00324 else if (!body.isEmpty()) 00325 msg->setBody(body.utf8()); 00326 00327 KMComposeWin *cWin = new KMComposeWin(msg); 00328 cWin->setCharset("", TRUE); 00329 for ( KURL::List::ConstIterator it = attachURLs.begin() ; it != attachURLs.end() ; ++it ) 00330 cWin->addAttach((*it)); 00331 if (hidden == 0) { 00332 cWin->show(); 00333 // Activate window - doing this instead of KWin::activateWindow(cWin->winId()); 00334 // so that it also works when called from KMailApplication::newInstance() 00335 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00336 KStartupInfo::setNewStartupId( cWin, kapp->startupId() ); 00337 #endif 00338 } 00339 return 1; 00340 } 00341 00342 00343 int KMKernel::openComposer (const QString &to, const QString &cc, 00344 const QString &bcc, const QString &subject, 00345 const QString &body, int hidden, 00346 const QString &attachName, 00347 const QCString &attachCte, 00348 const QCString &attachData, 00349 const QCString &attachType, 00350 const QCString &attachSubType, 00351 const QCString &attachParamAttr, 00352 const QString &attachParamValue, 00353 const QCString &attachContDisp) 00354 { 00355 kdDebug(5006) << "KMKernel::openComposer called" << endl; 00356 00357 KMMessage *msg = new KMMessage; 00358 msg->initHeader(); 00359 msg->setCharset("utf-8"); 00360 if (!cc.isEmpty()) msg->setCc(cc); 00361 if (!bcc.isEmpty()) msg->setBcc(bcc); 00362 if (!subject.isEmpty()) msg->setSubject(subject); 00363 if (!to.isEmpty()) msg->setTo(to); 00364 if (!body.isEmpty()) msg->setBody(body.utf8()); 00365 00366 KMComposeWin *cWin = new KMComposeWin(msg); 00367 cWin->setCharset("", TRUE); 00368 if (!attachData.isEmpty()) { 00369 KMMessagePart *msgPart = new KMMessagePart; 00370 msgPart->setName(attachName); 00371 msgPart->setCteStr(attachCte); 00372 msgPart->setBodyEncoded(attachData); 00373 msgPart->setTypeStr(attachType); 00374 msgPart->setSubtypeStr(attachSubType); 00375 msgPart->setParameter(attachParamAttr,attachParamValue); 00376 msgPart->setContentDisposition(attachContDisp); 00377 cWin->addAttach(msgPart); 00378 } 00379 00380 if (hidden == 0) { 00381 cWin->show(); 00382 // Activate window - doing this instead of KWin::activateWindow(cWin->winId()); 00383 // so that it also works when called from KMailApplication::newInstance() 00384 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00385 KStartupInfo::setNewStartupId( cWin, kapp->startupId() ); 00386 #endif 00387 } 00388 return 1; 00389 } 00390 00391 DCOPRef KMKernel::openComposer(const QString &to, const QString &cc, 00392 const QString &bcc, const QString &subject, 00393 const QString &body,bool hidden) 00394 { 00395 KMMessage *msg = new KMMessage; 00396 msg->initHeader(); 00397 msg->setCharset("utf-8"); 00398 if (!cc.isEmpty()) msg->setCc(cc); 00399 if (!bcc.isEmpty()) msg->setBcc(bcc); 00400 if (!subject.isEmpty()) msg->setSubject(subject); 00401 if (!to.isEmpty()) msg->setTo(to); 00402 if (!body.isEmpty()) msg->setBody(body.utf8()); 00403 00404 KMComposeWin *cWin = new KMComposeWin(msg); 00405 cWin->setCharset("", TRUE); 00406 if (!hidden) { 00407 cWin->show(); 00408 // Activate window - doing this instead of KWin::activateWindow(cWin->winId()); 00409 // so that it also works when called from KMailApplication::newInstance() 00410 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00411 KStartupInfo::setNewStartupId( cWin, kapp->startupId() ); 00412 #endif 00413 } 00414 00415 return DCOPRef(cWin); 00416 } 00417 00418 int KMKernel::sendCertificate( const QString& to, const QByteArray& certData ) 00419 { 00420 KMMessage *msg = new KMMessage; 00421 msg->initHeader(); 00422 msg->setCharset("utf-8"); 00423 msg->setSubject( i18n( "Certificate Signature Request" ) ); 00424 if (!to.isEmpty()) msg->setTo(to); 00425 msg->setBody( i18n( "Please sign this certificate and return to sender." ).utf8() ); 00426 00427 KMComposeWin *cWin = new KMComposeWin(msg); 00428 cWin->setCharset("", TRUE); 00429 cWin->slotSetAlwaysSend( true ); 00430 if (!certData.isEmpty()) { 00431 KMMessagePart *msgPart = new KMMessagePart; 00432 msgPart->setName("smime.p10"); 00433 msgPart->setCteStr("base64"); 00434 msgPart->setBodyEncodedBinary(certData); 00435 msgPart->setTypeStr("application"); 00436 msgPart->setSubtypeStr("pkcs10"); 00437 msgPart->setContentDisposition("attachment; filename=smime.p10"); 00438 cWin->addAttach(msgPart); 00439 } 00440 00441 cWin->show(); 00442 return 1; 00443 } 00444 00445 00446 void KMKernel::compactAllFolders () 00447 { 00448 kdDebug(5006) << "KMKernel::compactAllFolders called" << endl; 00449 the_folderMgr->compactAll(); 00450 kdDebug(5006) << "KMKernel::compactAllFolders finished" << endl; 00451 } 00452 00453 int KMKernel::dcopAddMessage(const QString & foldername,const QString & msgUrlString) 00454 { 00455 return dcopAddMessage(foldername, KURL(msgUrlString)); 00456 } 00457 00458 int KMKernel::dcopAddMessage(const QString & foldername,const KURL & msgUrl) 00459 { 00460 if ( foldername.isEmpty() ) 00461 return -1; 00462 00463 int retval; 00464 QCString messageText; 00465 static QStringList *msgIds = 0; 00466 static QString lastFolder = ""; 00467 bool readFolderMsgIds = false; 00468 00469 //kdDebug(5006) << "KMKernel::dcopAddMessage called" << endl; 00470 00471 if ( foldername != lastFolder ) { 00472 if ( msgIds != 0 ) { 00473 delete msgIds; 00474 msgIds = 0; 00475 } 00476 msgIds = new QStringList; 00477 readFolderMsgIds = true; 00478 lastFolder = foldername; 00479 } 00480 00481 if (!msgUrl.isEmpty() && msgUrl.isLocalFile()) { 00482 00483 // This is a proposed change by Daniel Andor. 00484 // He proposed to change from the fopen(blah) 00485 // to a kFileToString(blah). 00486 // Although it assigns a QString to a QString, 00487 // because of the implicit sharing this poses 00488 // no memory or performance penalty. 00489 00490 messageText = kFileToString( msgUrl.path(), true, false); 00491 if ( messageText.isNull() ) 00492 return -2; 00493 00494 KMMessage *msg = new KMMessage(); 00495 msg->fromString( messageText ); 00496 00497 KMFolder *folder = the_folderMgr->findOrCreate(foldername, false); 00498 00499 if ( folder ) { 00500 if (readFolderMsgIds) { 00501 00502 // Try to determine if a message already exists in 00503 // the folder. The message id that is searched for, is 00504 // the subject line + the date. This should be quite 00505 // unique. The change that a given date with a given 00506 // subject is in the folder twice is very small. 00507 00508 // If the subject is empty, the fromStrip string 00509 // is taken. 00510 int i; 00511 00512 folder->open(); 00513 for( i=0; i<folder->count(); i++) { 00514 KMMsgBase *mb = folder->getMsgBase(i); 00515 time_t DT = mb->date(); 00516 QString dt = ctime(&DT); 00517 QString id = mb->subject(); 00518 00519 if (id.isEmpty()) 00520 id = mb->fromStrip(); 00521 if (id.isEmpty()) 00522 id = mb->toStrip(); 00523 00524 id+=dt; 00525 00526 //fprintf(stderr,"%s\n",(const char *) id); 00527 if (!id.isEmpty()) { 00528 msgIds->append(id); 00529 } 00530 } 00531 folder->close(); 00532 } 00533 00534 time_t DT = msg->date(); 00535 QString dt = ctime( &DT ); 00536 QString msgId = msg->subject(); 00537 00538 if ( msgId.isEmpty() ) 00539 msgId = msg->fromStrip(); 00540 if ( msgId.isEmpty() ) 00541 msgId = msg->toStrip(); 00542 00543 msgId += dt; 00544 00545 int k = msgIds->findIndex( msgId ); 00546 //fprintf(stderr,"find %s = %d\n",(const char *) msgId,k); 00547 00548 if ( k == -1 ) { 00549 if ( !msgId.isEmpty() ) { 00550 msgIds->append( msgId ); 00551 } 00552 if ( folder->addMsg( msg ) == 0 ) { 00553 retval = 1; 00554 } else { 00555 retval =- 2; 00556 delete msg; 00557 msg = 0; 00558 } 00559 } else { 00560 retval = -4; 00561 } 00562 } else { 00563 retval = -1; 00564 } 00565 } else { 00566 retval = -2; 00567 } 00568 return retval; 00569 } 00570 00571 void KMKernel::requestAddresses( QString filename ) 00572 { 00573 mGroupware->requestAddresses( filename ); 00574 } 00575 00576 bool KMKernel::storeAddresses( QString addresses, QStringList delUIDs ) 00577 { 00578 return mGroupware->storeAddresses( addresses, delUIDs ); 00579 } 00580 00581 QStringList KMKernel::folderList() const 00582 { 00583 QStringList folders; 00584 the_folderMgr->getFolderURLS( folders ); 00585 the_imapFolderMgr->getFolderURLS( folders ); 00586 the_dimapFolderMgr->getFolderURLS( folders ); 00587 return folders; 00588 } 00589 00590 DCOPRef KMKernel::getFolder( const QString& vpath ) 00591 { 00592 if ( the_folderMgr->getFolderByURL( vpath ) ) 00593 return DCOPRef( new FolderIface( vpath ) ); 00594 else if ( the_imapFolderMgr->getFolderByURL( vpath ) ) 00595 return DCOPRef( new FolderIface( vpath ) ); 00596 else if ( the_dimapFolderMgr->getFolderByURL( vpath ) ) 00597 return DCOPRef( new FolderIface( vpath ) ); 00598 return DCOPRef(); 00599 } 00600 00601 bool KMKernel::showMail( Q_UINT32 serialNumber, QString /* messageId */ ) 00602 { 00603 KMMainWidget *mainWidget = 0; 00604 if (KMainWindow::memberList) { 00605 KMainWindow *win = 0; 00606 QObjectList *l; 00607 00608 // First look for a KMainWindow. 00609 for (win = KMainWindow::memberList->first(); win; 00610 win = KMainWindow::memberList->next()) { 00611 // Then look for a KMMainWidget. 00612 l = win->queryList("KMMainWidget"); 00613 if (l && l->first()) { 00614 mainWidget = dynamic_cast<KMMainWidget *>(l->first()); 00615 if (win->isActiveWindow()) 00616 break; 00617 } 00618 } 00619 } 00620 00621 if (mainWidget) { 00622 int idx = -1; 00623 KMFolder *folder = 0; 00624 msgDict()->getLocation(serialNumber, &folder, &idx); 00625 if (!folder || (idx == -1)) 00626 return false; 00627 folder->open(); 00628 KMMsgBase *msgBase = folder->getMsgBase(idx); 00629 if (!msgBase) 00630 return false; 00631 bool unGet = !msgBase->isMessage(); 00632 KMMessage *msg = folder->getMsg(idx); 00633 mainWidget->slotSelectFolder(folder); 00634 mainWidget->slotSelectMessage(msg); 00635 if (unGet) 00636 folder->unGetMsg(idx); 00637 folder->close(); 00638 return true; 00639 } 00640 00641 return false; 00642 } 00643 00644 /********************************************************************/ 00645 /* Kernel methods */ 00646 /********************************************************************/ 00647 00648 void KMKernel::quit() 00649 { 00650 // Called when all windows are closed. Will take care of compacting, 00651 // sending... should handle session management too!! 00652 } 00653 /* TODO later: 00654 Asuming that: 00655 - msgsender is nonblocking 00656 (our own, QSocketNotifier based. Pops up errors and sends signal 00657 senderFinished when done) 00658 - compacting is non blocking (insert processEvents there) 00659 00660 o If we are getting mail, stop it (but donīt lose something!) 00661 o If we are sending mail, go on UNLESS this was called by SM, 00662 in which case stop ASAP that too (can we warn? should we continue 00663 on next start?) 00664 o If we are compacting, or expunging, go on UNLESS this was SM call. 00665 In that case stop compacting ASAP and continue on next start, before 00666 touching any folders. 00667 00668 KMKernel::quit () 00669 { 00670 SM call? 00671 if compacting, stop; 00672 if sending, stop; 00673 if receiving, stop; 00674 Windows will take care of themselves (composer should dump 00675 itīs messages, if any but not in deadMail) 00676 declare us ready for the End of the Session 00677 00678 No, normal quit call 00679 All windows are off. Anything to do, should compact or sender sends? 00680 Yes, maybe put an icon in panel as a sign of life 00681 Folder manager, go compacting (*except* outbox and sent-mail!) 00682 if sender sending, connect us to his finished slot, declare us ready 00683 for quit and wait for senderFinished 00684 if not, Folder manager, go compact sent-mail and outbox 00685 } (= call slotFinished()) 00686 00687 void KMKernel::slotSenderFinished() 00688 { 00689 good, Folder manager go compact sent-mail and outbox 00690 clean up stage1 (release folders and config, unregister from dcop) 00691 -- another kmail may start now --- 00692 kapp->quit(); 00693 } 00694 00695 void KMKernel:: 00696 void KMKernel:: 00697 */ 00698 00699 00700 /********************************************************************/ 00701 /* Init, Exit, and handler methods */ 00702 /********************************************************************/ 00703 void KMKernel::testDir(const char *_name) 00704 { 00705 QString foldersPath = QDir::homeDirPath() + QString( _name ); 00706 QFileInfo info( foldersPath ); 00707 if ( !info.exists() ) { 00708 if ( ::mkdir( QFile::encodeName( foldersPath ) , S_IRWXU ) == -1 ) { 00709 KMessageBox::sorry(0, i18n("KMail couldn't create folder '%1'.\n" 00710 "Please make sure that you can view and " 00711 "modify the content of the folder '%2'.") 00712 .arg( foldersPath ).arg( QDir::homeDirPath() ) ); 00713 ::exit(-1); 00714 } 00715 } 00716 if ( !info.isDir() || !info.isReadable() || !info.isWritable() ) { 00717 KMessageBox::sorry(0, i18n("The permissions of the folder '%1' are " 00718 "incorrect.\n" 00719 "Please make sure that you can view and modify " 00720 "the content of this folder.") 00721 .arg( foldersPath ) ); 00722 ::exit(-1); 00723 } 00724 } 00725 00726 00727 //----------------------------------------------------------------------------- 00728 // Open a composer for each message found in ~/dead.letter 00729 //to control 00730 void KMKernel::recoverDeadLetters(void) 00731 { 00732 KMComposeWin* win; 00733 KMMessage* msg; 00734 QDir dir = QDir::home(); 00735 QString fname = dir.path(); 00736 int i, rc, num; 00737 mDeadLetterTimer = new QTimer(this); 00738 connect(mDeadLetterTimer, SIGNAL(timeout()), this, SLOT(dumpDeadLetters())); 00739 00740 if (!dir.exists("dead.letter")) { 00741 mDeadLetterTimer->start(mDeadLetterInterval); 00742 return; 00743 } 00744 00745 fname += "/dead.letter"; 00746 KMFolderMbox folder(0, fname); 00747 00748 folder.setAutoCreateIndex(FALSE); 00749 rc = folder.open(); 00750 if (rc) 00751 { 00752 perror(QString("cannot open file "+fname).latin1()); 00753 mDeadLetterTimer->start(mDeadLetterInterval); 00754 return; 00755 } 00756 00757 folder.open(); 00758 00759 num = folder.count(); 00760 for (i=0; i<num; i++) 00761 { 00762 msg = folder.take(0); 00763 if (msg) 00764 { 00765 win = new KMComposeWin(); 00766 win->setMsg(msg, false, false, true); 00767 win->show(); 00768 } 00769 } 00770 folder.close(); 00771 QFile::remove(fname); 00772 mDeadLetterTimer->start(mDeadLetterInterval); 00773 } 00774 00775 void KMKernel::initFolders(KConfig* cfg) 00776 { 00777 QString name; 00778 00779 name = cfg->readEntry("inboxFolder"); 00780 00781 // Currently the folder manager cannot manage folders which are not 00782 // in the base folder directory. 00783 //if (name.isEmpty()) name = getenv("MAIL"); 00784 00785 if (name.isEmpty()) name = I18N_NOOP("inbox"); 00786 00787 the_inboxFolder = (KMFolder*)the_folderMgr->findOrCreate(name); 00788 00789 if (the_inboxFolder->canAccess() != 0) { 00790 emergencyExit( i18n("You do not have read/write permission to your inbox folder.") ); 00791 } 00792 00793 the_inboxFolder->setSystemFolder(TRUE); 00794 if ( the_inboxFolder->userWhoField().isEmpty() ) 00795 the_inboxFolder->setUserWhoField( QString::null ); 00796 // inboxFolder->open(); 00797 00798 the_outboxFolder = the_folderMgr->findOrCreate(cfg->readEntry("outboxFolder", I18N_NOOP("outbox"))); 00799 if (the_outboxFolder->canAccess() != 0) { 00800 emergencyExit( i18n("You do not have read/write permission to your outbox folder.") ); 00801 } 00802 00803 the_outboxFolder->setType("Out"); 00804 the_outboxFolder->setSystemFolder(TRUE); 00805 if ( the_outboxFolder->userWhoField().isEmpty() ) 00806 the_outboxFolder->setUserWhoField( QString::null ); 00807 the_outboxFolder->open(); 00808 00809 the_sentFolder = the_folderMgr->findOrCreate(cfg->readEntry("sentFolder", I18N_NOOP("sent-mail"))); 00810 if (the_sentFolder->canAccess() != 0) { 00811 emergencyExit( i18n("You do not have read/write permission to your sent-mail folder.") ); 00812 } 00813 the_sentFolder->setType("St"); 00814 the_sentFolder->setSystemFolder(TRUE); 00815 if ( the_sentFolder->userWhoField().isEmpty() ) 00816 the_sentFolder->setUserWhoField( QString::null ); 00817 // the_sentFolder->open(); 00818 00819 the_trashFolder = the_folderMgr->findOrCreate(cfg->readEntry("trashFolder", I18N_NOOP("trash"))); 00820 if (the_trashFolder->canAccess() != 0) { 00821 emergencyExit( i18n("You do not have read/write permission to your trash folder.") ); 00822 } 00823 the_trashFolder->setType("Tr"); 00824 the_trashFolder->setSystemFolder(TRUE); 00825 if ( the_trashFolder->userWhoField().isEmpty() ) 00826 the_trashFolder->setUserWhoField( QString::null ); 00827 // the_trashFolder->open(); 00828 00829 the_draftsFolder = the_folderMgr->findOrCreate(cfg->readEntry("draftsFolder", I18N_NOOP("drafts"))); 00830 if (the_draftsFolder->canAccess() != 0) { 00831 emergencyExit( i18n("You do not have read/write permission to your drafts folder.") ); 00832 } 00833 the_draftsFolder->setType("Df"); 00834 the_draftsFolder->setSystemFolder(TRUE); 00835 if ( the_draftsFolder->userWhoField().isEmpty() ) 00836 the_draftsFolder->setUserWhoField( QString::null ); 00837 the_draftsFolder->open(); 00838 } 00839 00840 00841 void KMKernel::init() 00842 { 00843 QString foldersPath; 00844 KConfig* cfg; 00845 00846 the_shuttingDown = false; 00847 the_server_is_ready = false; 00848 00849 cfg = KMKernel::config(); 00850 00851 mCryptPlugList = new CryptPlugWrapperList(); 00852 mCryptPlugList->loadFromConfig( cfg ); 00853 00854 QDir dir; 00855 QString d = locateLocal("data", "kmail/"); 00856 00857 KConfigGroupSaver saver(cfg, "General"); 00858 the_firstStart = cfg->readBoolEntry("first-start", true); 00859 cfg->writeEntry("first-start", false); 00860 the_previousVersion = cfg->readEntry("previous-version"); 00861 cfg->writeEntry("previous-version", KMAIL_VERSION); 00862 foldersPath = cfg->readEntry("folders"); 00863 00864 if (foldersPath.isEmpty()) 00865 { 00866 foldersPath = QDir::homeDirPath() + QString("/Mail"); 00867 transferMail(); 00868 } 00869 the_undoStack = new UndoStack(20); 00870 the_folderMgr = new KMFolderMgr(foldersPath); 00871 the_imapFolderMgr = new KMFolderMgr(locateLocal("data","kmail/imap"), KMImapDir); 00872 the_dimapFolderMgr = new KMFolderMgr(locateLocal("data","kmail/dimap"), KMDImapDir); 00873 the_searchFolderMgr = new KMFolderMgr(locateLocal("data","kmail/search"), KMSearchDir); 00874 the_acctMgr = new KMAcctMgr(); 00875 the_filterMgr = new KMFilterMgr(); 00876 the_popFilterMgr = new KMFilterMgr(true); 00877 the_filterActionDict = new KMFilterActionDict; 00878 00879 // moved up here because KMMessage::stripOffPrefixes is used below -ta 00880 KMMessage::readConfig(); 00881 initFolders(cfg); 00882 the_acctMgr->readConfig(); 00883 the_filterMgr->readConfig(); 00884 the_popFilterMgr->readConfig(); 00885 cleanupImapFolders(); 00886 00887 the_msgSender = new KMSender; 00888 the_server_is_ready = true; 00889 00890 { // area for config group "Composer" 00891 KConfigGroupSaver saver(cfg, "Composer"); 00892 if (cfg->readListEntry("pref-charsets").isEmpty()) 00893 { 00894 cfg->writeEntry("pref-charsets", "us-ascii,iso-8859-1,locale,utf-8"); 00895 } 00896 } 00897 mGroupware->readConfig(); 00898 mICalIface->readConfig(); 00899 // filterMgr->dump(); 00900 #if 0 //disabled for now.. 00901 the_msgIndex = new KMMsgIndex(this, "the_index"); //create the indexer 00902 the_msgIndex->init(); 00903 the_msgIndex->remove(); 00904 delete the_msgIndex; 00905 the_msgIndex = 0; 00906 #endif 00907 00908 #if 0 00909 the_weaver = new KPIM::ThreadWeaver::Weaver( this ); 00910 the_weaverLogger = new KPIM::ThreadWeaver::WeaverThreadLogger(this); 00911 the_weaverLogger->attach (the_weaver); 00912 #endif 00913 00914 } 00915 00916 void KMKernel::cleanupImapFolders() 00917 { 00918 KMAccount *acct; 00919 KMFolderNode *node = the_imapFolderMgr->dir().first(); 00920 while (node) 00921 { 00922 if (node->isDir() || ((acct = the_acctMgr->find(node->name())) 00923 && ( acct->type() == "imap" )) ) 00924 { 00925 node = the_imapFolderMgr->dir().next(); 00926 } else { 00927 the_imapFolderMgr->remove(static_cast<KMFolderImap*>(node)); 00928 node = the_imapFolderMgr->dir().first(); 00929 } 00930 } 00931 00932 node = the_dimapFolderMgr->dir().first(); 00933 while (node) 00934 { 00935 if (node->isDir() || ((acct = the_acctMgr->find(node->name())) 00936 && ( acct->type() == "cachedimap" )) ) 00937 { 00938 node = the_dimapFolderMgr->dir().next(); 00939 } else { 00940 static_cast<KMFolderCachedImap*>(node)->removeRightAway(); 00941 the_dimapFolderMgr->remove(static_cast<KMFolderCachedImap*>(node)); 00942 node = the_imapFolderMgr->dir().first(); 00943 } 00944 } 00945 00946 the_imapFolderMgr->quiet(true); 00947 for (acct = the_acctMgr->first(); acct; acct = the_acctMgr->next()) 00948 { 00949 KMFolderImap *fld; 00950 KMAcctImap *imapAcct; 00951 00952 if (acct->type() != "imap") continue; 00953 fld = static_cast<KMFolderImap*>(the_imapFolderMgr 00954 ->findOrCreate(acct->name(), false)); 00955 fld->setNoContent(true); 00956 imapAcct = static_cast<KMAcctImap*>(acct); 00957 fld->setAccount(imapAcct); 00958 imapAcct->setImapFolder(fld); 00959 fld->close(); 00960 } 00961 the_imapFolderMgr->quiet(false); 00962 00963 the_dimapFolderMgr->quiet( true ); 00964 for (acct = the_acctMgr->first(); acct; acct = the_acctMgr->next()) 00965 { 00966 KMFolderCachedImap *cfld; 00967 KMAcctCachedImap *cachedImapAcct; 00968 00969 if (acct->type() != "cachedimap" ) continue; 00970 00971 cfld = static_cast<KMFolderCachedImap*>(the_dimapFolderMgr->find(acct->name())); 00972 if (cfld == 0) { 00973 // Folder doesn't exist yet 00974 cfld = static_cast<KMFolderCachedImap*>(the_dimapFolderMgr->createFolder(acct->name(), FALSE, KMFolderTypeCachedImap)); 00975 if (!cfld) { 00976 KMessageBox::error(0,(i18n("Cannot create file `%1' in %2.\nKMail cannot start without it.").arg(acct->name()).arg(the_imapFolderMgr->basePath()))); 00977 exit(-1); 00978 } 00979 } 00980 00981 cfld->setNoContent(true); 00982 cachedImapAcct = static_cast<KMAcctCachedImap*>(acct); 00983 cfld->setAccount(cachedImapAcct); 00984 cachedImapAcct->setImapFolder(cfld); 00985 cfld->close(); 00986 } 00987 the_dimapFolderMgr->quiet( false ); 00988 } 00989 00990 bool KMKernel::doSessionManagement() 00991 { 00992 00993 // Do session management 00994 if (kapp->isRestored()){ 00995 int n = 1; 00996 while (KMMainWin::canBeRestored(n)){ 00997 //only restore main windows! (Matthias); 00998 if (KMMainWin::classNameOfToplevel(n) == "KMMainWin") 00999 (new KMMainWin)->restore(n); 01000 n++; 01001 } 01002 return true; // we were restored by SM 01003 } 01004 return false; // no, we were not restored 01005 } 01006 01007 void KMKernel::closeAllKMTopLevelWidgets() 01008 { 01009 QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); 01010 KMainWindow *window = 0; 01011 while ((window = it.current()) != 0) { 01012 ++it; 01013 if (window->inherits("KMTopLevelWidget")) 01014 window->close(TRUE); 01015 } 01016 } 01017 01018 void KMKernel::notClosedByUser() 01019 { 01020 if (!closed_by_user) // already closed 01021 return; 01022 closed_by_user = false; 01023 the_shuttingDown = true; 01024 closeAllKMTopLevelWidgets(); 01025 01026 delete the_acctMgr; 01027 the_acctMgr = 0; 01028 delete the_filterMgr; 01029 the_filterMgr = 0; 01030 delete the_msgSender; 01031 the_msgSender = 0; 01032 delete the_filterActionDict; 01033 the_filterActionDict = 0; 01034 delete the_undoStack; 01035 the_undoStack = 0; 01036 delete the_popFilterMgr; 01037 the_popFilterMgr = 0; 01038 01039 QStringList strList; 01040 QValueList<QGuardedPtr<KMFolder> > folders; 01041 KMFolder *folder; 01042 the_folderMgr->createFolderList(&strList, &folders); 01043 for (int i = 0; folders.at(i) != folders.end(); i++) 01044 { 01045 folder = *folders.at(i); 01046 if (!folder || folder->isDir()) continue; 01047 folder->close(TRUE); 01048 } 01049 strList.clear(); 01050 folders.clear(); 01051 the_searchFolderMgr->createFolderList(&strList, &folders); 01052 for (int i = 0; folders.at(i) != folders.end(); i++) 01053 { 01054 folder = *folders.at(i); 01055 if (!folder || folder->isDir()) continue; 01056 folder->close(TRUE); 01057 } 01058 folderMgr()->writeMsgDict(msgDict()); 01059 imapFolderMgr()->writeMsgDict(msgDict()); 01060 dimapFolderMgr()->writeMsgDict(msgDict()); 01061 delete the_msgIndex; 01062 the_msgIndex = 0; 01063 delete the_folderMgr; 01064 the_folderMgr = 0; 01065 delete the_imapFolderMgr; 01066 the_imapFolderMgr = 0; 01067 delete the_dimapFolderMgr; 01068 the_dimapFolderMgr = 0; 01069 delete the_searchFolderMgr; 01070 the_searchFolderMgr = 0; 01071 delete the_msgDict; 01072 the_msgDict = 0; 01073 delete mConfigureDialog; 01074 mConfigureDialog = 0; 01075 delete mWin; 01076 mWin = 0; 01077 } 01078 01079 void KMKernel::cleanup(void) 01080 { 01081 dumpDeadLetters(); 01082 mDeadLetterTimer->stop(); 01083 the_shuttingDown = TRUE; 01084 closeAllKMTopLevelWidgets(); 01085 01086 delete the_acctMgr; 01087 the_acctMgr = 0; 01088 delete the_filterMgr; 01089 the_filterMgr = 0; 01090 delete the_msgSender; 01091 the_msgSender = 0; 01092 delete the_filterActionDict; 01093 the_filterActionDict = 0; 01094 delete the_undoStack; 01095 the_undoStack = 0; 01096 delete the_popFilterMgr; 01097 the_popFilterMgr = 0; 01098 01099 #if 0 01100 delete the_weaver; 01101 the_weaver = 0; 01102 #endif 01103 01104 // Since the application has already quit we can't use 01105 // kapp->processEvents() because it will return immediately: 01106 // We first have to fire up a new event loop. 01107 // We use the timer to transfer control to the cleanupLoop function 01108 // once the event loop is running. 01109 01110 // Don't handle DCOP requests from the event loop 01111 kapp->dcopClient()->suspend(); 01112 01113 // Schedule execution of cleanupLoop 01114 QTimer::singleShot(0, this, SLOT(cleanupLoop())); 01115 01116 // Start new event loop 01117 kapp->enter_loop(); 01118 } 01119 01120 void KMKernel::cleanupProgress() 01121 { 01122 mProgress->advance( 1 ); 01123 } 01124 01125 void KMKernel::cleanupLoop() 01126 { 01127 QStringList cleanupMsgs; 01128 cleanupMsgs << i18n("Cleaning up...") 01129 << i18n("Emptying trash...") 01130 << i18n("Expiring old messages...") 01131 << i18n("Compacting folders..."); 01132 enum { CleaningUpMsgNo = 0, 01133 EmptyTrashMsgNo = 1, 01134 ExpiringOldMessagesMsgNo = 2, 01135 CompactingFoldersMsgNo = 3 }; 01136 mProgress = 0; 01137 mCleanupLabel = 0; 01138 mCleanupPopup = 0; 01139 int nrFolders = the_folderMgr->folderCount(); 01140 if (closed_by_user) 01141 { 01142 mCleanupPopup = new KPassivePopup(); 01143 QVBox *box = mCleanupPopup->standardView( kapp->aboutData()->programName(), 01144 QString::null, kapp->miniIcon()); 01145 mCleanupLabel = new QLabel( cleanupMsgs[CleaningUpMsgNo], box ); 01146 // determine the maximal width of the clean up messages 01147 QFontMetrics fm = mCleanupLabel->fontMetrics(); 01148 int maxTextWidth = 0; 01149 for( QStringList::ConstIterator it = cleanupMsgs.begin(); 01150 it != cleanupMsgs.end(); 01151 ++it ) { 01152 int w; 01153 if( maxTextWidth < ( w = fm.width( *it ) ) ) 01154 maxTextWidth = w; 01155 } 01156 01157 mProgress = new KProgress( box, "kmail-cleanupProgress" ); 01158 mProgress->setMinimumWidth( maxTextWidth+20 ); 01159 mCleanupPopup->setView( box ); 01160 01161 mProgress->setTotalSteps(nrFolders*2+2); 01162 mProgress->setProgress(1); 01163 QApplication::syncX(); 01164 mCleanupPopup->adjustSize(); 01165 mCleanupPopup->show(); 01166 kapp->processEvents(); 01167 connect(the_folderMgr, SIGNAL(progress()), this, SLOT(cleanupProgress())); 01168 } 01169 01170 01171 KConfig* config = KMKernel::config(); 01172 KConfigGroupSaver saver(config, "General"); 01173 01174 bool expire = false; 01175 // Expire old messages in all folders. 01176 if (closed_by_user) { 01177 if (config->readNumEntry("when-to-expire")==expireAtExit) { 01178 expire = true; 01179 01180 if (config->readBoolEntry("warn-before-expire", true)) { 01181 expire = canExpire(); 01182 } 01183 } 01184 } 01185 01186 if (!closed_by_user) { 01187 if (the_trashFolder) 01188 the_trashFolder->close(); 01189 } 01190 else if (the_trashFolder) { 01191 01192 the_trashFolder->close(TRUE); 01193 01194 if (config->readBoolEntry("empty-trash-on-exit", true)) 01195 { 01196 if (mCleanupLabel) 01197 { 01198 mCleanupLabel->setText( cleanupMsgs[EmptyTrashMsgNo] ); 01199 QApplication::syncX(); 01200 kapp->processEvents(); 01201 } 01202 if ( the_trashFolder->count( true ) > 0 ) 01203 the_trashFolder->expunge(); 01204 } 01205 } 01206 01207 if (mProgress) 01208 mProgress->setProgress(2); 01209 01210 if (expire) { 01211 if (mCleanupLabel) 01212 { 01213 mCleanupLabel->setText( cleanupMsgs[ExpiringOldMessagesMsgNo] ); 01214 QApplication::syncX(); 01215 kapp->processEvents(); 01216 } 01217 the_folderMgr->expireAllFolders(0); 01218 } 01219 01220 if (mProgress) 01221 mProgress->setProgress(2+nrFolders); 01222 01223 if (closed_by_user && the_folderMgr) { 01224 if (config->readBoolEntry("compact-all-on-exit", true)) 01225 { 01226 if (mCleanupLabel) 01227 { 01228 mCleanupLabel->setText( cleanupMsgs[CompactingFoldersMsgNo] ); 01229 QApplication::syncX(); 01230 kapp->processEvents(); 01231 } 01232 the_folderMgr->compactAll(); // I can compact for ages in peace now! 01233 } 01234 } 01235 if (mProgress) { 01236 mCleanupLabel->setText( cleanupMsgs[CleaningUpMsgNo] ); 01237 mProgress->setProgress(2+2*nrFolders); 01238 QApplication::syncX(); 01239 kapp->processEvents(); 01240 } 01241 01242 if (the_inboxFolder) the_inboxFolder->close(TRUE); 01243 if (the_outboxFolder) the_outboxFolder->close(TRUE); 01244 if (the_sentFolder) the_sentFolder->close(TRUE); 01245 if (the_draftsFolder) the_draftsFolder->close(TRUE); 01246 01247 mICalIface->cleanup(); 01248 01249 folderMgr()->writeMsgDict(msgDict()); 01250 imapFolderMgr()->writeMsgDict(msgDict()); 01251 dimapFolderMgr()->writeMsgDict(msgDict()); 01252 QValueList<QGuardedPtr<KMFolder> > folders; 01253 QStringList strList; 01254 KMFolder *folder; 01255 the_searchFolderMgr->createFolderList(&strList, &folders); 01256 for (int i = 0; folders.at(i) != folders.end(); i++) 01257 { 01258 folder = *folders.at(i); 01259 if (!folder || folder->isDir()) continue; 01260 folder->close(TRUE); 01261 } 01262 delete the_msgIndex; 01263 the_msgIndex = 0; 01264 delete the_folderMgr; 01265 the_folderMgr = 0; 01266 delete the_imapFolderMgr; 01267 the_imapFolderMgr = 0; 01268 delete the_dimapFolderMgr; 01269 the_dimapFolderMgr = 0; 01270 delete the_searchFolderMgr; 01271 the_searchFolderMgr = 0; 01272 delete the_msgDict; 01273 the_msgDict = 0; 01274 delete mConfigureDialog; 01275 mConfigureDialog = 0; 01276 delete mWin; 01277 mWin = 0; 01278 mCryptPlugList->setAutoDelete(true); 01279 mCryptPlugList->clear(); 01280 delete mCryptPlugList; 01281 mCryptPlugList = 0; 01282 01283 //qInstallMsgHandler(oldMsgHandler); 01284 RecentAddresses::self(KMKernel::config())->save( KMKernel::config() ); 01285 KMKernel::config()->sync(); 01286 if (mCleanupPopup) 01287 { 01288 sleep(1); // Give the user some time to realize what's going on 01289 delete mCleanupPopup; 01290 mCleanupPopup = 0; 01291 mCleanupLabel = 0; // auto-deleted child of mCleanupPopup 01292 mProgress = 0; // ditto 01293 } 01294 kapp->exit_loop(); 01295 } 01296 01297 //Isnīt this obsolete? (sven) 01298 void KMKernel::transferMail(void) 01299 { 01300 QDir dir = QDir::home(); 01301 int rc; 01302 01303 // Stefan: This function is for all the whiners who think that KMail is 01304 // broken because they cannot read mail with pine and do not 01305 // know how to fix this problem with a simple symbolic link =;-) 01306 // Markus: lol ;-) 01307 if (!dir.cd("KMail")) return; 01308 01309 rc = KMessageBox::questionYesNo(0, 01310 i18n( 01311 "The directory ~/KMail exists. From now on, KMail uses the " 01312 "directory ~/Mail for its messages.\n" 01313 "KMail can move the contents of the directory ~/KMail into " 01314 "~/Mail, but this will replace existing files with the same " 01315 "name in the directory ~/Mail (e.g. inbox).\n" 01316 "Should KMail move the mail folders now?")); 01317 01318 if (rc == KMessageBox::No) return; 01319 01320 dir.cd("/"); // otherwise we lock the directory 01321 testDir("/Mail"); 01322 system("mv -f ~/KMail/* ~/Mail"); 01323 system("mv -f ~/KMail/.??* ~/Mail"); 01324 system("rmdir ~/KMail"); 01325 } 01326 01327 01328 void KMKernel::ungrabPtrKb(void) 01329 { 01330 if(!KMainWindow::memberList) return; 01331 QWidget* widg = KMainWindow::memberList->first(); 01332 Display* dpy; 01333 01334 if (!widg) return; 01335 dpy = widg->x11Display(); 01336 XUngrabKeyboard(dpy, CurrentTime); 01337 XUngrabPointer(dpy, CurrentTime); 01338 } 01339 01340 01341 // Message handler 01342 void KMKernel::kmailMsgHandler(QtMsgType aType, const char* aMsg) 01343 { 01344 static int recurse=-1; 01345 01346 recurse++; 01347 01348 switch (aType) 01349 { 01350 case QtDebugMsg: 01351 case QtWarningMsg: 01352 kdDebug(5006) << aMsg << endl; 01353 break; 01354 01355 case QtFatalMsg: // Hm, what about using kdFatal() here? 01356 ungrabPtrKb(); 01357 kdDebug(5006) << kapp->caption() << " fatal error " 01358 << aMsg << endl; 01359 KMessageBox::error(0, aMsg); 01360 abort(); 01361 } 01362 01363 recurse--; 01364 } 01365 void KMKernel::dumpDeadLetters() 01366 { 01367 if (shuttingDown()) 01368 return; //All documents should be saved before shutting down is set! 01369 mDeadLetterTimer->stop(); 01370 QWidget *win; 01371 QDir dir = QDir::home(); 01372 QString fname = dir.path(); 01373 QFile::remove(fname + "/dead.letter.tmp"); 01374 if (KMainWindow::memberList) { 01375 QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); 01376 01377 while ((win = it.current()) != 0) { 01378 ++it; 01379 if (win->inherits("KMComposeWin")) ((KMComposeWin*)win)->deadLetter(); 01380 // delete win; // WABA: Don't delete, we might crash in there! 01381 } 01382 } 01383 QFile::remove(fname + "/dead.letter"); 01384 dir.rename("dead.letter.tmp","dead.letter"); 01385 mDeadLetterTimer->start(mDeadLetterInterval); 01386 } 01387 01388 01389 01390 void KMKernel::action(bool mailto, bool check, const QString &to, 01391 const QString &cc, const QString &bcc, 01392 const QString &subj, const QString &body, 01393 const KURL &messageFile, 01394 const KURL::List &attachURLs) 01395 { 01396 // Run the groupware setup wizard. It doesn't do anything if this isn't 01397 // the first run. Replace this with a general wizard later 01398 // #### Disabled until we have a general startup wizard. 01399 // StartupWizard::run(); 01400 01401 if (mailto) 01402 openComposer (to, cc, bcc, subj, body, 0, messageFile, attachURLs); 01403 else 01404 openReader( check ); 01405 01406 if (check) 01407 checkMail(); 01408 //Anything else? 01409 } 01410 01411 void KMKernel::byteArrayToRemoteFile(const QByteArray &aData, const KURL &aURL, 01412 bool overwrite) 01413 { 01414 KIO::Job *job = KIO::put(aURL, -1, overwrite, FALSE); 01415 putData pd; pd.url = aURL; pd.data = aData; pd.offset = 0; 01416 mPutJobs.insert(job, pd); 01417 connect(job, SIGNAL(dataReq(KIO::Job*,QByteArray&)), 01418 SLOT(slotDataReq(KIO::Job*,QByteArray&))); 01419 connect(job, SIGNAL(result(KIO::Job*)), 01420 SLOT(slotResult(KIO::Job*))); 01421 } 01422 01423 void KMKernel::slotDataReq(KIO::Job *job, QByteArray &data) 01424 { 01425 // send the data in 64 KB chunks 01426 const int MAX_CHUNK_SIZE = 64*1024; 01427 QMap<KIO::Job*, putData>::Iterator it = mPutJobs.find(job); 01428 assert(it != mPutJobs.end()); 01429 int remainingBytes = (*it).data.size() - (*it).offset; 01430 if( remainingBytes > MAX_CHUNK_SIZE ) 01431 { 01432 // send MAX_CHUNK_SIZE bytes to the receiver (deep copy) 01433 data.duplicate( (*it).data.data() + (*it).offset, MAX_CHUNK_SIZE ); 01434 (*it).offset += MAX_CHUNK_SIZE; 01435 //kdDebug( 5006 ) << "Sending " << MAX_CHUNK_SIZE << " bytes (" 01436 // << remainingBytes - MAX_CHUNK_SIZE << " bytes remain)\n"; 01437 } 01438 else 01439 { 01440 // send the remaining bytes to the receiver (deep copy) 01441 data.duplicate( (*it).data.data() + (*it).offset, remainingBytes ); 01442 (*it).data = QByteArray(); 01443 (*it).offset = 0; 01444 //kdDebug( 5006 ) << "Sending " << remainingBytes << " bytes\n"; 01445 } 01446 } 01447 01448 void KMKernel::slotResult(KIO::Job *job) 01449 { 01450 QMap<KIO::Job*, putData>::Iterator it = mPutJobs.find(job); 01451 assert(it != mPutJobs.end()); 01452 if (job->error()) 01453 { 01454 if (job->error() == KIO::ERR_FILE_ALREADY_EXIST) 01455 { 01456 if (KMessageBox::warningContinueCancel(0, 01457 i18n("File %1 exists.\nDo you want to replace it?") 01458 .arg((*it).url.prettyURL()), i18n("Save to File"), i18n("&Replace")) 01459 == KMessageBox::Continue) 01460 byteArrayToRemoteFile((*it).data, (*it).url, TRUE); 01461 } 01462 else job->showErrorDialog(); 01463 } 01464 mPutJobs.remove(it); 01465 } 01466 01467 void KMKernel::slotCollectStdOut( KProcess * proc, char * buffer, int len ) 01468 { 01469 QByteArray & ba = mStdOutCollection[proc]; 01470 // append data to ba: 01471 int oldsize = ba.size(); 01472 ba.resize( oldsize + len ); 01473 qmemmove( ba.begin() + oldsize, buffer, len ); 01474 } 01475 01476 void KMKernel::slotCollectStdErr( KProcess * proc, char * buffer, int len ) 01477 { 01478 QByteArray & ba = mStdErrCollection[proc]; 01479 // append data to ba: 01480 int oldsize = ba.size(); 01481 ba.resize( oldsize + len ); 01482 qmemmove( ba.begin() + oldsize, buffer, len ); 01483 } 01484 01485 QByteArray KMKernel::getCollectedStdOut( KProcess * proc ) 01486 { 01487 QByteArray result = mStdOutCollection[proc]; 01488 mStdOutCollection.remove(proc); 01489 return result; 01490 } 01491 01492 QByteArray KMKernel::getCollectedStdErr( KProcess * proc ) 01493 { 01494 QByteArray result = mStdErrCollection[proc]; 01495 mStdErrCollection.remove(proc); 01496 return result; 01497 } 01498 01499 void KMKernel::slotRequestConfigSync() { 01500 // ### FIXME: delay as promised in the kdoc of this function ;-) 01501 KMKernel::config()->sync(); 01502 } 01503 01504 void KMKernel::slotShowConfigurationDialog() 01505 { 01506 if( !mConfigureDialog ) { 01507 mConfigureDialog = new ConfigureDialog( 0, "configure", false ); 01508 connect( mConfigureDialog, SIGNAL( configChanged() ), 01509 this, SIGNAL( configChanged() ) ); 01510 } 01511 01512 if( mConfigureDialog->isHidden() ) 01513 mConfigureDialog->show(); 01514 else 01515 mConfigureDialog->raise(); 01516 } 01517 01518 bool KMKernel::haveSystemTrayApplet() 01519 { 01520 return !systemTrayApplets.isEmpty(); 01521 } 01522 01523 bool KMKernel::registerSystemTrayApplet( const KSystemTray* applet ) 01524 { 01525 if ( systemTrayApplets.findIndex( applet ) == -1 ) { 01526 systemTrayApplets.append( applet ); 01527 return true; 01528 } 01529 else 01530 return false; 01531 } 01532 01533 bool KMKernel::unregisterSystemTrayApplet( const KSystemTray* applet ) 01534 { 01535 QValueList<const KSystemTray*>::iterator it = 01536 systemTrayApplets.find( applet ); 01537 if ( it != systemTrayApplets.end() ) { 01538 systemTrayApplets.remove( it ); 01539 return true; 01540 } 01541 else 01542 return false; 01543 } 01544 01545 void KMKernel::emergencyExit( const QString& reason ) 01546 { 01547 QString mesg; 01548 if ( reason.length() == 0 ) { 01549 mesg = i18n("KMail encountered a fatal error and will terminate now"); 01550 } 01551 else { 01552 mesg = i18n("KMail encountered a fatal error and will " 01553 "terminate now.\nThe error was:\n%1").arg( reason ); 01554 } 01555 01556 kdWarning() << mesg << endl; 01557 KNotifyClient::userEvent( 0, mesg, KNotifyClient::Messagebox, KNotifyClient::Error ); 01558 01559 ::exit(1); 01560 } 01561 01569 void 01570 KMKernel::setCanExpire(bool expire) { 01571 allowedToExpire = expire; 01572 } 01573 01578 bool 01579 KMKernel::canExpire() { 01580 return allowedToExpire; 01581 } 01582 01586 bool KMKernel::folderIsDraftOrOutbox(const KMFolder * folder) 01587 { 01588 assert( folder ); 01589 if ( folder == the_outboxFolder || folder == the_draftsFolder ) 01590 return true; 01591 01592 QString idString = folder->idString(); 01593 if ( idString.isEmpty() ) return false; 01594 01595 // search the identities if the folder matches the drafts-folder 01596 const IdentityManager * im = identityManager(); 01597 for( IdentityManager::ConstIterator it = im->begin(); it != im->end(); ++it ) 01598 if ( (*it).drafts() == idString ) return true; 01599 return false; 01600 } 01601 01602 bool KMKernel::folderIsTrash(KMFolder * folder) 01603 { 01604 assert(folder); 01605 if (folder == the_trashFolder) return true; 01606 if (folder->folderType() != KMFolderTypeImap) return false; 01607 KMFolderImap *fi = static_cast<KMFolderImap*>(folder); 01608 if (fi->account() && fi->account()->trash() == fi->idString()) 01609 return true; 01610 return false; 01611 } 01612 01613 bool KMKernel::folderIsSentMailFolder( const KMFolder * folder ) 01614 { 01615 assert( folder ); 01616 if ( folder == the_sentFolder ) 01617 return true; 01618 01619 QString idString = folder->idString(); 01620 if ( idString.isEmpty() ) return false; 01621 01622 // search the identities if the folder matches the sent-folder 01623 const IdentityManager * im = identityManager(); 01624 for( IdentityManager::ConstIterator it = im->begin(); it != im->end(); ++it ) 01625 if ( (*it).fcc() == idString ) return true; 01626 return false; 01627 } 01628 01629 IdentityManager * KMKernel::identityManager() { 01630 if ( !mIdentityManager ) { 01631 kdDebug(5006) << "instantating IdentityManager" << endl; 01632 mIdentityManager = new IdentityManager( this, "mIdentityManager" ); 01633 } 01634 return mIdentityManager; 01635 } 01636 01637 KMMsgDict *KMKernel::msgDict() 01638 { 01639 if (the_msgDict) 01640 return the_msgDict; 01641 the_msgDict = new KMMsgDict; 01642 folderMgr()->readMsgDict(msgDict()); 01643 imapFolderMgr()->readMsgDict(msgDict()); 01644 dimapFolderMgr()->readMsgDict(msgDict()); 01645 return the_msgDict; 01646 } 01647 01648 KMMsgIndex *KMKernel::msgIndex() 01649 { 01650 return the_msgIndex; 01651 } 01652 01653 KMainWindow* KMKernel::mainWin() 01654 { 01655 if (KMainWindow::memberList) { 01656 KMainWindow *kmWin = 0; 01657 01658 // First look for a KMMainWin. 01659 for (kmWin = KMainWindow::memberList->first(); kmWin; 01660 kmWin = KMainWindow::memberList->next()) 01661 if (kmWin->isA("KMMainWin")) 01662 return kmWin; 01663 01664 // There is no KMMainWin. Use any other KMainWindow instead (e.g. in 01665 // case we are running inside Kontact) because we anyway only need 01666 // it for modal message boxes and for KNotify events. 01667 kmWin = KMainWindow::memberList->first(); 01668 if ( kmWin ) 01669 return kmWin; 01670 } 01671 01672 // There's not a single KMainWindow. Create a KMMainWin. 01673 // This could happen if we want to pop up an error message 01674 // while we are still doing the startup wizard and no other 01675 // KMainWindow is running. 01676 mWin = new KMMainWin; 01677 return mWin; 01678 } 01679 01680 01684 void KMKernel::slotEmptyTrash() 01685 { 01686 QString title = i18n("Empty Trash"); 01687 QString text = i18n("Are you sure you want to empty the trash?"); 01688 if (KMessageBox::warningContinueCancel(0, text, title, 01689 KStdGuiItem::cont(), "confirm_empty_trash") 01690 != KMessageBox::Continue) 01691 { 01692 return; 01693 } 01694 01695 for (KMAccount* acct = acctMgr()->first(); acct; acct = acctMgr()->next()) 01696 { 01697 KMFolder* trash = folderMgr()->findIdString(acct->trash()); 01698 if (trash) 01699 { 01700 trash->expunge(); 01701 } 01702 } 01703 } 01704 01705 #if KDE_IS_VERSION( 3, 1, 92 ) 01706 KConfig* KMKernel::config() 01707 { 01708 assert(mySelf); 01709 if (!mySelf->mConfig) 01710 { 01711 mySelf->mConfig = KSharedConfig::openConfig( "kmailrc" ); 01712 // Check that all updates have been run on the config file: 01713 KMail::checkConfigUpdates(); 01714 } 01715 return mySelf->mConfig; 01716 } 01717 #else 01718 KConfig *KMKernel::myConfig = 0; 01719 static KStaticDeleter<KConfig> myConfigSD; 01720 01721 KConfig* KMKernel::config() 01722 { 01723 if (!myConfig) 01724 myConfig = myConfigSD.setObject(myConfig, new KConfig( "kmailrc")); 01725 return myConfig; 01726 } 01727 #endif 01728 01729 KMGroupware & KMKernel::groupware() 01730 { 01731 assert( mGroupware ); 01732 return *mGroupware; 01733 } 01734 01735 KMailICalIfaceImpl& KMKernel::iCalIface() 01736 { 01737 assert( mICalIface ); 01738 return *mICalIface; 01739 } 01740 01741 01742 #include "kmkernel.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jul 28 23:58:02 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003