1 /* -*- mode: C++; c-file-style: "gnu" -*- */
5 #include <config-kmail.h>
7 #include "globalsettings.h"
8 #include "broadcaststatus.h"
9 using KPIM::BroadcastStatus
;
10 #include "kmstartup.h"
11 #include "kmmainwin.h"
13 #include "kmmsgpart.h"
14 #include "kmreadermainwin.h"
15 #include "kmfoldermgr.h"
16 #include "kmfoldercachedimap.h"
17 #include "kmacctcachedimap.h"
18 #include "kmfiltermgr.h"
19 #include "kmfilteraction.h"
20 #define REALLY_WANT_KMSENDER
22 #undef REALLY_WANT_KMSENDER
23 #include "undostack.h"
24 #include "accountmanager.h"
25 using KMail::AccountManager
;
26 #include <kpimutils/kfileio.h>
27 #include "kmversion.h"
28 #include "kmreaderwin.h"
29 #include "kmmainwidget.h"
30 #include "recentaddresses.h"
31 using KPIM::RecentAddresses
;
32 #include "kmmsgdict.h"
33 #include <kpimidentities/identity.h>
34 #include <kpimidentities/identitymanager.h>
35 #include "configuredialog.h"
36 #include "kmcommands.h"
37 #include "kmsystemtray.h"
39 #include <mailtransport/transport.h>
40 #include <mailtransport/transportmanager.h>
43 #include <kwindowsystem.h>
44 #include "kmailicalifaceimpl.h"
45 #include "mailserviceimpl.h"
46 using KMail::MailServiceImpl
;
47 #include "jobscheduler.h"
48 #include "templateparser.h"
49 using KMail::TemplateParser
;
50 #include "mainfolderview.h"
52 #include <kmessagebox.h>
53 #include <knotification.h>
54 #include <kstandarddirs.h>
56 #include <kpassivepopup.h>
57 #include <kapplication.h>
58 #include <ksystemtrayicon.h>
59 #include <kconfiggroup.h>
60 #include <libkpgp/kpgp.h>
62 #include <kio/jobuidelegate.h>
63 #include <kio/netaccess.h>
65 using KWallet::Wallet
;
66 #include "actionscheduler.h"
75 #include <sys/types.h>
83 #include <kcmdlineargs.h>
84 #include <kstartupinfo.h>
85 #include <kmailadaptor.h>
86 #include "kmailinterface.h"
88 #include "folderadaptor.h"
89 #include "groupware_types.h"
91 static KMKernel
* mySelf
= 0;
93 /********************************************************************/
94 /* Constructor and destructor */
95 /********************************************************************/
96 KMKernel::KMKernel (QObject
*parent
, const char *name
) :
98 mIdentityManager(0), mConfigureDialog(0), mICalIface(0), mMailService(0),
99 mContextMenuShown( false ), mWallet( 0 )
102 setObjectName( name
);
104 the_startingUp
= true;
105 closed_by_user
= true;
106 the_firstInstance
= true;
109 the_outboxFolder
= 0;
112 the_draftsFolder
= 0;
113 the_templatesFolder
= 0;
116 the_imapFolderMgr
= 0;
117 the_dimapFolderMgr
= 0;
118 the_searchFolderMgr
= 0;
122 the_popFilterMgr
= 0;
123 the_filterActionDict
= 0;
127 mMailCheckAborted
= false;
129 // make sure that we check for config updates before doing anything else
131 // this shares the kmailrc parsing too (via KSharedConfig), and reads values from it
132 // so better do it here, than in some code where changing the group of config()
133 // would be unexpected
134 GlobalSettings::self();
136 mJobScheduler
= new JobScheduler( this );
137 mICalIface
= new KMailICalIfaceImpl();
139 mXmlGuiInstance
= KComponentData();
143 netCodec
= QTextCodec::codecForName( KGlobal::locale()->encoding() );
145 // In the case of Japan. Japanese locale name is "eucjp" but
146 // The Japanese mail systems normally used "iso-2022-jp" of locale name.
147 // We want to change locale name from eucjp to iso-2022-jp at KMail only.
149 // (Introduction to i18n, 6.6 Limit of Locale technology):
150 // EUC-JP is the de-facto standard for UNIX systems, ISO 2022-JP
151 // is the standard for Internet, and Shift-JIS is the encoding
152 // for Windows and Macintosh.
153 if ( netCodec
->name().toLower() == "eucjp"
154 #if defined Q_WS_WIN || defined Q_WS_MACX
155 || netCodec
->name().toLower() == "shift-jis" // OK?
159 netCodec
= QTextCodec::codecForName("jis7");
160 // QTextCodec *cdc = QTextCodec::codecForName("jis7");
161 // QTextCodec::setCodecForLocale(cdc);
162 // KGlobal::locale()->setEncoding(cdc->mibEnum());
165 connect( MailTransport::TransportManager::self(),
166 SIGNAL(transportRemoved(int,QString
)),
167 SLOT(transportRemoved(int,QString
)) );
168 connect( MailTransport::TransportManager::self(),
169 SIGNAL(transportRenamed(int,QString
,QString
)),
170 SLOT(transportRenamed(int,QString
,QString
)) );
173 KMKernel::~KMKernel ()
175 QMap
<KIO::Job
*, putData
>::Iterator it
= mPutJobs
.begin();
176 while ( it
!= mPutJobs
.end() )
178 KIO::Job
*job
= it
.key();
179 mPutJobs
.erase( it
);
181 it
= mPutJobs
.begin();
189 GlobalSettings::self()->writeConfig();
196 void KMKernel::setupDBus()
198 (void) new KmailAdaptor( this );
199 QDBusConnection::sessionBus().registerObject( "/KMail", this );
200 mICalIface
->registerWithDBus();
201 mICalIface
->readConfig();
202 mMailService
= new MailServiceImpl();
205 bool KMKernel::handleCommandLine( bool noArgsOpensReader
)
207 QString to
, cc
, bcc
, subj
, body
;
208 QStringList customHeaders
;
210 KUrl::List attachURLs
;
212 bool checkMail
= false;
213 bool viewOnly
= false;
214 bool calledWithSession
= false; // for ignoring '-session foo'
217 KCmdLineArgs
*args
= KCmdLineArgs::parsedArgs();
218 if (args
->isSet("subject"))
220 subj
= args
->getOption("subject");
221 // if kmail is called with 'kmail -session abc' then this doesn't mean
222 // that the user wants to send a message with subject "ession" but
223 // (most likely) that the user clicked on KMail's system tray applet
224 // which results in KMKernel::raise() calling "kmail kmail newInstance"
225 // via D-Bus which apparently executes the application with the original
226 // command line arguments and those include "-session ..." if
227 // kmail/kontact was restored by session management
228 if ( subj
== "ession" ) {
230 calledWithSession
= true;
236 if (args
->isSet("cc"))
239 cc
= args
->getOption("cc");
242 if (args
->isSet("bcc"))
245 bcc
= args
->getOption("bcc");
248 if (args
->isSet("msg"))
251 messageFile
.setPath( args
->getOption("msg") );
254 if (args
->isSet("body"))
257 body
= args
->getOption("body");
260 QStringList attachList
= args
->getOptionList("attach");
261 if (!attachList
.isEmpty())
264 for ( QStringList::Iterator it
= attachList
.begin() ; it
!= attachList
.end() ; ++it
)
265 if ( !(*it
).isEmpty() )
266 attachURLs
+= KUrl( *it
);
269 customHeaders
= args
->getOptionList("header");
271 if (args
->isSet("composer"))
274 if (args
->isSet("check"))
277 if ( args
->isSet( "view" ) ) {
279 const QString filename
=
280 args
->getOption( "view" );
281 messageFile
= KUrl( filename
);
282 if ( !messageFile
.isValid() ) {
283 messageFile
= KUrl();
284 messageFile
.setPath( filename
);
288 if ( !calledWithSession
) {
289 // only read additional command line arguments if kmail/kontact is
290 // not called with "-session foo"
291 for(int i
= 0; i
< args
->count(); i
++)
293 if (args
->arg(i
).startsWith("mailto:", Qt::CaseInsensitive
))
294 to
+= args
->url(i
).path() + ", ";
296 QString tmpArg
= args
->arg(i
);
298 if (url
.isValid() && !url
.protocol().isEmpty())
305 if ( !to
.isEmpty() ) {
306 // cut off the superfluous trailing ", "
307 to
.truncate( to
.length() - 2 );
311 if ( !calledWithSession
)
314 if ( !noArgsOpensReader
&& !mailto
&& !checkMail
&& !viewOnly
)
318 viewMessage( messageFile
);
320 action( mailto
, checkMail
, to
, cc
, bcc
, subj
, body
, messageFile
,
321 attachURLs
, customHeaders
);
325 /********************************************************************/
326 /* DCOP-callable, and command line actions */
327 /********************************************************************/
328 void KMKernel::checkMail () //might create a new reader but won't show!!
330 if ( !kmkernel
->askToGoOnline() )
332 kmkernel
->acctMgr()->checkMail( false );
335 QStringList
KMKernel::accounts()
337 return kmkernel
->acctMgr()->getAccounts();
340 void KMKernel::checkAccount( const QString
&account
) //might create a new reader but won't show!!
343 if ( account
.isEmpty() )
346 KMAccount
* acct
= kmkernel
->acctMgr()->findByName( account
);
348 kmkernel
->acctMgr()->singleCheckMail (acct
, false );
352 void KMKernel::openReader( bool onlyCheck
)
355 KMainWindow
*ktmw
= 0;
358 foreach ( KMainWindow
*window
, KMainWindow::memberList() )
360 if ( ::qobject_cast
<KMMainWin
*>( window
) )
369 mWin
= (KMMainWin
*) ktmw
;
370 activate
= !onlyCheck
; // existing window: only activate if not --check
375 mWin
= new KMMainWin
;
377 activate
= false; // new window: no explicit activation (#73591)
381 // Activate window - doing this instead of KWindowSystem::activateWindow(mWin->winId());
382 // so that it also works when called from KMailApplication::newInstance()
383 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
384 KStartupInfo::setNewStartupId( mWin
, kapp
->startupId() );
389 int KMKernel::openComposer( const QString
&to
, const QString
&cc
,
390 const QString
&bcc
, const QString
&subject
,
391 const QString
&body
, bool hidden
,
392 const QString
&messageFile
,
393 const QStringList
&attachmentPaths
,
394 const QStringList
&customHeaders
)
397 KMMessage
*msg
= new KMMessage
;
399 msg
->setCharset("utf-8");
400 // tentatively decode to, cc and bcc because invokeMailer calls us with
401 // RFC 2047 encoded addresses in order to protect non-ASCII email addresses
403 msg
->setTo( KMMsgBase::decodeRFC2047String( to
.toLatin1() ) );
405 msg
->setCc( KMMsgBase::decodeRFC2047String( cc
.toLatin1() ) );
407 msg
->setBcc( KMMsgBase::decodeRFC2047String( bcc
.toLatin1() ) );
408 if (!subject
.isEmpty()) msg
->setSubject(subject
);
410 KUrl messageUrl
= KUrl( messageFile
);
411 if ( !messageUrl
.isEmpty() && messageUrl
.isLocalFile() ) {
412 QByteArray str
= KPIMUtils::kFileToByteArray( messageUrl
.path(), true, false );
413 if( !str
.isEmpty() ) {
414 msg
->setBody( QString::fromLocal8Bit( str
.data(), str
.size() ).toUtf8() );
417 TemplateParser
parser( msg
, TemplateParser::NewMessage
,
418 QString(), false, false, false );
419 parser
.process( NULL
, NULL
);
422 else if ( !body
.isEmpty() ) {
423 msg
->setBody( body
.toUtf8() );
426 TemplateParser
parser( msg
, TemplateParser::NewMessage
,
427 QString(), false, false, false );
428 parser
.process( 0, 0 );
431 if ( !customHeaders
.isEmpty() )
433 for ( QStringList::ConstIterator it
= customHeaders
.begin() ; it
!= customHeaders
.end() ; ++it
)
434 if ( !(*it
).isEmpty() )
436 const int pos
= (*it
).indexOf( ':' );
439 QString header
= (*it
).left( pos
).trimmed();
440 QString value
= (*it
).mid( pos
+1 ).trimmed();
441 if ( !header
.isEmpty() && !value
.isEmpty() )
442 msg
->setHeaderField( header
.toUtf8(), value
);
447 KMail::Composer
* cWin
= KMail::makeComposer( msg
);
448 cWin
->setCharset( "", true );
449 KUrl::List attachURLs
= KUrl::List( attachmentPaths
);
450 for ( KUrl::List::ConstIterator it
= attachURLs
.begin() ; it
!= attachURLs
.end() ; ++it
)
451 cWin
->addAttach( (*it
) );
454 // Activate window - doing this instead of KWindowSystem::activateWindow(cWin->winId());
455 // so that it also works when called from KMailApplication::newInstance()
456 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
457 KStartupInfo::setNewStartupId( cWin
, kapp
->startupId() );
463 int KMKernel::openComposer (const QString
&to
, const QString
&cc
,
464 const QString
&bcc
, const QString
&subject
,
465 const QString
&body
, bool hidden
,
466 const QString
&attachName
,
467 const QByteArray
&attachCte
,
468 const QByteArray
&attachData
,
469 const QByteArray
&attachType
,
470 const QByteArray
&attachSubType
,
471 const QByteArray
&attachParamAttr
,
472 const QString
&attachParamValue
,
473 const QByteArray
&attachContDisp
,
474 const QByteArray
&attachCharset
,
475 unsigned int identity
)
479 KMMessage
*msg
= new KMMessage
;
480 KMMessagePart
*msgPart
= 0;
482 msg
->setCharset( "utf-8" );
483 if ( !cc
.isEmpty() ) msg
->setCc(cc
);
484 if ( !bcc
.isEmpty() ) msg
->setBcc(bcc
);
485 if ( !subject
.isEmpty() ) msg
->setSubject(subject
);
486 if ( !to
.isEmpty() ) msg
->setTo(to
);
487 if ( identity
> 0 ) msg
->setHeaderField( "X-KMail-Identity", QString::number( identity
) );
488 if ( !body
.isEmpty() ) {
489 msg
->setBody(body
.toUtf8());
491 TemplateParser
parser( msg
, TemplateParser::NewMessage
,
492 QString(), false, false, false );
493 parser
.process( NULL
, NULL
);
496 bool iCalAutoSend
= false;
497 bool noWordWrap
= false;
498 bool isICalInvitation
= false;
499 KConfigGroup
options( config(), "Groupware" );
500 if ( !attachData
.isEmpty() ) {
501 isICalInvitation
= attachName
== "cal.ics" &&
502 attachType
== "text" &&
503 attachSubType
== "calendar" &&
504 attachParamAttr
== "method";
505 // Remove BCC from identity on ical invitations (https://intevation.de/roundup/kolab/issue474)
506 if ( isICalInvitation
&& bcc
.isEmpty() )
508 if ( isICalInvitation
&&
509 GlobalSettings::self()->legacyBodyInvites() ) {
510 // KOrganizer invitation caught and to be sent as body instead
511 msg
->setBody( attachData
);
512 msg
->setHeaderField( "Content-Type",
513 QString( "text/calendar; method=%1; "
514 "charset=\"utf-8\"" ).
515 arg( attachParamValue
) );
517 iCalAutoSend
= true; // no point in editing raw ICAL
518 noWordWrap
= true; // we shant word wrap inline invitations
520 // Just do what we're told to do
521 msgPart
= new KMMessagePart
;
522 msgPart
->setName( attachName
);
523 msgPart
->setCteStr( attachCte
);
524 msgPart
->setBodyEncoded( attachData
);
525 msgPart
->setTypeStr( attachType
);
526 msgPart
->setSubtypeStr( attachSubType
);
527 msgPart
->setParameter( attachParamAttr
, attachParamValue
);
528 if( ! GlobalSettings::self()->exchangeCompatibleInvitations() ) {
529 msgPart
->setContentDisposition( attachContDisp
);
531 if( !attachCharset
.isEmpty() ) {
532 // kDebug(5006) << "Set attachCharset to" << attachCharset;
533 msgPart
->setCharset( attachCharset
);
535 // Don't show the composer window if the automatic sending is checked
536 iCalAutoSend
= GlobalSettings::self()->automaticSending();
540 KMail::Composer
* cWin
= KMail::makeComposer();
541 cWin
->setMsg( msg
, !isICalInvitation
/* mayAutoSign */ );
542 cWin
->setSigningAndEncryptionDisabled( isICalInvitation
543 && GlobalSettings::self()->legacyBodyInvites() );
544 cWin
->setAutoDelete( true );
546 cWin
->disableWordWrap();
548 cWin
->setCharset( "", true );
550 cWin
->addAttach(msgPart
);
552 if ( !hidden
&& !iCalAutoSend
) {
554 // Activate window - doing this instead of KWin::activateWindow(cWin->winId());
555 // so that it also works when called from KMailApplication::newInstance()
556 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
557 KStartupInfo::setNewStartupId( cWin
, kapp
->startupId() );
566 void KMKernel::setDefaultTransport( const QString
& transport
)
568 MailTransport::Transport
*t
= MailTransport::TransportManager::self()->transportByName( transport
, false );
570 kWarning(5006) <<"The transport you entered is not available";
573 MailTransport::TransportManager::self()->setDefaultTransport( t
->id() );
576 QDBusObjectPath
KMKernel::openComposer( const QString
&to
, const QString
&cc
,
578 const QString
&subject
,
579 const QString
&body
, bool hidden
)
581 KMMessage
*msg
= new KMMessage
;
583 msg
->setCharset("utf-8");
584 if (!cc
.isEmpty()) msg
->setCc(cc
);
585 if (!bcc
.isEmpty()) msg
->setBcc(bcc
);
586 if (!subject
.isEmpty()) msg
->setSubject(subject
);
587 if (!to
.isEmpty()) msg
->setTo(to
);
588 if ( !body
.isEmpty() ) {
589 msg
->setBody(body
.toUtf8());
591 TemplateParser
parser( msg
, TemplateParser::NewMessage
,
592 QString(), false, false, false );
593 parser
.process( NULL
, NULL
);
596 KMail::Composer
* cWin
= KMail::makeComposer( msg
);
597 cWin
->setCharset("", true);
600 // Activate window - doing this instead of KWindowSystem::activateWindow(cWin->winId());
601 // so that it also works when called from KMailApplication::newInstance()
602 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
603 KStartupInfo::setNewStartupId( cWin
, kapp
->startupId() );
607 return QDBusObjectPath(cWin
->dbusObjectPath());
610 QDBusObjectPath
KMKernel::newMessage( const QString
&to
,
615 const QString
& /*messageFile*/,
616 const QString
&_attachURL
)
618 KUrl
attachURL( _attachURL
);
619 KMMessage
*msg
= new KMMessage
;
620 KMFolder
*folder
= 0;
624 //create message with required folder identity
625 folder
= currentFolder();
626 id
= folder
? folder
->identity() : 0;
628 msg
->initHeader( id
);
629 msg
->setCharset( "utf-8" );
631 if ( !to
.isEmpty() ) {
634 if ( !cc
.isEmpty() ) {
637 if ( !bcc
.isEmpty() ) {
641 TemplateParser
parser( msg
, TemplateParser::NewMessage
,
642 QString(), false, false, false );
643 parser
.process( NULL
, folder
);
645 KMail::Composer
*win
= makeComposer( msg
, id
);
647 //Add the attachment if we have one
648 if ( !attachURL
.isEmpty() && attachURL
.isValid() ) {
649 win
->addAttach( attachURL
);
652 //only show window when required
656 return QDBusObjectPath( win
->dbusObjectPath() );
659 int KMKernel::viewMessage( const KUrl
& messageFile
)
661 KMOpenMsgCommand
*openCommand
= new KMOpenMsgCommand( 0, messageFile
);
663 openCommand
->start();
668 int KMKernel::sendCertificate( const QString
& to
, const QByteArray
& certData
)
670 KMMessage
*msg
= new KMMessage
;
672 msg
->setCharset("utf-8");
673 msg
->setSubject( i18n( "Certificate Signature Request" ) );
674 if (!to
.isEmpty()) msg
->setTo(to
);
675 // ### Make this message customizable via KIOSK
676 msg
->setBody( i18n( "Please create a certificate from attachment and return to sender." ).toUtf8() );
678 KMail::Composer
* cWin
= KMail::makeComposer( msg
);
679 cWin
->setCharset("", true);
680 cWin
->slotSetAlwaysSend( true );
681 if (!certData
.isEmpty()) {
682 KMMessagePart
*msgPart
= new KMMessagePart
;
683 msgPart
->setName("smime.p10");
684 msgPart
->setCteStr("base64");
685 msgPart
->setBodyEncodedBinary(certData
);
686 msgPart
->setTypeStr("application");
687 msgPart
->setSubtypeStr("pkcs10");
688 msgPart
->setContentDisposition("attachment; filename=smime.p10");
689 cWin
->addAttach(msgPart
);
696 int KMKernel::dbusAddMessage( const QString
& foldername
,
697 const QString
& messageFile
,
698 const QString
& MsgStatusFlags
)
702 if ( foldername
.isEmpty() || foldername
.startsWith('.'))
706 bool readFolderMsgIds
= false;
707 QString _foldername
= foldername
.trimmed();
708 _foldername
= _foldername
.remove( '\\' ); //try to prevent ESCAPE Sequences
710 if ( foldername
!= mAddMessageLastFolder
) {
711 mAddMessageMsgIds
.clear();
712 readFolderMsgIds
= true;
713 mAddMessageLastFolder
= foldername
;
716 KUrl
msgUrl( messageFile
);
717 if ( !msgUrl
.isEmpty() && msgUrl
.isLocalFile() ) {
719 const QByteArray messageText
=
720 KPIMUtils::kFileToByteArray( msgUrl
.path(), true, false );
721 if ( messageText
.isEmpty() )
724 KMMessage
*msg
= new KMMessage();
725 msg
->fromString( messageText
);
727 if (readFolderMsgIds
) {
728 if ( foldername
.contains("/")) {
729 QString tmp_fname
= "";
730 KMFolder
*folder
= NULL
;
731 KMFolderDir
*subfolder
;
734 QStringList subFList
= _foldername
.split('/', QString::SkipEmptyParts
);
736 for ( QStringList::Iterator it
= subFList
.begin(); it
!= subFList
.end(); ++it
) {
737 QString _newFolder
= *it
;
738 if(_newFolder
.startsWith('.')) return -1;
741 folder
= the_folderMgr
->findOrCreate(*it
, false);
744 tmp_fname
= '/' + *it
;
749 subfolder
= folder
->createChildFolder();
750 tmp_fname
+= '/' + *it
;
751 if(!the_folderMgr
->getFolderByURL( tmp_fname
)) {
752 folder
= the_folderMgr
->createFolder(*it
, false, folder
->folderType(), subfolder
);
755 if(!(folder
= the_folderMgr
->getFolderByURL( tmp_fname
))) return -1;
759 mAddMsgCurrentFolder
= the_folderMgr
->getFolderByURL( tmp_fname
);
760 if(!folder
) return -1;
764 mAddMsgCurrentFolder
= the_folderMgr
->findOrCreate(_foldername
, false);
768 if ( mAddMsgCurrentFolder
) {
769 if (readFolderMsgIds
) {
772 // Try to determine if a message already exists in
773 // the folder. The message id that is searched for, is
774 // the subject line + the date. This should be quite
775 // unique. The change that a given date with a given
776 // subject is in the folder twice is very small.
777 // If the subject is empty, the fromStrip string
780 // NEW COMMENT from Danny Kukawka (danny.kukawka@web.de):
781 // subject line + the date is only unique if the following
782 // return a correct unique value:
783 // time_t DT = mb->date();
784 // QString dt = ctime(&DT);
785 // But if the datestring in the Header isn't RFC conform
786 // subject line + the date isn't unique.
788 // The only uique headerfield is the Message-ID. In some
789 // cases this could be empty. I then I use the
790 // subject line + dateStr .
794 mAddMsgCurrentFolder
->open( "dbusadd" );
795 for( i
=0; i
<mAddMsgCurrentFolder
->count(); i
++) {
796 KMMsgBase
*mb
= mAddMsgCurrentFolder
->getMsgBase(i
);
797 QString id
= mb
->msgIdMD5();
798 if ( id
.isEmpty() ) {
801 id
= mb
->fromStrip();
808 //fprintf(stderr,"%s\n",(const char *) id);
809 if ( !id
.isEmpty() ) {
810 mAddMessageMsgIds
.append(id
);
813 mAddMsgCurrentFolder
->close( "dbusadd" );
816 QString msgId
= msg
->msgIdMD5();
817 if ( msgId
.isEmpty()) {
818 msgId
= msg
->subject();
819 if ( msgId
.isEmpty() )
820 msgId
= msg
->fromStrip();
821 if ( msgId
.isEmpty() )
822 msgId
= msg
->toStrip();
824 msgId
+= msg
->dateStr();
827 int k
= mAddMessageMsgIds
.indexOf( msgId
);
828 //fprintf(stderr,"find %s = %d\n",(const char *) msgId,k);
831 if ( !msgId
.isEmpty() ) {
832 mAddMessageMsgIds
.append( msgId
);
835 if ( !MsgStatusFlags
.isEmpty() ) {
836 msg
->status().setStatusFromStr(MsgStatusFlags
);
840 if ( mAddMsgCurrentFolder
->addMsg( msg
, &index
) == 0 ) {
841 mAddMsgCurrentFolder
->unGetMsg( index
);
849 //qDebug( "duplicate: " + msgId + "; subj: " + msg->subject() + ", from: " + msgId = msg->fromStrip());
861 void KMKernel::dbusResetAddMessage()
863 mAddMessageMsgIds
.clear();
864 mAddMessageLastFolder
.clear();
867 int KMKernel::dbusAddMessage_fastImport( const QString
& foldername
,
868 const QString
& messageFile
,
869 const QString
& MsgStatusFlags
)
871 // Use this function to import messages without
872 // search for already existing emails.
875 if ( foldername
.isEmpty() || foldername
.startsWith('.'))
879 bool createNewFolder
= false;
881 QString _foldername
= foldername
.trimmed();
882 _foldername
= _foldername
.remove( '\\' ); //try to prevent ESCAPE Sequences
884 if ( foldername
!= mAddMessageLastFolder
) {
885 createNewFolder
= true;
886 mAddMessageLastFolder
= foldername
;
889 KUrl
msgUrl( messageFile
);
890 if ( !msgUrl
.isEmpty() && msgUrl
.isLocalFile() ) {
891 const QByteArray messageText
=
892 KPIMUtils::kFileToByteArray( msgUrl
.path(), true, false );
893 if ( messageText
.isEmpty() )
896 KMMessage
*msg
= new KMMessage();
897 msg
->fromString( messageText
);
899 if (createNewFolder
) {
900 if ( foldername
.contains("/")) {
901 QString tmp_fname
= "";
902 KMFolder
*folder
= NULL
;
903 KMFolderDir
*subfolder
;
906 QStringList subFList
= _foldername
.split('/', QString::SkipEmptyParts
);
908 for ( QStringList::Iterator it
= subFList
.begin(); it
!= subFList
.end(); ++it
) {
909 QString _newFolder
= *it
;
910 if(_newFolder
.startsWith('.')) return -1;
913 folder
= the_folderMgr
->findOrCreate(*it
, false);
916 tmp_fname
= '/' + *it
;
921 subfolder
= folder
->createChildFolder();
922 tmp_fname
+= '/' + *it
;
923 if(!the_folderMgr
->getFolderByURL( tmp_fname
)) {
924 folder
= the_folderMgr
->createFolder(*it
, false, folder
->folderType(), subfolder
);
926 if(!(folder
= the_folderMgr
->getFolderByURL( tmp_fname
))) return -1;
930 mAddMsgCurrentFolder
= the_folderMgr
->getFolderByURL( tmp_fname
);
931 if(!folder
) return -1;
935 mAddMsgCurrentFolder
= the_folderMgr
->findOrCreate(_foldername
, false);
939 if ( mAddMsgCurrentFolder
) {
942 if( !MsgStatusFlags
.isEmpty() ) {
943 msg
->status().setStatusFromStr(MsgStatusFlags
);
946 if ( mAddMsgCurrentFolder
->addMsg( msg
, &index
) == 0 ) {
947 mAddMsgCurrentFolder
->unGetMsg( index
);
964 QStringList
KMKernel::folderList() const
967 const QString localPrefix
= "/Local";
968 folders
<< localPrefix
;
969 the_folderMgr
->getFolderURLS( folders
, localPrefix
);
970 the_imapFolderMgr
->getFolderURLS( folders
);
971 the_dimapFolderMgr
->getFolderURLS( folders
);
975 QString
KMKernel::getFolder( const QString
& vpath
)
978 const QString localPrefix
= "/Local";
979 if ( the_folderMgr
->getFolderByURL( vpath
) )
981 else if ( vpath
.startsWith( localPrefix
) && the_folderMgr
->getFolderByURL( vpath
.mid( localPrefix
.length() ) ) )
982 adaptorName
=vpath
.mid( localPrefix
.length() );
983 else if ( the_imapFolderMgr
->getFolderByURL( vpath
) )
985 else if (the_dimapFolderMgr
->getFolderByURL( vpath
) )
987 if( !adaptorName
.isEmpty())
991 folderAdaptor
->unregisterobject();
992 delete folderAdaptor
;
994 folderAdaptor
= new KMail::FolderAdaptor(adaptorName
);
997 kWarning(5006) << "Folder not found:" << vpath
;
1001 void KMKernel::raise()
1003 QDBusInterface
iface( KMAIL_DBUS_SERVICE
, "/MainApplication",
1004 "org.kde.KUniqueApplication",
1005 QDBusConnection::sessionBus());
1006 QDBusReply
<int> reply
;
1007 if ( !iface
.isValid() || !( reply
= iface
.call( "newInstance" ) ).isValid() )
1009 QDBusError err
= iface
.lastError();
1010 kError() << "Communication problem with KMail. "
1011 << "Error message was:" << err
.name() << ": \"" << err
.message() << "\"";
1016 bool KMKernel::showMail( quint32 serialNumber
, const QString
& /* messageId */ )
1018 KMMainWidget
*mainWidget
= 0;
1020 // First look for a KMainWindow.
1021 foreach ( KMainWindow
* window
, KMainWindow::memberList() ) {
1022 // Then look for a KMMainWidget.
1023 QList
<KMMainWidget
*> l
= window
->findChildren
<KMMainWidget
*>();
1024 if ( !l
.isEmpty() && l
.first() ) {
1025 mainWidget
= l
.first();
1026 if ( window
->isActiveWindow() )
1033 KMFolder
*folder
= 0;
1034 KMMsgDict::instance()->getLocation(serialNumber
, &folder
, &idx
);
1035 if (!folder
|| (idx
== -1))
1037 KMFolderOpener
openFolder(folder
, "showmail");
1038 KMMsgBase
*msgBase
= folder
->getMsgBase(idx
);
1041 bool unGet
= !msgBase
->isMessage();
1042 KMMessage
*msg
= folder
->getMsg(idx
);
1044 KMReaderMainWin
*win
= new KMReaderMainWin( false, false );
1045 KMMessage
*newMessage
= new KMMessage( *msg
);
1046 newMessage
->setParent( msg
->parent() );
1047 newMessage
->setMsgSerNum( msg
->getMsgSerNum() );
1048 newMessage
->setReadyToShow( true );
1049 win
->showMsg( GlobalSettings::self()->overrideCharacterEncoding(), newMessage
);
1053 folder
->unGetMsg(idx
);
1060 QString
KMKernel::getFrom( quint32 serialNumber
)
1063 KMFolder
*folder
= 0;
1064 KMMsgDict::instance()->getLocation(serialNumber
, &folder
, &idx
);
1065 if (!folder
|| (idx
== -1))
1067 KMFolderOpener
openFolder(folder
, "getFrom");
1068 KMMsgBase
*msgBase
= folder
->getMsgBase(idx
);
1071 bool unGet
= !msgBase
->isMessage();
1072 KMMessage
*msg
= folder
->getMsg(idx
);
1073 QString result
= msg
->from();
1075 folder
->unGetMsg(idx
);
1079 QString
KMKernel::debugScheduler()
1081 QString res
= KMail::ActionScheduler::debug();
1085 QString
KMKernel::debugSernum( quint32 serialNumber
)
1088 if (serialNumber
!= 0) {
1090 KMFolder
*folder
= 0;
1092 KMMsgDict::instance()->getLocation( serialNumber
, &folder
, &idx
);
1093 // It's possible that the message has been deleted or moved into a
1095 if (folder
&& (idx
!= -1)) {
1097 KMFolderOpener
openFolder( folder
, "debugser" );
1098 msg
= folder
->getMsgBase( idx
);
1100 res
.append( QString( " subject %s,\n sender %s,\n date %s.\n" )
1101 .arg( msg
->subject() )
1102 .arg( msg
->fromStrip() )
1103 .arg( msg
->dateStr() ) );
1105 res
.append( QString( "Invalid serial number." ) );
1108 res
.append( QString( "Invalid serial number." ) );
1115 void KMKernel::pauseBackgroundJobs()
1117 mBackgroundTasksTimer
->stop();
1118 mJobScheduler
->pause();
1121 void KMKernel::resumeBackgroundJobs()
1123 mJobScheduler
->resume();
1124 mBackgroundTasksTimer
->start( 4 * 60 * 60 * 1000 );
1127 void KMKernel::stopNetworkJobs()
1129 if ( GlobalSettings::self()->networkState() == GlobalSettings::EnumNetworkState::Offline
)
1132 GlobalSettings::setNetworkState( GlobalSettings::EnumNetworkState::Offline
);
1133 BroadcastStatus::instance()->setStatusMsg( i18n("KMail is set to be offline; all network jobs are suspended"));
1134 emit
onlineStatusChanged( (GlobalSettings::EnumNetworkState::type
)GlobalSettings::networkState() );
1138 void KMKernel::resumeNetworkJobs()
1140 if ( GlobalSettings::self()->networkState() == GlobalSettings::EnumNetworkState::Online
)
1143 GlobalSettings::setNetworkState( GlobalSettings::EnumNetworkState::Online
);
1144 BroadcastStatus::instance()->setStatusMsg( i18n("KMail is set to be online; all network jobs resumed"));
1145 emit
onlineStatusChanged( (GlobalSettings::EnumNetworkState::type
)GlobalSettings::networkState() );
1147 if ( kmkernel
->msgSender()->sendImmediate() ) {
1148 kmkernel
->msgSender()->sendQueued();
1152 bool KMKernel::isOffline()
1154 if ( GlobalSettings::self()->networkState() == GlobalSettings::EnumNetworkState::Offline
)
1160 bool KMKernel::askToGoOnline()
1162 if ( kmkernel
->isOffline() ) {
1164 KMessageBox::questionYesNo( KMKernel::self()->mainWin(),
1165 i18n("KMail is currently in offline mode. "
1166 "How do you want to proceed?"),
1167 i18n("Online/Offline"),
1168 KGuiItem(i18n("Work Online")),
1169 KGuiItem(i18n("Work Offline")));
1171 if( rc
== KMessageBox::No
) {
1174 kmkernel
->resumeNetworkJobs();
1180 /********************************************************************/
1181 /* Kernel methods */
1182 /********************************************************************/
1184 void KMKernel::quit()
1186 // Called when all windows are closed. Will take care of compacting,
1187 // sending... should handle session management too!!
1191 - msgsender is nonblocking
1192 (our own, QSocketNotifier based. Pops up errors and sends signal
1193 senderFinished when done)
1195 o If we are getting mail, stop it (but don't lose something!)
1196 [Done already, see mailCheckAborted]
1197 o If we are sending mail, go on UNLESS this was called by SM,
1198 in which case stop ASAP that too (can we warn? should we continue
1200 o If we are compacting, or expunging, go on UNLESS this was SM call.
1201 In that case stop compacting ASAP and continue on next start, before
1202 touching any folders. [Not needed anymore with CompactionJob]
1207 if compacting, stop;
1210 Windows will take care of themselves (composer should dump
1211 its messages, if any but not in deadMail)
1212 declare us ready for the End of the Session
1214 No, normal quit call
1215 All windows are off. Anything to do, should compact or sender sends?
1216 Yes, maybe put an icon in panel as a sign of life
1217 if sender sending, connect us to his finished slot, declare us ready
1218 for quit and wait for senderFinished
1219 if not, Folder manager, go compact sent-mail and outbox
1220 } (= call slotFinished())
1222 void KMKernel::slotSenderFinished()
1224 good, Folder manager go compact sent-mail and outbox
1225 clean up stage1 (release folders and config, unregister from dcop)
1226 -- another kmail may start now ---
1232 /********************************************************************/
1233 /* Init, Exit, and handler methods */
1234 /********************************************************************/
1235 void KMKernel::testDir( const char *_name
)
1237 QString foldersPath
= QDir::homePath() + QString( _name
);
1238 QFileInfo
info( foldersPath
);
1239 if ( !info
.exists() ) {
1240 if ( KDE_mkdir( QFile::encodeName( foldersPath
), S_IRWXU
) == -1 ) {
1241 KMessageBox::sorry( 0, i18n( "KMail could not create folder '%1';\n"
1242 "please make sure that you can view and "
1243 "modify the content of the folder '%2'.",
1244 foldersPath
, QDir::homePath() ) );
1248 if ( !info
.isDir() || !info
.isReadable() || !info
.isWritable() ) {
1249 KMessageBox::sorry( 0, i18n( "The permissions of the folder '%1' are "
1251 "please make sure that you can view and "
1252 "modify the content of this folder.",
1259 //-----------------------------------------------------------------------------
1260 // Open a composer for each message found in the dead.letter folder
1261 void KMKernel::recoverDeadLetters()
1263 const QString pathName
= localDataPath();
1264 QDir
dir( pathName
);
1265 if ( !dir
.exists( "autosave" ) )
1268 KMFolder
folder( 0, pathName
+ "autosave", KMFolderTypeMaildir
, false /* no index */ );
1269 KMFolderOpener
openFolder( &folder
, "recover" );
1270 if ( !folder
.isOpened() ) {
1271 perror( "cannot open autosave folder" );
1275 const int num
= folder
.count();
1276 for ( int i
= 0; i
< num
; i
++ ) {
1277 KMMessage
*msg
= folder
.take( 0 );
1279 KMail::Composer
* win
= KMail::makeComposer();
1280 win
->setMsg( msg
, false, false, true );
1281 win
->setAutoSaveFilename( msg
->fileName() );
1287 //-----------------------------------------------------------------------------
1288 void KMKernel::initFolders(KConfig
* cfg
)
1291 KConfigGroup
group(cfg
,"General");
1293 name
= group
.readEntry("inboxFolder");
1295 // Currently the folder manager cannot manage folders which are not
1296 // in the base folder directory.
1297 //if (name.isEmpty()) name = getenv("MAIL");
1299 if (name
.isEmpty()) name
= I18N_NOOP("inbox");
1301 the_inboxFolder
= (KMFolder
*)the_folderMgr
->findOrCreate(name
);
1303 if ( !the_inboxFolder
->canAccess() ) {
1304 emergencyExit( i18n("You do not have read/write permission to your inbox folder.") );
1307 the_inboxFolder
->setSystemFolder(true);
1308 if ( the_inboxFolder
->userWhoField().isEmpty() )
1309 the_inboxFolder
->setUserWhoField( QString() );
1310 // inboxFolder->open();
1312 the_outboxFolder
= the_folderMgr
->findOrCreate(group
.readEntry("outboxFolder", I18N_NOOP("outbox")));
1313 if ( !the_outboxFolder
->canAccess() ) {
1314 emergencyExit( i18n("You do not have read/write permission to your outbox folder.") );
1316 the_outboxFolder
->setNoChildren(true);
1318 the_outboxFolder
->setSystemFolder(true);
1319 if ( the_outboxFolder
->userWhoField().isEmpty() )
1320 the_outboxFolder
->setUserWhoField( QString() );
1321 /* Nuke the oubox's index file, to make sure that no ghost messages are in
1322 * it from a previous crash. Ghost messages happen in the outbox because it
1323 * the only folder where messages enter and leave within 5 seconds, which is
1324 * the leniency period for index invalidation. Since the number of mails in
1325 * this folder is expected to be very small, we can live with regenerating
1326 * the index on each start to be on the save side. */
1327 //if ( the_outboxFolder->folderType() == KMFolderTypeMaildir )
1328 // unlink( QFile::encodeName( the_outboxFolder->indexLocation() ) );
1329 the_outboxFolder
->open( "kmkernel" );
1331 the_sentFolder
= the_folderMgr
->findOrCreate(group
.readEntry("sentFolder", I18N_NOOP("sent-mail")));
1332 if ( !the_sentFolder
->canAccess() ) {
1333 emergencyExit( i18n("You do not have read/write permission to your sent-mail folder.") );
1335 the_sentFolder
->setSystemFolder(true);
1336 if ( the_sentFolder
->userWhoField().isEmpty() )
1337 the_sentFolder
->setUserWhoField( QString() );
1338 // the_sentFolder->open();
1340 the_trashFolder
= the_folderMgr
->findOrCreate(group
.readEntry("trashFolder", I18N_NOOP("trash")));
1341 if ( !the_trashFolder
->canAccess() ) {
1342 emergencyExit( i18n("You do not have read/write permission to your trash folder.") );
1344 the_trashFolder
->setSystemFolder(true);
1345 if ( the_trashFolder
->userWhoField().isEmpty() )
1346 the_trashFolder
->setUserWhoField( QString() );
1347 // the_trashFolder->open();
1349 the_draftsFolder
= the_folderMgr
->findOrCreate(group
.readEntry("draftsFolder", I18N_NOOP("drafts")));
1350 if ( !the_draftsFolder
->canAccess() ) {
1351 emergencyExit( i18n("You do not have read/write permission to your drafts folder.") );
1353 the_draftsFolder
->setSystemFolder(true);
1354 if ( the_draftsFolder
->userWhoField().isEmpty() )
1355 the_draftsFolder
->setUserWhoField( QString() );
1356 the_draftsFolder
->open( "kmkernel" );
1358 the_templatesFolder
= the_folderMgr
->findOrCreate(group
.readEntry("templatesFolder", I18N_NOOP("templates")));
1359 if ( !the_templatesFolder
->canAccess() ) {
1360 emergencyExit( i18n("You do not have read/write permission to your templates folder.") );
1362 the_templatesFolder
->setSystemFolder(true);
1363 if ( the_templatesFolder
->userWhoField().isEmpty() )
1364 the_templatesFolder
->setUserWhoField( QString() );
1365 the_templatesFolder
->open( "kmkernel" );
1369 void KMKernel::init()
1371 the_shuttingDown
= false;
1372 the_server_is_ready
= false;
1374 KConfig
* cfg
= KMKernel::config();
1378 KConfigGroup
group(cfg
, "General");
1379 the_firstStart
= group
.readEntry("first-start", true );
1380 group
.writeEntry("first-start", false);
1381 the_previousVersion
= group
.readEntry("previous-version");
1382 group
.writeEntry("previous-version", KMAIL_VERSION
);
1384 QString foldersPath
= group
.readPathEntry( "folders", QString() );
1385 QString standardFolderPath
= localDataPath() + "mail";
1386 kDebug() << "foldersPath (from config):" << foldersPath
;
1388 if ( foldersPath
.isEmpty() ) {
1389 foldersPath
= standardFolderPath
;
1390 if ( transferMail( foldersPath
) ) {
1391 group
.writePathEntry( "folders", foldersPath
);
1393 kDebug() << "foldersPath (after transferMail):" << foldersPath
;
1396 // Check if the folder path from config really exists.
1397 // When migrating from KDE3 to KDE4, some distros change the home directory
1398 // from .kde to .kde4, and if the user has copied the config file + app data
1399 // over to .kde4, the config file then contains the incorrect entry.
1400 // Therefore, we fall back to KDEHOME/share/apps/kmail/mail if the folders
1402 QDir
configFolderDir( foldersPath
);
1403 if ( foldersPath
.contains( ".kde/share/apps/kmail/mail" ) &&
1404 !configFolderDir
.exists() ) {
1405 QDir
standardConfigDir( standardFolderPath
);
1406 if ( standardConfigDir
.exists() ) {
1407 foldersPath
= standardFolderPath
;
1408 kDebug() << "foldersPath from config doesn't exist, using standard "
1414 //Here because folderMgr's need it when they read the index and sort tags
1415 the_msgTagMgr
= new KMMessageTagMgr();
1416 the_msgTagMgr
->readConfig();
1418 // moved up here because KMMessage::stripOffPrefixes is used below
1419 KMMessage::readConfig();
1421 the_undoStack
= new UndoStack(20);
1422 the_folderMgr
= new KMFolderMgr(foldersPath
);
1423 the_imapFolderMgr
= new KMFolderMgr( KMFolderImap::cacheLocation(), KMImapDir
);
1424 the_dimapFolderMgr
= new KMFolderMgr( KMFolderCachedImap::cacheLocation(), KMDImapDir
);
1426 the_searchFolderMgr
= new KMFolderMgr(KStandardDirs::locateLocal("data","kmail/search"), KMSearchDir
);
1427 KMFolder
*lsf
= the_searchFolderMgr
->find( i18n("Last Search") );
1429 the_searchFolderMgr
->remove( lsf
);
1431 the_acctMgr
= new AccountManager();
1432 the_filterMgr
= new KMFilterMgr();
1433 the_popFilterMgr
= new KMFilterMgr(true);
1434 the_filterActionDict
= new KMFilterActionDict
;
1437 the_acctMgr
->readConfig();
1438 the_filterMgr
->readConfig();
1439 the_popFilterMgr
->readConfig();
1440 cleanupImapFolders();
1442 the_msgSender
= new KMSender
;
1443 the_server_is_ready
= true;
1444 { // area for config group "Composer"
1445 KConfigGroup
group(cfg
, "Composer");
1446 if (group
.readEntry("pref-charsets", QStringList() ).isEmpty())
1448 group
.writeEntry("pref-charsets", "us-ascii,iso-8859-1,locale,utf-8");
1452 // filterMgr->dump();
1454 the_weaver
= new ThreadWeaver::Weaver( this );
1456 connect( the_folderMgr
, SIGNAL( folderRemoved(KMFolder
*) ),
1457 this, SIGNAL( folderRemoved(KMFolder
*) ) );
1458 connect( the_dimapFolderMgr
, SIGNAL( folderRemoved(KMFolder
*) ),
1459 this, SIGNAL( folderRemoved(KMFolder
*) ) );
1460 connect( the_imapFolderMgr
, SIGNAL( folderRemoved(KMFolder
*) ),
1461 this, SIGNAL( folderRemoved(KMFolder
*) ) );
1462 connect( the_searchFolderMgr
, SIGNAL( folderRemoved(KMFolder
*) ),
1463 this, SIGNAL( folderRemoved(KMFolder
*) ) );
1465 mBackgroundTasksTimer
= new QTimer( this );
1466 mBackgroundTasksTimer
->setSingleShot( true );
1467 connect( mBackgroundTasksTimer
, SIGNAL( timeout() ), this, SLOT( slotRunBackgroundTasks() ) );
1468 #ifdef DEBUG_SCHEDULER // for debugging, see jobscheduler.h
1469 mBackgroundTasksTimer
->start( 10000 ); // 10s, singleshot
1471 mBackgroundTasksTimer
->start( 5 * 60000 ); // 5 minutes, singleshot
1475 void KMKernel::readConfig()
1477 //Needed here, since this function is also called when the configuration
1478 //changes, and the static variables should be updated then - IOF
1479 KMMessage::readConfig();
1482 void KMKernel::cleanupImapFolders()
1484 KMAccount
*acct
= 0;
1485 QList
<KMFolderNode
*>::iterator it
= the_imapFolderMgr
->dir().begin();
1486 while ( it
!= the_imapFolderMgr
->dir().end() )
1488 KMFolderNode
*node
= *it
;
1489 if (node
->isDir() || ((acct
= the_acctMgr
->find(node
->id()))
1490 && ( acct
->type() == KAccount::Imap
))
1491 || !the_acctMgr
->isEnabled( node
->id() ))
1495 KMFolder
* folder
= static_cast<KMFolder
*>(node
);
1496 // delete only local
1497 static_cast<KMFolderImap
*>( folder
->storage() )->setAlreadyRemoved( true );
1498 the_imapFolderMgr
->remove(folder
);
1499 it
= the_imapFolderMgr
->dir().begin();
1503 it
= the_dimapFolderMgr
->dir().begin();
1504 while ( it
!= the_dimapFolderMgr
->dir().end() )
1506 KMFolderNode
*node
= *it
;
1507 if (node
->isDir() || ((acct
= the_acctMgr
->find(node
->id()))
1508 && ( acct
->type() == KAccount::DImap
)) )
1512 the_dimapFolderMgr
->remove(static_cast<KMFolder
*>(node
));
1513 it
= the_dimapFolderMgr
->dir().begin();
1517 the_imapFolderMgr
->quiet(true);
1518 QList
<KMAccount
*>::iterator accountIt
= the_acctMgr
->begin();
1519 while ( accountIt
!= the_acctMgr
->end() ) {
1523 KMAcctImap
*imapAcct
;
1525 if (acct
->type() != KAccount::Imap
)
1527 fld
= static_cast<KMFolderImap
*>(the_imapFolderMgr
1528 ->findOrCreate(QString::number(acct
->id()), false, acct
->id())->storage());
1529 fld
->setNoContent(true);
1530 fld
->folder()->setLabel(acct
->name());
1531 imapAcct
= static_cast<KMAcctImap
*>(acct
);
1532 fld
->setAccount(imapAcct
);
1533 imapAcct
->setImapFolder(fld
);
1534 fld
->close( "kernel", true );
1536 the_imapFolderMgr
->quiet(false);
1538 the_dimapFolderMgr
->quiet( true );
1539 accountIt
= the_acctMgr
->begin();
1540 while ( accountIt
!= the_acctMgr
->end() ) {
1544 KMFolderCachedImap
*cfld
= 0;
1545 KMAcctCachedImap
*cachedImapAcct
;
1547 if (acct
->type() != KAccount::DImap
) continue;
1549 KMFolder
* fld
= the_dimapFolderMgr
->find(QString::number(acct
->id()));
1551 cfld
= static_cast<KMFolderCachedImap
*>( fld
->storage() );
1553 // Folder doesn't exist yet
1554 cfld
= static_cast<KMFolderCachedImap
*>(the_dimapFolderMgr
->createFolder(QString::number(acct
->id()),
1555 false, KMFolderTypeCachedImap
)->storage());
1557 KMessageBox::error(0,(i18n("Cannot create file `%1' in %2.\nKMail cannot start without it.", acct
->name(), the_dimapFolderMgr
->basePath())));
1560 cfld
->folder()->setId( acct
->id() );
1563 cfld
->setNoContent(true);
1564 cfld
->folder()->setLabel(acct
->name());
1565 cachedImapAcct
= static_cast<KMAcctCachedImap
*>(acct
);
1566 cfld
->setAccount(cachedImapAcct
);
1567 cachedImapAcct
->setImapFolder(cfld
);
1568 cfld
->close( "kmkernel" );
1570 the_dimapFolderMgr
->quiet( false );
1573 bool KMKernel::doSessionManagement()
1576 // Do session management
1577 if (kapp
->isSessionRestored()){
1579 while (KMMainWin::canBeRestored(n
)){
1580 //only restore main windows! (Matthias);
1581 if (KMMainWin::classNameOfToplevel(n
) == "KMMainWin")
1582 (new KMMainWin
)->restore(n
);
1585 return true; // we were restored by SM
1587 return false; // no, we were not restored
1590 void KMKernel::closeAllKMailWindows()
1592 QList
<KMainWindow
*> windowsToDelete
;
1594 foreach ( KMainWindow
* window
, KMainWindow::memberList() ) {
1595 if ( ::qobject_cast
<KMMainWin
*>(window
) ||
1596 ::qobject_cast
<KMail::SecondaryWindow
*>(window
) )
1598 // close and delete the window
1599 window
->setAttribute(Qt::WA_DeleteOnClose
);
1601 windowsToDelete
.append( window
);
1605 // We delete all main windows here. Above we called close(), but that calls
1606 // deleteLater() internally, therefore does not delete it immediately.
1607 // This would lead to problems when closing Kontact when a composer window
1608 // is open, because the destruction order is:
1610 // 1. destructor of the Kontact mainwinow
1611 // 2. delete all parts
1612 // 3. the KMail part destructor calls KMKernel::cleanup(), which calls
1614 // 4. delete all other mainwindows
1616 // Deleting the composer windows here will make sure that step 4 will not delete
1617 // any composer window, which would fail because the kernel is already deleted.
1618 qDeleteAll( windowsToDelete
);
1619 windowsToDelete
.clear();
1622 void KMKernel::cleanup(void)
1625 the_shuttingDown
= true;
1626 closeAllKMailWindows();
1628 // Write the config while all other managers are alive
1629 the_acctMgr
->writeConfig(false);
1630 delete the_filterMgr
;
1632 delete the_msgSender
;
1634 delete the_filterActionDict
;
1635 the_filterActionDict
= 0;
1636 delete the_msgTagMgr
;
1638 delete the_undoStack
;
1640 delete the_popFilterMgr
;
1641 the_popFilterMgr
= 0;
1646 KConfig
* config
= KMKernel::config();
1647 KConfigGroup
group(config
, "General");
1649 if ( the_trashFolder
) {
1651 the_trashFolder
->close( "kmkernel", true );
1653 if ( group
.readEntry( "empty-trash-on-exit", false ) ) {
1654 if ( the_trashFolder
->count( true ) > 0 ) {
1655 the_trashFolder
->expunge();
1661 mICalIface
->cleanup();
1663 QList
<QPointer
<KMFolder
> > folders
;
1664 QStringList strList
;
1666 the_folderMgr
->createFolderList(&strList
, &folders
);
1668 QList
<QPointer
<KMFolder
> >::const_iterator it
;
1669 for ( it
= folders
.begin(); it
!= folders
.end(); ++it
) {
1671 if ( !folder
|| folder
->isDir() ) {
1674 folder
->close( "kmkernel", true );
1678 the_searchFolderMgr
->createFolderList(&strList
, &folders
);
1679 for ( it
= folders
.begin(); it
!= folders
.end(); ++it
) {
1681 if ( !folder
|| folder
->isDir() ) {
1684 folder
->close( "kmkernel", true );
1687 delete the_folderMgr
;
1689 delete the_imapFolderMgr
;
1690 the_imapFolderMgr
= 0;
1691 delete the_dimapFolderMgr
;
1692 the_dimapFolderMgr
= 0;
1693 // Delete the_acctMgr here since it is used in the other *Mgrs above.
1696 delete the_searchFolderMgr
;
1697 the_searchFolderMgr
= 0;
1698 delete mConfigureDialog
;
1699 mConfigureDialog
= 0;
1700 // do not delete, because mWin may point to an existing window
1704 if ( RecentAddresses::exists() )
1705 RecentAddresses::self( config
)->save( config
);
1709 bool KMKernel::transferMail( QString
& destinationDir
)
1713 // check whether the user has a ~/KMail folder
1714 QFileInfo
fi( QDir::home(), "KMail" );
1715 if ( fi
.exists() && fi
.isDir() ) {
1716 dir
= QDir::homePath() + "/KMail";
1717 // the following two lines can be removed once moving mail is reactivated
1718 destinationDir
= dir
;
1722 if ( dir
.isEmpty() ) {
1723 // check whether the user has a ~/Mail folder
1724 fi
.setFile( QDir::home(), "Mail" );
1725 if ( fi
.exists() && fi
.isDir() &&
1726 QFile::exists( QDir::homePath() + "/Mail/.inbox.index" ) ) {
1727 // there's a ~/Mail folder which seems to be used by KMail (because of the
1729 dir
= QDir::homePath() + "/Mail";
1730 // the following two lines can be removed once moving mail is reactivated
1731 destinationDir
= dir
;
1736 if ( dir
.isEmpty() ) {
1737 return true; // there's no old mail folder
1741 // disabled for now since moving fails in certain cases (e.g. if symbolic links are involved)
1742 const QString kmailName
= KGlobal::mainComponent().aboutData()()->programName();
1744 if ( KIO::NetAccess::exists( destinationDir
, KIO::NetAccess::SourceSide
, 0 ) ) {
1745 // if destinationDir exists, we need to warn about possible
1746 // overwriting of files. otherwise, we don't have to
1747 msg
= ki18nc( "%1-%3 is the application name, %4-%7 are folder path",
1748 "<qt>The <i>%4</i> folder exists. "
1749 "%1 now uses the <i>%5</i> folder for "
1751 "%2 can move the contents of <i>%6</i> into this folder for "
1752 "you, though this may replace any existing files with "
1753 "the same name in <i>%7</i>.</p><p>"
1754 "<strong>Would you like %3 to move the mail "
1755 "files now?</strong></p></qt>" )
1756 .subs( kmailName
).subs( kmailName
).subs( kmailName
)
1757 .subs( dir
).subs( destinationDir
).subs( dir
).subs( destinationDir
)
1761 msg
= ki18nc( "%1-%3 is the application name, %4-%6 are folder path",
1762 "<qt>The <i>%4</i> folder exists. "
1763 "%1 now uses the <i>%5</i> folder for "
1764 "its messages. %2 can move the contents of <i>%6</i> into "
1765 "this folder for you.<p>"
1766 "<strong>Would you like %3 to move the mail "
1767 "files now?</strong></p></qt>" )
1768 .subs( kmailName
).subs( kmailName
).subs( kmailName
)
1769 .subs( dir
).subs( destinationDir
).subs( dir
)
1772 QString title
= i18n( "Migrate Mail Files?" );
1773 QString buttonText
= i18n( "Move" );
1775 if ( KMessageBox::questionYesNo( 0, msg
, title
, buttonText
, i18n("Do Not Move") ) ==
1777 destinationDir
= dir
;
1781 if ( !KIO::NetAccess::move( dir
, destinationDir
) ) {
1782 kDebug(5006) <<"Moving" << dir
<<" to" << destinationDir
<<" failed:" << KIO::NetAccess::lastErrorString();
1783 kDebug(5006) <<"Deleting" << destinationDir
;
1784 KIO::NetAccess::del( destinationDir
, 0 );
1785 destinationDir
= dir
;
1795 void KMKernel::dumpDeadLetters()
1797 if ( shuttingDown() )
1798 return; //All documents should be saved before shutting down is set!
1800 // make all composer windows autosave their contents
1801 foreach ( KMainWindow
* window
, KMainWindow::memberList() ) {
1802 if ( KMail::Composer
* win
= ::qobject_cast
<KMail::Composer
*>( window
) ) {
1803 win
->autoSaveMessage();
1804 // saving the message has to be finished right here, we are called from a dtor,
1805 // therefore we have no chance to finish this later
1806 // yes, this is ugly and potentially dangerous, but the alternative is losing
1807 // currently composed messages...
1808 while ( win
->isComposing() )
1809 qApp
->processEvents();
1816 void KMKernel::action( bool mailto
, bool check
, const QString
&to
,
1817 const QString
&cc
, const QString
&bcc
,
1818 const QString
&subj
, const QString
&body
,
1819 const KUrl
&messageFile
,
1820 const KUrl::List
&attachURLs
,
1821 const QStringList
&customHeaders
)
1824 openComposer( to
, cc
, bcc
, subj
, body
, 0,
1825 messageFile
.pathOrUrl(), attachURLs
.toStringList(),
1828 openReader( check
);
1835 void KMKernel::byteArrayToRemoteFile(const QByteArray
&aData
, const KUrl
&aURL
,
1838 // ## when KDE 3.3 is out: use KIO::storedPut to remove slotDataReq altogether
1839 KIO::Job
*job
= KIO::put(aURL
, -1, overwrite
? KIO::Overwrite
: KIO::DefaultFlags
);
1840 putData pd
; pd
.url
= aURL
; pd
.data
= aData
; pd
.offset
= 0;
1841 mPutJobs
.insert(job
, pd
);
1842 connect(job
, SIGNAL(dataReq(KIO::Job
*,QByteArray
&)),
1843 SLOT(slotDataReq(KIO::Job
*,QByteArray
&)));
1844 connect(job
, SIGNAL(result(KJob
*)),
1845 SLOT(slotResult(KJob
*)));
1848 void KMKernel::slotDataReq(KIO::Job
*job
, QByteArray
&data
)
1850 // send the data in 64 KB chunks
1851 const int MAX_CHUNK_SIZE
= 64*1024;
1852 QMap
<KIO::Job
*, putData
>::Iterator it
= mPutJobs
.find(job
);
1853 assert(it
!= mPutJobs
.end());
1854 int remainingBytes
= (*it
).data
.size() - (*it
).offset
;
1855 if( remainingBytes
> MAX_CHUNK_SIZE
)
1857 // send MAX_CHUNK_SIZE bytes to the receiver (deep copy)
1858 data
= QByteArray( (*it
).data
.data() + (*it
).offset
, MAX_CHUNK_SIZE
);
1859 (*it
).offset
+= MAX_CHUNK_SIZE
;
1860 //kDebug( 5006 ) <<"Sending" << MAX_CHUNK_SIZE <<" bytes ("
1861 // << remainingBytes - MAX_CHUNK_SIZE << " bytes remain)\n";
1865 // send the remaining bytes to the receiver (deep copy)
1866 data
= QByteArray( (*it
).data
.data() + (*it
).offset
, remainingBytes
);
1867 (*it
).data
= QByteArray();
1869 //kDebug( 5006 ) <<"Sending" << remainingBytes <<" bytes";
1873 void KMKernel::slotResult(KJob
*job
)
1875 QMap
<KIO::Job
*, putData
>::Iterator it
= mPutJobs
.find(static_cast<KIO::Job
*>(job
));
1876 assert(it
!= mPutJobs
.end());
1879 if (job
->error() == KIO::ERR_FILE_ALREADY_EXIST
)
1881 if (KMessageBox::warningContinueCancel(0,
1882 i18n("File %1 exists.\nDo you want to replace it?",
1883 (*it
).url
.prettyUrl()), i18n("Save to File"), KGuiItem(i18n("&Replace")))
1884 == KMessageBox::Continue
)
1885 byteArrayToRemoteFile((*it
).data
, (*it
).url
, true);
1888 KIO::JobUiDelegate
*ui
= static_cast<KIO::Job
*>( job
)->ui();
1889 ui
->showErrorMessage();
1895 void KMKernel::slotRequestConfigSync() {
1896 // ### FIXME: delay as promised in the kdoc of this function ;-)
1897 KMKernel::config()->sync();
1900 void KMKernel::slotShowConfigurationDialog()
1902 if( !mConfigureDialog
) {
1903 mConfigureDialog
= new ConfigureDialog( 0, false );
1904 mConfigureDialog
->setObjectName( "configure" );
1905 connect( mConfigureDialog
, SIGNAL( configCommitted() ),
1906 this, SLOT( slotConfigChanged() ) );
1909 if( KMKernel::getKMMainWidget() == 0 ) {
1910 // ensure that there is a main widget available
1911 // as parts of the configure dialog (identity) rely on this
1912 // and this slot can be called when there is only a KMComposeWin showing
1913 KMMainWin
*win
= new KMMainWin
;
1918 if( mConfigureDialog
->isHidden() ) {
1919 mConfigureDialog
->show();
1921 mConfigureDialog
->raise();
1925 void KMKernel::slotConfigChanged()
1928 emit
configChanged();
1931 //-------------------------------------------------------------------------------
1933 QString
KMKernel::localDataPath()
1935 return KStandardDirs::locateLocal( "data", "kmail/" );
1938 //-------------------------------------------------------------------------------
1940 bool KMKernel::haveSystemTrayApplet()
1942 return !systemTrayApplets
.isEmpty();
1945 bool KMKernel::registerSystemTrayApplet( const KSystemTrayIcon
* applet
)
1947 if ( !systemTrayApplets
.contains( applet
) ) {
1948 systemTrayApplets
.append( applet
);
1955 bool KMKernel::unregisterSystemTrayApplet( const KSystemTrayIcon
* applet
)
1957 return systemTrayApplets
.removeAll( applet
) > 0;
1960 void KMKernel::emergencyExit( const QString
& reason
)
1963 if ( reason
.length() == 0 ) {
1964 mesg
= i18n("KMail encountered a fatal error and will terminate now");
1967 mesg
= i18n("KMail encountered a fatal error and will "
1968 "terminate now.\nThe error was:\n%1", reason
);
1971 kWarning(5006) << mesg
;
1972 KMessageBox::error( 0, mesg
);
1978 * Returns true if the folder is either the outbox or one of the drafts-folders
1980 bool KMKernel::folderIsDraftOrOutbox(const KMFolder
* folder
)
1983 if ( folder
== the_outboxFolder
)
1985 return folderIsDrafts( folder
);
1988 bool KMKernel::folderIsDrafts(const KMFolder
* folder
)
1991 if ( folder
== the_draftsFolder
)
1994 QString idString
= folder
->idString();
1995 if ( idString
.isEmpty() ) return false;
1997 // search the identities if the folder matches the drafts-folder
1998 const KPIMIdentities::IdentityManager
* im
= identityManager();
1999 for( KPIMIdentities::IdentityManager::ConstIterator it
= im
->begin(); it
!= im
->end(); ++it
)
2000 if ( (*it
).drafts() == idString
) return true;
2004 bool KMKernel::folderIsTemplates(const KMFolder
* folder
)
2007 if ( folder
== the_templatesFolder
)
2010 QString idString
= folder
->idString();
2011 if ( idString
.isEmpty() ) return false;
2013 // search the identities if the folder matches the templates-folder
2014 const KPIMIdentities::IdentityManager
* im
= identityManager();
2015 for( KPIMIdentities::IdentityManager::ConstIterator it
= im
->begin(); it
!= im
->end(); ++it
)
2016 if ( (*it
).templates() == idString
) return true;
2020 bool KMKernel::folderIsTrash(KMFolder
* folder
)
2023 if (folder
== the_trashFolder
) return true;
2024 QStringList actList
= acctMgr()->getAccounts();
2025 QStringList::Iterator
it( actList
.begin() );
2026 for( ; it
!= actList
.end() ; ++it
) {
2027 KMAccount
* act
= acctMgr()->findByName( *it
);
2028 if ( act
&& ( act
->trash() == folder
->idString() ) )
2034 bool KMKernel::folderIsSentMailFolder( const KMFolder
* folder
)
2037 if ( folder
== the_sentFolder
)
2040 QString idString
= folder
->idString();
2041 if ( idString
.isEmpty() ) return false;
2043 // search the identities if the folder matches the sent-folder
2044 const KPIMIdentities::IdentityManager
* im
= identityManager();
2045 for( KPIMIdentities::IdentityManager::ConstIterator it
= im
->begin(); it
!= im
->end(); ++it
)
2046 if ( (*it
).fcc() == idString
) return true;
2050 KPIMIdentities::IdentityManager
* KMKernel::identityManager() {
2051 if ( !mIdentityManager
) {
2053 mIdentityManager
= new KPIMIdentities::IdentityManager( false, this, "mIdentityManager" );
2055 return mIdentityManager
;
2058 KMainWindow
* KMKernel::mainWin()
2060 KMainWindow
*kmWin
= 0;
2062 // First look for a KMMainWin.
2063 foreach ( KMainWindow
* window
, KMainWindow::memberList() )
2064 if ( ::qobject_cast
<KMMainWin
*>(window
) )
2067 // There is no KMMainWin. Use any other KMainWindow instead (e.g. in
2068 // case we are running inside Kontact) because we anyway only need
2069 // it for modal message boxes and for KNotify events.
2070 kmWin
= KMainWindow::memberList().first();
2074 // There's not a single KMainWindow. Create a KMMainWin.
2075 // This could happen if we want to pop up an error message
2076 // while we are still doing the startup wizard and no other
2077 // KMainWindow is running.
2078 mWin
= new KMMainWin
;
2084 * Empties all trash folders
2086 void KMKernel::slotEmptyTrash()
2088 QString title
= i18n("Empty Trash");
2089 QString text
= i18n("Are you sure you want to empty the trash folders of all accounts?");
2090 if (KMessageBox::warningContinueCancel(0, text
, title
,
2091 KStandardGuiItem::cont(), KStandardGuiItem::cancel(),
2092 "confirm_empty_trash")
2093 != KMessageBox::Continue
)
2098 QList
<KMAccount
*>::iterator accountIt
= acctMgr()->begin();
2099 while ( accountIt
!= acctMgr()->end() ) {
2100 KMAccount
*acct
= *accountIt
;
2102 KMFolder
* trash
= findFolderById(acct
->trash());
2110 KMKernel
* KMKernel::self()
2116 KConfig
* KMKernel::config()
2119 if ( !mySelf
->mConfig
)
2121 mySelf
->mConfig
= KSharedConfig::openConfig( "kmailrc" );
2122 // Check that all updates have been run on the config file:
2123 KMail::checkConfigUpdates();
2125 return mySelf
->mConfig
.data();
2128 KMailICalIfaceImpl
& KMKernel::iCalIface()
2130 assert( mICalIface
);
2134 void KMKernel::selectFolder( const QString
&folderPath
)
2136 kDebug(5006)<<"Selecting a folder"<<folderPath
;
2137 const QString localPrefix
= "/Local";
2138 KMFolder
*folder
= kmkernel
->folderMgr()->getFolderByURL( folderPath
);
2139 if ( !folder
&& folderPath
.startsWith( localPrefix
) )
2140 folder
= the_folderMgr
->getFolderByURL( folderPath
.mid( localPrefix
.length() ) );
2142 folder
= kmkernel
->imapFolderMgr()->getFolderByURL( folderPath
);
2144 folder
= kmkernel
->dimapFolderMgr()->getFolderByURL( folderPath
);
2147 KMMainWidget
*widget
= getKMMainWidget();
2152 widget
->mainFolderView()->setCurrentFolder( folder
);
2155 KMMainWidget
*KMKernel::getKMMainWidget()
2157 //This could definitely use a speadup
2158 QWidgetList l
= QApplication::topLevelWidgets();
2161 Q_FOREACH( wid
, l
) {
2162 QList
<KMMainWidget
*> l2
= wid
->topLevelWidget()->findChildren
<KMMainWidget
*>();
2163 if ( !l2
.isEmpty() && l2
.first() )
2169 void KMKernel::slotRunBackgroundTasks() // called regularly by timer
2171 // Hidden KConfig keys. Not meant to be used, but a nice fallback in case
2172 // a stable kmail release goes out with a nasty bug in CompactionJob...
2173 KConfigGroup
generalGroup( config(), "General" );
2175 if ( generalGroup
.readEntry( "auto-expiring", true ) ) {
2176 if ( the_folderMgr
)
2177 the_folderMgr
->expireAllFolders( false /*scheduled, not immediate*/ );
2178 if ( the_imapFolderMgr
)
2179 the_imapFolderMgr
->expireAllFolders( false /*scheduled, not immediate*/ );
2180 if ( the_dimapFolderMgr
)
2181 the_dimapFolderMgr
->expireAllFolders( false /*scheduled, not immediate*/ );
2182 // the_searchFolderMgr: no expiry there
2185 if ( generalGroup
.readEntry( "auto-compaction", true ) ) {
2186 if ( the_folderMgr
)
2187 the_folderMgr
->compactAllFolders( false /*scheduled, not immediate*/ );
2188 // the_imapFolderMgr: no compaction
2189 if ( the_dimapFolderMgr
)
2190 the_dimapFolderMgr
->compactAllFolders( false /*scheduled, not immediate*/ );
2191 // the_searchFolderMgr: no compaction
2194 #ifdef DEBUG_SCHEDULER // for debugging, see jobscheduler.h
2195 mBackgroundTasksTimer
->start( 60 * 1000 ); // check again in 1 minute
2197 mBackgroundTasksTimer
->start( 4 * 60 * 60 * 1000 ); // check again in 4 hours
2202 void KMKernel::expireAllFoldersNow() // called by the GUI
2204 the_folderMgr
->expireAllFolders( true /*immediate*/ );
2205 the_imapFolderMgr
->expireAllFolders( true /*immediate*/ );
2206 the_dimapFolderMgr
->expireAllFolders( true /*immediate*/ );
2209 void KMKernel::compactAllFolders() // called by the GUI
2211 the_folderMgr
->compactAllFolders( true /*immediate*/ );
2212 //the_imapFolderMgr->compactAllFolders( true /*immediate*/ );
2213 the_dimapFolderMgr
->compactAllFolders( true /*immediate*/ );
2216 KMFolder
* KMKernel::findFolderById( const QString
& idString
)
2218 KMFolder
* folder
= the_folderMgr
->findIdString( idString
);
2220 folder
= the_imapFolderMgr
->findIdString( idString
);
2222 folder
= the_dimapFolderMgr
->findIdString( idString
);
2224 folder
= the_searchFolderMgr
->findIdString( idString
);
2228 void KMKernel::enableMailCheck()
2230 mMailCheckAborted
= false;
2233 bool KMKernel::mailCheckAborted() const
2235 return mMailCheckAborted
;
2238 void KMKernel::abortMailCheck()
2240 mMailCheckAborted
= true;
2243 bool KMKernel::canQueryClose()
2245 if ( KMMainWidget::mainWidgetList() &&
2246 KMMainWidget::mainWidgetList()->count() > 1 )
2248 KMMainWidget
*widget
= getKMMainWidget();
2251 KMSystemTray
* systray
= widget
->systray();
2252 if ( !systray
|| GlobalSettings::closeDespiteSystemTray() )
2254 if ( systray
->mode() == GlobalSettings::EnumSystemTrayPolicy::ShowAlways
) {
2255 systray
->hideKMail();
2257 } else if ( systray
->mode() == GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread
) {
2259 systray
->hideKMail();
2265 void KMKernel::messageCountChanged()
2267 mTimeOfLastMessageCountChange
= ::time( 0 );
2270 int KMKernel::timeOfLastMessageCountChange() const
2272 return mTimeOfLastMessageCountChange
;
2275 Wallet
*KMKernel::wallet() {
2276 static bool walletOpenFailed
= false;
2277 if ( mWallet
&& mWallet
->isOpen() )
2280 if ( !Wallet::isEnabled() || walletOpenFailed
)
2283 // find an appropriate parent window for the wallet dialog
2285 if ( qApp
->activeWindow() )
2286 window
= qApp
->activeWindow()->winId();
2287 else if ( getKMMainWidget() )
2288 window
= getKMMainWidget()->topLevelWidget()->winId();
2291 mWallet
= Wallet::openWallet( Wallet::NetworkWallet(), window
);
2294 walletOpenFailed
= true;
2298 if ( !mWallet
->hasFolder( "kmail" ) )
2299 mWallet
->createFolder( "kmail" );
2300 mWallet
->setFolder( "kmail" );
2304 QList
< QPointer
<KMFolder
> > KMKernel::allFolders()
2307 QList
<QPointer
<KMFolder
> > folders
;
2308 folderMgr()->createFolderList(&names
, &folders
);
2309 imapFolderMgr()->createFolderList(&names
, &folders
);
2310 dimapFolderMgr()->createFolderList(&names
, &folders
);
2311 searchFolderMgr()->createFolderList(&names
, &folders
);
2316 KMFolder
*KMKernel::currentFolder() {
2317 KMMainWidget
*widget
= getKMMainWidget();
2318 KMFolder
*folder
= 0;
2319 if ( widget
&& widget
->mainFolderView() ) {
2320 folder
= widget
->mainFolderView()->currentFolder();
2325 // can't be inline, since KMSender isn't known to implement
2326 // KMail::MessageSender outside this .cpp file
2327 KMail::MessageSender
* KMKernel::msgSender() { return the_msgSender
; }
2329 void KMKernel::transportRemoved(int id
, const QString
& name
)
2333 // reset all identities using the deleted transport
2334 QStringList changedIdents
;
2335 KPIMIdentities::IdentityManager
* im
= identityManager();
2336 for ( KPIMIdentities::IdentityManager::Iterator it
= im
->modifyBegin(); it
!= im
->modifyEnd(); ++it
) {
2337 if ( name
== (*it
).transport() ) {
2338 (*it
).setTransport( QString() );
2339 changedIdents
+= (*it
).identityName();
2343 // if the deleted transport is the currently used transport reset it to default
2344 const QString
& currentTransport
= GlobalSettings::self()->currentTransport();
2345 if ( name
== currentTransport
)
2346 GlobalSettings::self()->setCurrentTransport( QString() );
2348 if ( !changedIdents
.isEmpty() ) {
2349 QString information
= i18np( "This identity has been changed to use the default transport:",
2350 "These %1 identities have been changed to use the default transport:",
2351 changedIdents
.count() );
2352 KMessageBox::informationList( mWin
, information
, changedIdents
);
2357 void KMKernel::transportRenamed(int id
, const QString
& oldName
, const QString
& newName
)
2361 QStringList changedIdents
;
2362 KPIMIdentities::IdentityManager
* im
= identityManager();
2363 for ( KPIMIdentities::IdentityManager::Iterator it
= im
->modifyBegin(); it
!= im
->modifyEnd(); ++it
) {
2364 if ( oldName
== (*it
).transport() ) {
2365 (*it
).setTransport( newName
);
2366 changedIdents
<< (*it
).identityName();
2370 if ( !changedIdents
.isEmpty() ) {
2371 QString information
=
2372 i18np( "This identity has been changed to use the modified transport:",
2373 "These %1 identities have been changed to use the modified transport:",
2374 changedIdents
.count() );
2375 KMessageBox::informationList( mWin
, information
, changedIdents
);
2380 void KMKernel::updatedTemplates()
2382 emit
customTemplatesChanged();
2386 #include "kmkernel.moc"