kmail

kmmainwidget.cpp

00001 // -*- mode: C++; c-file-style: "gnu" -*-
00002 // kmmainwidget.cpp
00003 //#define MALLOC_DEBUG 1
00004 
00005 #ifdef HAVE_CONFIG_H
00006 #include <config.h>
00007 #endif
00008 
00009 #include <kwin.h>
00010 
00011 #ifdef MALLOC_DEBUG
00012 #include <malloc.h>
00013 #endif
00014 
00015 #undef Unsorted // X headers...
00016 #include <qaccel.h>
00017 #include <qlayout.h>
00018 #include <qhbox.h>
00019 #include <qvbox.h>
00020 #include <qpopupmenu.h>
00021 
00022 #include <kopenwith.h>
00023 
00024 #include <kmessagebox.h>
00025 
00026 #include <kpopupmenu.h>
00027 #include <kaccelmanager.h>
00028 #include <kglobalsettings.h>
00029 #include <kstdaccel.h>
00030 #include <kkeydialog.h>
00031 #include <kcharsets.h>
00032 #include <knotifyclient.h>
00033 #include <kdebug.h>
00034 #include <kapplication.h>
00035 #include <kfiledialog.h>
00036 #include <ktip.h>
00037 #include <knotifydialog.h>
00038 #include <kstandarddirs.h>
00039 #include <dcopclient.h>
00040 #include <kaddrbook.h>
00041 #include <kaccel.h>
00042 
00043 #include "globalsettings.h"
00044 #include "kcursorsaver.h"
00045 #include "broadcaststatus.h"
00046 using KPIM::BroadcastStatus;
00047 #include "kmfoldermgr.h"
00048 #include "kmfolderdia.h"
00049 #include "accountmanager.h"
00050 using KMail::AccountManager;
00051 #include "kmfilter.h"
00052 #include "kmfoldertree.h"
00053 #include "kmreadermainwin.h"
00054 #include "kmfoldercachedimap.h"
00055 #include "kmfolderimap.h"
00056 #include "kmacctcachedimap.h"
00057 #include "composer.h"
00058 #include "kmfolderseldlg.h"
00059 #include "kmfiltermgr.h"
00060 #include "messagesender.h"
00061 #include "kmaddrbook.h"
00062 #include "kmversion.h"
00063 #include "searchwindow.h"
00064 using KMail::SearchWindow;
00065 #include "kmacctfolder.h"
00066 #include "undostack.h"
00067 #include "kmcommands.h"
00068 #include "kmmainwin.h"
00069 #include "kmsystemtray.h"
00070 #include "imapaccountbase.h"
00071 #include "transportmanager.h"
00072 using KMail::ImapAccountBase;
00073 #include "vacation.h"
00074 using KMail::Vacation;
00075 
00076 #include "subscriptiondialog.h"
00077 using KMail::SubscriptionDialog;
00078 #include "attachmentstrategy.h"
00079 using KMail::AttachmentStrategy;
00080 #include "headerstrategy.h"
00081 using KMail::HeaderStrategy;
00082 #include "headerstyle.h"
00083 using KMail::HeaderStyle;
00084 #include "folderjob.h"
00085 using KMail::FolderJob;
00086 #include "mailinglist-magic.h"
00087 #include "antispamwizard.h"
00088 using KMail::AntiSpamWizard;
00089 #include "filterlogdlg.h"
00090 using KMail::FilterLogDialog;
00091 #include <headerlistquicksearch.h>
00092 #include "klistviewindexedsearchline.h"
00093 using KMail::HeaderListQuickSearch;
00094 #include "kmheaders.h"
00095 #include "mailinglistpropertiesdialog.h"
00096 
00097 #if !defined(NDEBUG)
00098     #include "sievedebugdialog.h"
00099     using KMail::SieveDebugDialog;
00100 #endif
00101 
00102 #include <assert.h>
00103 #include <kstatusbar.h>
00104 #include <kstaticdeleter.h>
00105 #include <kaction.h>
00106 
00107 #include <kmime_mdn.h>
00108 #include <kmime_header_parsing.h>
00109 using namespace KMime;
00110 using KMime::Types::AddrSpecList;
00111 
00112 #include "progressmanager.h"
00113 using KPIM::ProgressManager;
00114 
00115 #include "managesievescriptsdialog.h"
00116 #include <qstylesheet.h>
00117 
00118 #include "kmmainwidget.moc"
00119 
00120 QValueList<KMMainWidget*>* KMMainWidget::s_mainWidgetList = 0;
00121 static KStaticDeleter<QValueList<KMMainWidget*> > mwlsd;
00122 
00123 //-----------------------------------------------------------------------------
00124 KMMainWidget::KMMainWidget(QWidget *parent, const char *name,
00125                            KXMLGUIClient *aGUIClient,
00126                            KActionCollection *actionCollection, KConfig* config ) :
00127     QWidget(parent, name),
00128     mQuickSearchLine( 0 ),
00129     mShowBusySplashTimer( 0 ),
00130     mShowingOfflineScreen( false )
00131 {
00132   // must be the first line of the constructor:
00133   mStartupDone = FALSE;
00134   mSearchWin = 0;
00135   mIntegrated  = TRUE;
00136   mFolder = 0;
00137   mFolderThreadPref = false;
00138   mFolderThreadSubjPref = true;
00139   mReaderWindowActive = true;
00140   mReaderWindowBelow = true;
00141   mFolderHtmlPref = false;
00142   mFolderHtmlLoadExtPref = false;
00143   mSystemTray = 0;
00144   mDestructed = false;
00145   mActionCollection = actionCollection;
00146   mTopLayout = new QVBoxLayout(this);
00147   mFilterMenuActions.setAutoDelete(true);
00148   mFilterTBarActions.setAutoDelete(false);
00149   mFilterCommands.setAutoDelete(true);
00150   mFolderShortcutCommands.setAutoDelete(true);
00151   mJob = 0;
00152   mConfig = config;
00153   mGUIClient = aGUIClient;
00154   // FIXME This should become a line separator as soon as the API
00155   // is extended in kdelibs.
00156   mToolbarActionSeparator = new KActionSeparator( actionCollection );
00157 
00158   if( !s_mainWidgetList )
00159     mwlsd.setObject( s_mainWidgetList, new QValueList<KMMainWidget*>() );
00160   s_mainWidgetList->append( this );
00161 
00162   mPanner1Sep << 1 << 1;
00163   mPanner2Sep << 1 << 1;
00164 
00165   setMinimumSize(400, 300);
00166 
00167   readPreConfig();
00168   createWidgets();
00169 
00170   setupActions();
00171 
00172   readConfig();
00173 
00174   activatePanners();
00175 
00176   QTimer::singleShot( 0, this, SLOT( slotShowStartupFolder() ));
00177 
00178   connect( kmkernel->acctMgr(), SIGNAL( checkedMail( bool, bool, const QMap<QString, int> & ) ),
00179            this, SLOT( slotMailChecked( bool, bool, const QMap<QString, int> & ) ) );
00180 
00181   connect( kmkernel->acctMgr(), SIGNAL( accountAdded( KMAccount* ) ),
00182            this, SLOT( initializeIMAPActions() ) );
00183   connect( kmkernel->acctMgr(), SIGNAL( accountRemoved( KMAccount* ) ),
00184            this, SLOT( initializeIMAPActions() ) );
00185 
00186   connect(kmkernel, SIGNAL( configChanged() ),
00187           this, SLOT( slotConfigChanged() ));
00188 
00189   // display the full path to the folder in the caption
00190   connect(mFolderTree, SIGNAL(currentChanged(QListViewItem*)),
00191       this, SLOT(slotChangeCaption(QListViewItem*)));
00192 
00193   connect(kmkernel->folderMgr(), SIGNAL(folderRemoved(KMFolder*)),
00194           this, SLOT(slotFolderRemoved(KMFolder*)));
00195 
00196   connect(kmkernel->imapFolderMgr(), SIGNAL(folderRemoved(KMFolder*)),
00197           this, SLOT(slotFolderRemoved(KMFolder*)));
00198 
00199   connect(kmkernel->dimapFolderMgr(), SIGNAL(folderRemoved(KMFolder*)),
00200           this, SLOT(slotFolderRemoved(KMFolder*)));
00201 
00202   connect(kmkernel->searchFolderMgr(), SIGNAL(folderRemoved(KMFolder*)),
00203           this, SLOT(slotFolderRemoved(KMFolder*)));
00204 
00205   connect( kmkernel, SIGNAL( onlineStatusChanged( GlobalSettings::EnumNetworkState::type ) ),
00206            this, SLOT( slotUpdateOnlineStatus( GlobalSettings::EnumNetworkState::type ) ) );
00207 
00208   toggleSystemTray();
00209 
00210   // must be the last line of the constructor:
00211   mStartupDone = TRUE;
00212 }
00213 
00214 
00215 //-----------------------------------------------------------------------------
00216 //The kernel may have already been deleted when this method is called,
00217 //perform all cleanup that requires the kernel in destruct()
00218 KMMainWidget::~KMMainWidget()
00219 {
00220   s_mainWidgetList->remove( this );
00221   destruct();
00222 }
00223 
00224 
00225 //-----------------------------------------------------------------------------
00226 //This method performs all cleanup that requires the kernel to exist.
00227 void KMMainWidget::destruct()
00228 {
00229   if (mDestructed)
00230     return;
00231   if (mSearchWin)
00232     mSearchWin->close();
00233   writeConfig();
00234   writeFolderConfig();
00235   delete mHeaders;
00236   delete mFolderTree;
00237   delete mSystemTray;
00238   delete mMsgView;
00239   mDestructed = true;
00240 }
00241 
00242 
00243 //-----------------------------------------------------------------------------
00244 void KMMainWidget::readPreConfig(void)
00245 {
00246   const KConfigGroup geometry( KMKernel::config(), "Geometry" );
00247   const KConfigGroup general( KMKernel::config(), "General" );
00248 
00249   mLongFolderList = geometry.readEntry( "FolderList", "long" ) != "short";
00250   mReaderWindowActive = geometry.readEntry( "readerWindowMode", "below" ) != "hide";
00251   mReaderWindowBelow = geometry.readEntry( "readerWindowMode", "below" ) == "below";
00252 }
00253 
00254 
00255 //-----------------------------------------------------------------------------
00256 void KMMainWidget::readFolderConfig(void)
00257 {
00258   if (!mFolder)
00259     return;
00260 
00261   KConfig *config = KMKernel::config();
00262   KConfigGroupSaver saver(config, "Folder-" + mFolder->idString());
00263   mFolderThreadPref = config->readBoolEntry( "threadMessagesOverride", false );
00264   mFolderThreadSubjPref = config->readBoolEntry( "threadMessagesBySubject", true );
00265   mFolderHtmlPref = config->readBoolEntry( "htmlMailOverride", false );
00266   mFolderHtmlLoadExtPref = config->readBoolEntry( "htmlLoadExternalOverride", false );
00267 }
00268 
00269 
00270 //-----------------------------------------------------------------------------
00271 void KMMainWidget::writeFolderConfig(void)
00272 {
00273   if (!mFolder)
00274     return;
00275 
00276   KConfig *config = KMKernel::config();
00277   KConfigGroupSaver saver(config, "Folder-" + mFolder->idString());
00278   config->writeEntry( "threadMessagesOverride", mFolderThreadPref );
00279   config->writeEntry( "threadMessagesBySubject", mFolderThreadSubjPref );
00280   config->writeEntry( "htmlMailOverride", mFolderHtmlPref );
00281   config->writeEntry( "htmlLoadExternalOverride", mFolderHtmlLoadExtPref );
00282 }
00283 
00284 
00285 //-----------------------------------------------------------------------------
00286 void KMMainWidget::readConfig(void)
00287 {
00288   KConfig *config = KMKernel::config();
00289 
00290   bool oldLongFolderList =  mLongFolderList;
00291   bool oldReaderWindowActive = mReaderWindowActive;
00292   bool oldReaderWindowBelow = mReaderWindowBelow;
00293 
00294   QString str;
00295   QSize siz;
00296 
00297   if (mStartupDone)
00298   {
00299     writeConfig();
00300 
00301     readPreConfig();
00302     mHeaders->refreshNestedState();
00303 
00304     bool layoutChanged = ( oldLongFolderList != mLongFolderList )
00305                     || ( oldReaderWindowActive != mReaderWindowActive )
00306                     || ( oldReaderWindowBelow != mReaderWindowBelow );
00307 
00308 
00309     if( layoutChanged ) {
00310       hide();
00311       // delete all panners
00312       delete mPanner1; // will always delete the others
00313       createWidgets();
00314     }
00315 
00316   }
00317 
00318   // read "Reader" config options
00319   KConfigGroup readerConfig( config, "Reader" );
00320   mHtmlPref = readerConfig.readBoolEntry( "htmlMail", false );
00321   mHtmlLoadExtPref = readerConfig.readBoolEntry( "htmlLoadExternal", false );
00322 
00323   { // area for config group "Geometry"
00324     KConfigGroupSaver saver(config, "Geometry");
00325     mThreadPref = config->readBoolEntry( "nestedMessages", false );
00326     // size of the mainwin
00327     QSize defaultSize(750,560);
00328     siz = config->readSizeEntry("MainWin", &defaultSize);
00329     if (!siz.isEmpty())
00330       resize(siz);
00331     // default width of the foldertree
00332     static const int folderpanewidth = 250;
00333 
00334     const int folderW = config->readNumEntry( "FolderPaneWidth", folderpanewidth );
00335     const int headerW = config->readNumEntry( "HeaderPaneWidth", width()-folderpanewidth );
00336     const int headerH = config->readNumEntry( "HeaderPaneHeight", 180 );
00337     const int readerH = config->readNumEntry( "ReaderPaneHeight", 280 );
00338 
00339     mPanner1Sep.clear();
00340     mPanner2Sep.clear();
00341     QValueList<int> & widths = mLongFolderList ? mPanner1Sep : mPanner2Sep ;
00342     QValueList<int> & heights = mLongFolderList ? mPanner2Sep : mPanner1Sep ;
00343 
00344     widths << folderW << headerW;
00345     heights << headerH << readerH;
00346 
00347     bool layoutChanged = ( oldLongFolderList != mLongFolderList )
00348                     || ( oldReaderWindowActive != mReaderWindowActive )
00349                     || ( oldReaderWindowBelow != mReaderWindowBelow );
00350 
00351     if (!mStartupDone || layoutChanged )
00352     {
00356       // The columns are shown by default.
00357 
00358       const int unreadColumn = config->readNumEntry("UnreadColumn", 1);
00359       const int totalColumn = config->readNumEntry("TotalColumn", 2);
00360 
00361       /* we need to _activate_ them in the correct order
00362       * this is ugly because we can't use header()->moveSection
00363       * but otherwise the restoreLayout from KMFolderTree
00364       * doesn't know that to do */
00365       if (unreadColumn != -1 && unreadColumn < totalColumn)
00366         mFolderTree->addUnreadColumn( i18n("Unread"), 70 );
00367       if (totalColumn != -1)
00368         mFolderTree->addTotalColumn( i18n("Total"), 70 );
00369       if (unreadColumn != -1 && unreadColumn > totalColumn)
00370         mFolderTree->addUnreadColumn( i18n("Unread"), 70 );
00371       mUnreadColumnToggle->setChecked( mFolderTree->isUnreadActive() );
00372       mUnreadTextToggle->setChecked( !mFolderTree->isUnreadActive() );
00373       mTotalColumnToggle->setChecked( mFolderTree->isTotalActive() );
00374 
00375       mFolderTree->updatePopup();
00376     }
00377   }
00378 
00379   if (mMsgView)
00380     mMsgView->readConfig();
00381 
00382   mHeaders->readConfig();
00383   mHeaders->restoreLayout(KMKernel::config(), "Header-Geometry");
00384 
00385   mFolderTree->readConfig();
00386 
00387   { // area for config group "General"
00388     KConfigGroupSaver saver(config, "General");
00389     mBeepOnNew = config->readBoolEntry("beep-on-mail", false);
00390     mConfirmEmpty = config->readBoolEntry("confirm-before-empty", true);
00391     // startup-Folder, defaults to system-inbox
00392     mStartupFolder = config->readEntry("startupFolder", kmkernel->inboxFolder()->idString());
00393     if (!mStartupDone)
00394     {
00395       // check mail on startup
00396       bool check = config->readBoolEntry("checkmail-startup", false);
00397       if (check)
00398         // do it after building the kmmainwin, so that the progressdialog is available
00399         QTimer::singleShot( 0, this, SLOT( slotCheckMail() ) );
00400     }
00401   }
00402 
00403   // reload foldertree
00404   mFolderTree->reload();
00405 
00406   // Re-activate panners
00407   if (mStartupDone)
00408   {
00409     // Update systray
00410     toggleSystemTray();
00411 
00412     bool layoutChanged = ( oldLongFolderList != mLongFolderList )
00413                     || ( oldReaderWindowActive != mReaderWindowActive )
00414                     || ( oldReaderWindowBelow != mReaderWindowBelow );
00415     if ( layoutChanged ) {
00416       activatePanners();
00417     }
00418 
00419     mFolderTree->showFolder( mFolder );
00420 
00421     // sanders - New code
00422     mHeaders->setFolder(mFolder);
00423     if (mMsgView) {
00424       int aIdx = mHeaders->currentItemIndex();
00425       if (aIdx != -1)
00426         mMsgView->setMsg( mFolder->getMsg(aIdx), true );
00427       else
00428         mMsgView->clear( true );
00429     }
00430     updateMessageActions();
00431     show();
00432     // sanders - Maybe this fixes a bug?
00433 
00434   }
00435   updateMessageMenu();
00436   updateFileMenu();
00437 }
00438 
00439 
00440 //-----------------------------------------------------------------------------
00441 void KMMainWidget::writeConfig(void)
00442 {
00443   QString s;
00444   KConfig *config = KMKernel::config();
00445   KConfigGroup geometry( config, "Geometry" );
00446   KConfigGroup general( config, "General" );
00447 
00448   if (mMsgView)
00449     mMsgView->writeConfig();
00450 
00451   mFolderTree->writeConfig();
00452 
00453   geometry.writeEntry( "MainWin", this->geometry().size() );
00454 
00455   const QValueList<int> widths = ( mLongFolderList ? mPanner1 : mPanner2 )->sizes();
00456   const QValueList<int> heights = ( mLongFolderList ? mPanner2 : mPanner1 )->sizes();
00457 
00458   geometry.writeEntry( "FolderPaneWidth", widths[0] );
00459   geometry.writeEntry( "HeaderPaneWidth", widths[1] );
00460 
00461   // Only save when the widget is shown (to avoid saving a wrong value)
00462   if ( mSearchAndHeaders && mSearchAndHeaders->isShown() ) {
00463     geometry.writeEntry( "HeaderPaneHeight", heights[0] );
00464     geometry.writeEntry( "ReaderPaneHeight", heights[1] );
00465   }
00466 
00467   // save the state of the unread/total-columns
00468   geometry.writeEntry( "UnreadColumn", mFolderTree->unreadIndex() );
00469   geometry.writeEntry( "TotalColumn", mFolderTree->totalIndex() );
00470 }
00471 
00472 
00473 //-----------------------------------------------------------------------------
00474 void KMMainWidget::createWidgets(void)
00475 {
00476   // Create the splitters according to the layout settings
00477   QWidget *headerParent = 0, *folderParent = 0,
00478             *mimeParent = 0, *messageParent = 0;
00479 
00480   const bool opaqueResize = KGlobalSettings::opaqueResize();
00481   if ( mLongFolderList ) {
00482     // superior splitter: folder tree vs. rest
00483     // inferior splitter: headers vs. message vs. mime tree
00484     mPanner1 = new QSplitter( Qt::Horizontal, this, "panner 1" );
00485     mPanner1->setOpaqueResize( opaqueResize );
00486     Qt::Orientation orientation = mReaderWindowBelow ? Qt::Vertical : Qt::Horizontal;
00487     mPanner2 = new QSplitter( orientation, mPanner1, "panner 2" );
00488     mPanner2->setOpaqueResize( opaqueResize );
00489     folderParent = mPanner1;
00490     headerParent = mimeParent = messageParent = mPanner2;
00491   } else /* !mLongFolderList */ {
00492     // superior splitter: ( folder tree + headers ) vs. message vs. mime
00493     // inferior splitter: folder tree vs. headers
00494     mPanner1 = new QSplitter( Qt::Vertical, this, "panner 1" );
00495     mPanner1->setOpaqueResize( opaqueResize );
00496     mPanner2 = new QSplitter( Qt::Horizontal, mPanner1, "panner 2" );
00497     mPanner2->setOpaqueResize( opaqueResize );
00498     headerParent = folderParent = mPanner2;
00499     mimeParent = messageParent = mPanner1;
00500   }
00501 
00502 #ifndef NDEBUG
00503   if( mPanner1 ) mPanner1->dumpObjectTree();
00504   if( mPanner2 ) mPanner2->dumpObjectTree();
00505 #endif
00506 
00507   mTopLayout->add( mPanner1 );
00508 
00509   // BUG -sanders these accelerators stop working after switching
00510   // between long/short folder layout
00511   // Probably need to disconnect them first.
00512 
00513   // create list of messages
00514 #ifndef NDEBUG
00515   headerParent->dumpObjectTree();
00516 #endif
00517   mSearchAndHeaders = new QVBox( headerParent );
00518   mSearchToolBar = new KToolBar( mSearchAndHeaders, "search toolbar");
00519   mSearchToolBar->setMovingEnabled(false);
00520   mSearchToolBar->boxLayout()->setSpacing( KDialog::spacingHint() );
00521   QLabel *label = new QLabel( i18n("S&earch:"), mSearchToolBar, "kde toolbar widget" );
00522 
00523 
00524   mHeaders = new KMHeaders(this, mSearchAndHeaders, "headers");
00525 #ifdef HAVE_INDEXLIB
00526   mQuickSearchLine = new KListViewIndexedSearchLine( mSearchToolBar, mHeaders,
00527                                                     actionCollection(), "headers quick search line" );
00528 #else
00529   mQuickSearchLine = new HeaderListQuickSearch( mSearchToolBar, mHeaders,
00530                         actionCollection(), "headers quick search line" );
00531 #endif
00532   label->setBuddy( mQuickSearchLine );
00533   mSearchToolBar->setStretchableWidget( mQuickSearchLine );
00534     connect( mHeaders, SIGNAL( messageListUpdated() ),
00535            mQuickSearchLine, SLOT( updateSearch() ) );
00536   if ( !GlobalSettings::self()->quickSearchActive() ) mSearchToolBar->hide();
00537 
00538   if (mReaderWindowActive) {
00539     connect(mHeaders, SIGNAL(selected(KMMessage*)),
00540             this, SLOT(slotMsgSelected(KMMessage*)));
00541   }
00542   connect(mHeaders, SIGNAL(activated(KMMessage*)),
00543           this, SLOT(slotMsgActivated(KMMessage*)));
00544   connect( mHeaders, SIGNAL( selectionChanged() ),
00545            SLOT( startUpdateMessageActionsTimer() ) );
00546   QAccel *accel = actionCollection()->kaccel();
00547   accel->connectItem(accel->insertItem(SHIFT+Key_Left),
00548                      mHeaders, SLOT(selectPrevMessage()));
00549   accel->connectItem(accel->insertItem(SHIFT+Key_Right),
00550                      mHeaders, SLOT(selectNextMessage()));
00551 
00552   if (mReaderWindowActive) {
00553     mMsgView = new KMReaderWin(messageParent, this, actionCollection(), 0 );
00554 
00555     connect(mMsgView, SIGNAL(replaceMsgByUnencryptedVersion()),
00556         this, SLOT(slotReplaceMsgByUnencryptedVersion()));
00557     connect(mMsgView, SIGNAL(popupMenu(KMMessage&,const KURL&,const QPoint&)),
00558         this, SLOT(slotMsgPopup(KMMessage&,const KURL&,const QPoint&)));
00559     connect(mMsgView, SIGNAL(urlClicked(const KURL&,int)),
00560         mMsgView, SLOT(slotUrlClicked()));
00561     connect(mHeaders, SIGNAL(maybeDeleting()),
00562         mMsgView, SLOT(clearCache()));
00563     connect(mMsgView, SIGNAL(noDrag()),
00564         mHeaders, SLOT(slotNoDrag()));
00565     accel->connectItem(accel->insertItem(Key_Up),
00566         mMsgView, SLOT(slotScrollUp()));
00567     accel->connectItem(accel->insertItem(Key_Down),
00568         mMsgView, SLOT(slotScrollDown()));
00569     accel->connectItem(accel->insertItem(Key_Prior),
00570         mMsgView, SLOT(slotScrollPrior()));
00571     accel->connectItem(accel->insertItem(Key_Next),
00572         mMsgView, SLOT(slotScrollNext()));
00573   } else {
00574     mMsgView = NULL;
00575   }
00576 
00577   KAction *action;
00578 
00579   action = new KAction( i18n("Move Message to Folder"), Key_M, this,
00580                SLOT(slotMoveMsg()), actionCollection(),
00581                "move_message_to_folder" );
00582   action->plugAccel( actionCollection()->kaccel() );
00583 
00584   action = new KAction( i18n("Copy Message to Folder"), Key_C, this,
00585                SLOT(slotCopyMsg()), actionCollection(),
00586                "copy_message_to_folder" );
00587   action->plugAccel( actionCollection()->kaccel() );
00588 
00589   action = new KAction( i18n("Jump to Folder"), Key_J, this,
00590                SLOT(slotJumpToFolder()), actionCollection(),
00591                "jump_to_folder" );
00592   action->plugAccel( actionCollection()->kaccel() );
00593 
00594   // create list of folders
00595   mFolderTree = new KMFolderTree(this, folderParent, "folderTree");
00596 
00597   connect(mFolderTree, SIGNAL(folderSelected(KMFolder*)),
00598       this, SLOT(folderSelected(KMFolder*)));
00599   connect( mFolderTree, SIGNAL( folderSelected( KMFolder* ) ),
00600            mQuickSearchLine, SLOT( reset() ) );
00601   connect(mFolderTree, SIGNAL(folderSelectedUnread(KMFolder*)),
00602       this, SLOT(folderSelectedUnread(KMFolder*)));
00603   connect(mFolderTree, SIGNAL(folderDrop(KMFolder*)),
00604       this, SLOT(slotMoveMsgToFolder(KMFolder*)));
00605   connect(mFolderTree, SIGNAL(folderDropCopy(KMFolder*)),
00606           this, SLOT(slotCopyMsgToFolder(KMFolder*)));
00607   connect(mFolderTree, SIGNAL(columnsChanged()),
00608           this, SLOT(slotFolderTreeColumnsChanged()));
00609 
00610   //Commands not worthy of menu items, but that deserve configurable keybindings
00611   action = new KAction(
00612     i18n("Remove Duplicate Messages"), CTRL+Key_Asterisk, this,
00613     SLOT(removeDuplicates()), actionCollection(), "remove_duplicate_messages");
00614   action->plugAccel( actionCollection()->kaccel() );
00615 
00616   action = new KAction(
00617     i18n("Abort Current Operation"), Key_Escape, ProgressManager::instance(),
00618     SLOT(slotAbortAll()), actionCollection(), "cancel" );
00619   action->plugAccel( actionCollection()->kaccel() );
00620 
00621   action = new KAction(
00622    i18n("Focus on Next Folder"), CTRL+Key_Right, mFolderTree,
00623    SLOT(incCurrentFolder()), actionCollection(), "inc_current_folder");
00624   action->plugAccel( actionCollection()->kaccel() );
00625 
00626   action = new KAction(
00627    i18n("Focus on Previous Folder"), CTRL+Key_Left, mFolderTree,
00628    SLOT(decCurrentFolder()), actionCollection(), "dec_current_folder");
00629   action->plugAccel( actionCollection()->kaccel() );
00630 
00631   action = new KAction(
00632    i18n("Select Folder with Focus"), CTRL+Key_Space, mFolderTree,
00633    SLOT(selectCurrentFolder()), actionCollection(), "select_current_folder");
00634   action->plugAccel( actionCollection()->kaccel() );
00635 
00636   action = new KAction(
00637     i18n("Focus on Next Message"), ALT+Key_Right, mHeaders,
00638     SLOT(incCurrentMessage()), actionCollection(), "inc_current_message");
00639   action->plugAccel( actionCollection()->kaccel() );
00640 
00641   action = new KAction(
00642     i18n("Focus on Previous Message"), ALT+Key_Left, mHeaders,
00643     SLOT(decCurrentMessage()), actionCollection(), "dec_current_message");
00644   action->plugAccel( actionCollection()->kaccel() );
00645 
00646   action = new KAction(
00647     i18n("Select Message with Focus"), ALT+Key_Space, mHeaders,
00648     SLOT( selectCurrentMessage() ), actionCollection(), "select_current_message");
00649   action->plugAccel( actionCollection()->kaccel() );
00650 
00651   connect( kmkernel->outboxFolder(), SIGNAL( msgRemoved(int, QString) ),
00652            SLOT( startUpdateMessageActionsTimer() ) );
00653   connect( kmkernel->outboxFolder(), SIGNAL( msgAdded(int) ),
00654            SLOT( startUpdateMessageActionsTimer() ) );
00655 }
00656 
00657 
00658 //-----------------------------------------------------------------------------
00659 void KMMainWidget::activatePanners(void)
00660 {
00661   if (mMsgView) {
00662     QObject::disconnect( mMsgView->copyAction(),
00663         SIGNAL( activated() ),
00664         mMsgView, SLOT( slotCopySelectedText() ));
00665   }
00666   if ( mLongFolderList ) {
00667     mSearchAndHeaders->reparent( mPanner2, 0, QPoint( 0, 0 ) );
00668     if (mMsgView) {
00669       mMsgView->reparent( mPanner2, 0, QPoint( 0, 0 ) );
00670       mPanner2->moveToLast( mMsgView );
00671     }
00672     mFolderTree->reparent( mPanner1, 0, QPoint( 0, 0 ) );
00673     mPanner1->moveToLast( mPanner2 );
00674     mPanner1->setSizes( mPanner1Sep );
00675     mPanner1->setResizeMode( mFolderTree, QSplitter::KeepSize );
00676     mPanner2->setSizes( mPanner2Sep );
00677     mPanner2->setResizeMode( mSearchAndHeaders, QSplitter::KeepSize );
00678   } else /* !mLongFolderList */ {
00679     mFolderTree->reparent( mPanner2, 0, QPoint( 0, 0 ) );
00680     mSearchAndHeaders->reparent( mPanner2, 0, QPoint( 0, 0 ) );
00681     mPanner2->moveToLast( mSearchAndHeaders );
00682     mPanner1->moveToFirst( mPanner2 );
00683     if (mMsgView) {
00684       mMsgView->reparent( mPanner1, 0, QPoint( 0, 0 ) );
00685       mPanner1->moveToLast( mMsgView );
00686     }
00687     mPanner1->setSizes( mPanner1Sep );
00688     mPanner2->setSizes( mPanner2Sep );
00689     mPanner1->setResizeMode( mPanner2, QSplitter::KeepSize );
00690     mPanner2->setResizeMode( mFolderTree, QSplitter::KeepSize );
00691   }
00692 
00693   if (mMsgView) {
00694     QObject::connect( mMsgView->copyAction(),
00695             SIGNAL( activated() ),
00696             mMsgView, SLOT( slotCopySelectedText() ));
00697   }
00698 }
00699 
00700 
00701 //-----------------------------------------------------------------------------
00702 void KMMainWidget::hide()
00703 {
00704   QWidget::hide();
00705 }
00706 
00707 
00708 //-----------------------------------------------------------------------------
00709 void KMMainWidget::show()
00710 {
00711   QWidget::show();
00712 }
00713 
00714 //-------------------------------------------------------------------------
00715 void KMMainWidget::slotSearch()
00716 {
00717   if(!mSearchWin)
00718   {
00719     mSearchWin = new SearchWindow(this, "Search", mFolder, false);
00720     connect(mSearchWin, SIGNAL(destroyed()),
00721         this, SLOT(slotSearchClosed()));
00722   }
00723   else
00724   {
00725     mSearchWin->activateFolder(mFolder);
00726   }
00727 
00728   mSearchWin->show();
00729   KWin::activateWindow( mSearchWin->winId() );
00730 }
00731 
00732 
00733 //-------------------------------------------------------------------------
00734 void KMMainWidget::slotSearchClosed()
00735 {
00736   mSearchWin = 0;
00737 }
00738 
00739 
00740 //-------------------------------------------------------------------------
00741 void KMMainWidget::slotFind()
00742 {
00743   if( mMsgView )
00744     mMsgView->slotFind();
00745 }
00746 
00747 
00748 //-----------------------------------------------------------------------------
00749 void KMMainWidget::slotHelp()
00750 {
00751   kapp->invokeHelp();
00752 }
00753 
00754 
00755 //-----------------------------------------------------------------------------
00756 void KMMainWidget::slotFilter()
00757 {
00758   kmkernel->filterMgr()->openDialog( this );
00759 }
00760 
00761 
00762 //-----------------------------------------------------------------------------
00763 void KMMainWidget::slotPopFilter()
00764 {
00765   kmkernel->popFilterMgr()->openDialog( this );
00766 }
00767 
00768 void KMMainWidget::slotManageSieveScripts()
00769 {
00770   if ( !kmkernel->askToGoOnline() ) {
00771     return;
00772   }
00773   KMail::ManageSieveScriptsDialog * dlg = new KMail::ManageSieveScriptsDialog( this );
00774   dlg->show();
00775 }
00776 
00777 
00778 //-----------------------------------------------------------------------------
00779 void KMMainWidget::slotAddrBook()
00780 {
00781   KAddrBookExternal::openAddressBook(this);
00782 }
00783 
00784 
00785 //-----------------------------------------------------------------------------
00786 void KMMainWidget::slotImport()
00787 {
00788   KRun::runCommand("kmailcvt");
00789 }
00790 
00791 //-----------------------------------------------------------------------------
00792 void KMMainWidget::slotCheckMail()
00793 {
00794   if ( !kmkernel->askToGoOnline() ) {
00795     return;
00796   }
00797   kmkernel->acctMgr()->checkMail(true);
00798 }
00799 
00800 //-----------------------------------------------------------------------------
00801 void KMMainWidget::slotCheckOneAccount(int item)
00802 {
00803   if ( !kmkernel->askToGoOnline() ) {
00804     return;
00805   }
00806   kmkernel->acctMgr()->intCheckMail(item);
00807 }
00808 
00809 //-----------------------------------------------------------------------------
00810 void KMMainWidget::slotMailChecked( bool newMail, bool sendOnCheck,
00811                                     const QMap<QString, int> & newInFolder )
00812 {
00813   const bool sendOnAll =
00814     GlobalSettings::self()->sendOnCheck() == GlobalSettings::EnumSendOnCheck::SendOnAllChecks;
00815   const bool sendOnManual =
00816     GlobalSettings::self()->sendOnCheck() == GlobalSettings::EnumSendOnCheck::SendOnManualChecks;
00817   if( sendOnAll || (sendOnManual && sendOnCheck ) )
00818     slotSendQueued();
00819 
00820   if ( !newMail || newInFolder.isEmpty() )
00821     return;
00822 
00823   kapp->dcopClient()->emitDCOPSignal( "unreadCountChanged()", QByteArray() );
00824 
00825   // build summary for new mail message
00826   bool showNotification = false;
00827   QString summary;
00828   QStringList keys( newInFolder.keys() );
00829   keys.sort();
00830   for ( QStringList::const_iterator it = keys.begin();
00831         it != keys.end();
00832         ++it ) {
00833     kdDebug(5006) << newInFolder.find( *it ).data() << " new message(s) in "
00834                   << *it << endl;
00835 
00836     KMFolder *folder = kmkernel->findFolderById( *it );
00837 
00838     if ( !folder->ignoreNewMail() ) {
00839       showNotification = true;
00840       if ( GlobalSettings::self()->verboseNewMailNotification() ) {
00841         summary += "<br>" + i18n( "1 new message in %1",
00842                                   "%n new messages in %1",
00843                                   newInFolder.find( *it ).data() )
00844                             .arg( folder->prettyURL() );
00845       }
00846     }
00847   }
00848 
00849   if ( !showNotification )
00850     return;
00851 
00852   if ( GlobalSettings::self()->verboseNewMailNotification() ) {
00853     summary = i18n( "%1 is a list of the number of new messages per folder",
00854                     "<b>New mail arrived</b><br>%1" )
00855               .arg( summary );
00856   }
00857   else {
00858     summary = i18n( "New mail arrived" );
00859   }
00860 
00861   if(kmkernel->xmlGuiInstance()) {
00862     KNotifyClient::Instance instance(kmkernel->xmlGuiInstance());
00863     KNotifyClient::event( topLevelWidget()->winId(), "new-mail-arrived",
00864                           summary );
00865   }
00866   else
00867     KNotifyClient::event( topLevelWidget()->winId(), "new-mail-arrived",
00868                           summary );
00869 
00870   if (mBeepOnNew) {
00871     KNotifyClient::beep();
00872   }
00873 }
00874 
00875 
00876 //-----------------------------------------------------------------------------
00877 void KMMainWidget::slotCompose()
00878 {
00879   KMail::Composer * win;
00880   KMMessage* msg = new KMMessage;
00881 
00882   if ( mFolder ) {
00883       msg->initHeader( mFolder->identity() );
00884       win = KMail::makeComposer( msg, mFolder->identity() );
00885   } else {
00886       msg->initHeader();
00887       win = KMail::makeComposer( msg );
00888   }
00889 
00890   win->show();
00891 
00892 }
00893 
00894 
00895 //-----------------------------------------------------------------------------
00896 void KMMainWidget::slotPostToML()
00897 {
00898   if ( mFolder && mFolder->isMailingListEnabled() ) {
00899     KMCommand *command = new KMMailingListPostCommand( this, mFolder );
00900     command->start();
00901   }
00902   else
00903     slotCompose();
00904 }
00905 
00906 //-----------------------------------------------------------------------------
00907 void KMMainWidget::slotFolderMailingListProperties()
00908 {
00909   if (!mFolderTree) return;
00910   KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( mFolderTree->currentItem() );
00911   if ( !item ) return;
00912   KMFolder* folder = item->folder();
00913   if ( folder ) {
00914     ( new KMail::MailingListFolderPropertiesDialog( this, folder ) )->show();
00915   }
00916 }
00917 
00918 //-----------------------------------------------------------------------------
00919 void KMMainWidget::slotFolderShortcutCommand()
00920 {
00921   if (!mFolderTree) return;
00922   KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( mFolderTree->currentItem() );
00923   if ( item )
00924     item->assignShortcut();
00925 }
00926 
00927 
00928 //-----------------------------------------------------------------------------
00929 void KMMainWidget::slotModifyFolder()
00930 {
00931   if (!mFolderTree) return;
00932   KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( mFolderTree->currentItem() );
00933   if ( item )
00934     modifyFolder( item );
00935 }
00936 
00937 //-----------------------------------------------------------------------------
00938 void KMMainWidget::modifyFolder( KMFolderTreeItem* folderItem )
00939 {
00940   KMFolder* folder = folderItem->folder();
00941   KMFolderTree* folderTree = static_cast<KMFolderTree *>( folderItem->listView() );
00942   KMFolderDialog props( folder, folder->parent(), folderTree,
00943                         i18n("Properties of Folder %1").arg( folder->label() ) );
00944   props.exec();
00945   updateFolderMenu();
00946 }
00947 
00948 //-----------------------------------------------------------------------------
00949 void KMMainWidget::slotExpireFolder()
00950 {
00951   QString     str;
00952   bool        canBeExpired = true;
00953 
00954   if (!mFolder) return;
00955 
00956   if (!mFolder->isAutoExpire()) {
00957     canBeExpired = false;
00958   } else if (mFolder->getUnreadExpireUnits()==expireNever &&
00959          mFolder->getReadExpireUnits()==expireNever) {
00960     canBeExpired = false;
00961   }
00962 
00963   if (!canBeExpired) {
00964     str = i18n("This folder does not have any expiry options set");
00965     KMessageBox::information(this, str);
00966     return;
00967   }
00968   KConfig           *config = KMKernel::config();
00969   KConfigGroupSaver saver(config, "General");
00970 
00971   if (config->readBoolEntry("warn-before-expire", true)) {
00972     str = i18n("<qt>Are you sure you want to expire the folder <b>%1</b>?</qt>").arg(QStyleSheet::escape( mFolder->label() ));
00973     if (KMessageBox::warningContinueCancel(this, str, i18n("Expire Folder"),
00974                        i18n("&Expire"))
00975     != KMessageBox::Continue) return;
00976   }
00977 
00978   mFolder->expireOldMessages( true /*immediate*/);
00979 }
00980 
00981 //-----------------------------------------------------------------------------
00982 void KMMainWidget::slotEmptyFolder()
00983 {
00984   QString str;
00985 
00986   if (!mFolder) return;
00987   bool isTrash = kmkernel->folderIsTrash(mFolder);
00988 
00989   if (mConfirmEmpty)
00990   {
00991     QString title = (isTrash) ? i18n("Empty Trash") : i18n("Move to Trash");
00992     QString text = (isTrash) ?
00993       i18n("Are you sure you want to empty the trash folder?") :
00994       i18n("<qt>Are you sure you want to move all messages from "
00995            "folder <b>%1</b> to the trash?</qt>").arg( QStyleSheet::escape( mFolder->label() ) );
00996 
00997     if (KMessageBox::warningContinueCancel(this, text, title, KGuiItem( title, "edittrash"))
00998       != KMessageBox::Continue) return;
00999   }
01000   KCursorSaver busy(KBusyPtr::busy());
01001   slotMarkAll();
01002   if (isTrash) {
01003     /* Don't ask for confirmation again when deleting, the user has already
01004        confirmed. */
01005     slotDeleteMsg( false );
01006   }
01007   else
01008     slotTrashMsg();
01009 
01010   if (mMsgView) mMsgView->clearCache();
01011 
01012   if ( !isTrash )
01013     BroadcastStatus::instance()->setStatusMsg(i18n("Moved all messages to the trash"));
01014 
01015   updateMessageActions();
01016 }
01017 
01018 
01019 //-----------------------------------------------------------------------------
01020 void KMMainWidget::slotRemoveFolder()
01021 {
01022   QString str;
01023   QDir dir;
01024 
01025   if ( !mFolder ) return;
01026   if ( mFolder->isSystemFolder() ) return;
01027   if ( mFolder->isReadOnly() ) return;
01028 
01029   QString title;
01030   if ( mFolder->folderType() == KMFolderTypeSearch ) {
01031     title = i18n("Delete Search");
01032     str = i18n("<qt>Are you sure you want to delete the search <b>%1</b>?<br>"
01033                 "Any messages it shows will still be available in their original folder.</qt>")
01034            .arg( QStyleSheet::escape( mFolder->label() ) );
01035   } else {
01036     title = i18n("Delete Folder");
01037     if ( mFolder->count() == 0 ) {
01038       if ( !mFolder->child() || mFolder->child()->isEmpty() ) {
01039         str = i18n("<qt>Are you sure you want to delete the empty folder "
01040                    "<b>%1</b>?</qt>")
01041               .arg( QStyleSheet::escape( mFolder->label() ) );
01042       }
01043       else {
01044         str = i18n("<qt>Are you sure you want to delete the empty folder "
01045                    "<b>%1</b> and all its subfolders? Those subfolders might "
01046                    "not be empty and their contents will be discarded as well. "
01047                    "<p><b>Beware</b> that discarded messages are not saved "
01048                    "into your Trash folder and are permanently deleted.</qt>")
01049               .arg( QStyleSheet::escape( mFolder->label() ) );
01050       }
01051     } else {
01052       if ( !mFolder->child() || mFolder->child()->isEmpty() ) {
01053         str = i18n("<qt>Are you sure you want to delete the folder "
01054                    "<b>%1</b>, discarding its contents? "
01055                    "<p><b>Beware</b> that discarded messages are not saved "
01056                    "into your Trash folder and are permanently deleted.</qt>")
01057               .arg( QStyleSheet::escape( mFolder->label() ) );
01058       }
01059       else {
01060         str = i18n("<qt>Are you sure you want to delete the folder <b>%1</b> "
01061                    "and all its subfolders, discarding their contents? "
01062                    "<p><b>Beware</b> that discarded messages are not saved "
01063                    "into your Trash folder and are permanently deleted.</qt>")
01064             .arg( QStyleSheet::escape( mFolder->label() ) );
01065       }
01066     }
01067   }
01068 
01069   if (KMessageBox::warningContinueCancel(this, str, title,
01070                                          KGuiItem( i18n("&Delete"), "editdelete"))
01071       == KMessageBox::Continue)
01072   {
01073     if ( mFolder->hasAccounts() ) {
01074       // this folder has an account, so we need to change that to the inbox
01075       for ( AccountList::Iterator it (mFolder->acctList()->begin() ),
01076              end( mFolder->acctList()->end() ); it != end; ++it ) {
01077         (*it)->setFolder( kmkernel->inboxFolder() );
01078         KMessageBox::information(this,
01079             i18n("<qt>The folder you deleted was associated with the account "
01080               "<b>%1</b> which delivered mail into it. The folder the account "
01081               "delivers new mail into was reset to the main Inbox folder.</qt>").arg( (*it)->name()));
01082       }
01083     }
01084     if (mFolder->folderType() == KMFolderTypeImap)
01085       kmkernel->imapFolderMgr()->remove(mFolder);
01086     else if (mFolder->folderType() == KMFolderTypeCachedImap) {
01087       // Deleted by user -> tell the account (see KMFolderCachedImap::listDirectory2)
01088       KMFolderCachedImap* storage = static_cast<KMFolderCachedImap*>( mFolder->storage() );
01089       KMAcctCachedImap* acct = storage->account();
01090       if ( acct )
01091         acct->addDeletedFolder( mFolder );
01092 
01093       kmkernel->dimapFolderMgr()->remove(mFolder);
01094     }
01095     else if (mFolder->folderType() == KMFolderTypeSearch)
01096       kmkernel->searchFolderMgr()->remove(mFolder);
01097     else
01098       kmkernel->folderMgr()->remove(mFolder);
01099   }
01100 }
01101 
01102 //-----------------------------------------------------------------------------
01103 void KMMainWidget::slotMarkAllAsRead()
01104 {
01105   if (!mFolder)
01106     return;
01107   mFolder->markUnreadAsRead();
01108 }
01109 
01110 //-----------------------------------------------------------------------------
01111 void KMMainWidget::slotCompactFolder()
01112 {
01113   if (mFolder) {
01114     int idx = mHeaders->currentItemIndex();
01115     KCursorSaver busy(KBusyPtr::busy());
01116     mFolder->compact( KMFolder::CompactNow );
01117     // setCurrentItemByIndex will override the statusbar message, so save/restore it
01118     QString statusMsg = BroadcastStatus::instance()->statusMsg();
01119     mHeaders->setCurrentItemByIndex(idx);
01120     BroadcastStatus::instance()->setStatusMsg( statusMsg );
01121   }
01122 }
01123 
01124 
01125 //-----------------------------------------------------------------------------
01126 void KMMainWidget::slotRefreshFolder()
01127 {
01128   if (mFolder)
01129   {
01130     if ( mFolder->folderType() == KMFolderTypeImap || mFolder->folderType() == KMFolderTypeCachedImap ) {
01131       if ( !kmkernel->askToGoOnline() ) {
01132         return;
01133       }
01134     }
01135 
01136     if (mFolder->folderType() == KMFolderTypeImap)
01137     {
01138       KMFolderImap *imap = static_cast<KMFolderImap*>(mFolder->storage());
01139       imap->getAndCheckFolder();
01140     } else if ( mFolder->folderType() == KMFolderTypeCachedImap ) {
01141       KMFolderCachedImap* f = static_cast<KMFolderCachedImap*>( mFolder->storage() );
01142       f->account()->processNewMailSingleFolder( mFolder );
01143     }
01144   }
01145 }
01146 
01147 void KMMainWidget::slotTroubleshootFolder()
01148 {
01149   if (mFolder)
01150   {
01151     if ( mFolder->folderType() == KMFolderTypeCachedImap ) {
01152       KMFolderCachedImap* f = static_cast<KMFolderCachedImap*>( mFolder->storage() );
01153       f->slotTroubleshoot();
01154     }
01155   }
01156 }
01157 
01158 void KMMainWidget::slotInvalidateIMAPFolders() {
01159   if ( KMessageBox::warningContinueCancel( this,
01160           i18n("Are you sure you want to refresh the IMAP cache?\n"
01161            "This will remove all changes that you have done "
01162            "locally to your IMAP folders."),
01163       i18n("Refresh IMAP Cache"), i18n("&Refresh") ) == KMessageBox::Continue )
01164     kmkernel->acctMgr()->invalidateIMAPFolders();
01165 }
01166 
01167 //-----------------------------------------------------------------------------
01168 void KMMainWidget::slotExpireAll() {
01169   KConfig    *config = KMKernel::config();
01170   int        ret = 0;
01171 
01172   KConfigGroupSaver saver(config, "General");
01173 
01174   if (config->readBoolEntry("warn-before-expire", true)) {
01175     ret = KMessageBox::warningContinueCancel(KMainWindow::memberList->first(),
01176              i18n("Are you sure you want to expire all old messages?"),
01177              i18n("Expire Old Messages?"), i18n("Expire"));
01178     if (ret != KMessageBox::Continue) {
01179       return;
01180     }
01181   }
01182 
01183   kmkernel->expireAllFoldersNow();
01184 }
01185 
01186 //-----------------------------------------------------------------------------
01187 void KMMainWidget::slotCompactAll()
01188 {
01189   KCursorSaver busy(KBusyPtr::busy());
01190   kmkernel->compactAllFolders();
01191 }
01192 
01193 
01194 //-----------------------------------------------------------------------------
01195 void KMMainWidget::slotOverrideHtml()
01196 {
01197   if( mHtmlPref == mFolderHtmlPref ) {
01198     int result = KMessageBox::warningContinueCancel( this,
01199       // the warning text is taken from configuredialog.cpp:
01200       i18n( "Use of HTML in mail will make you more vulnerable to "
01201         "\"spam\" and may increase the likelihood that your system will be "
01202         "compromised by other present and anticipated security exploits." ),
01203       i18n( "Security Warning" ),
01204       i18n( "Use HTML" ),
01205       "OverrideHtmlWarning", false);
01206     if( result == KMessageBox::Cancel ) {
01207       mPreferHtmlAction->setChecked( false );
01208       return;
01209     }
01210   }
01211   mFolderHtmlPref = !mFolderHtmlPref;
01212   if (mMsgView) {
01213     mMsgView->setHtmlOverride(mFolderHtmlPref);
01214     mMsgView->update( true );
01215   }
01216 }
01217 
01218 //-----------------------------------------------------------------------------
01219 void KMMainWidget::slotOverrideHtmlLoadExt()
01220 {
01221   if( mHtmlLoadExtPref == mFolderHtmlLoadExtPref ) {
01222     int result = KMessageBox::warningContinueCancel( this,
01223       // the warning text is taken from configuredialog.cpp:
01224       i18n( "Loading external references in html mail will make you more vulnerable to "
01225         "\"spam\" and may increase the likelihood that your system will be "
01226         "compromised by other present and anticipated security exploits." ),
01227       i18n( "Security Warning" ),
01228       i18n( "Load External References" ),
01229       "OverrideHtmlLoadExtWarning", false);
01230     if( result == KMessageBox::Cancel ) {
01231       mPreferHtmlLoadExtAction->setChecked( false );
01232       return;
01233     }
01234   }
01235   mFolderHtmlLoadExtPref = !mFolderHtmlLoadExtPref;
01236   if (mMsgView) {
01237     mMsgView->setHtmlLoadExtOverride(mFolderHtmlLoadExtPref);
01238     mMsgView->update( true );
01239   }
01240 }
01241 
01242 //-----------------------------------------------------------------------------
01243 void KMMainWidget::slotOverrideThread()
01244 {
01245   mFolderThreadPref = !mFolderThreadPref;
01246   mHeaders->setNestedOverride(mFolderThreadPref);
01247   mThreadBySubjectAction->setEnabled(mThreadMessagesAction->isChecked());
01248 }
01249 
01250 //-----------------------------------------------------------------------------
01251 void KMMainWidget::slotToggleSubjectThreading()
01252 {
01253   mFolderThreadSubjPref = !mFolderThreadSubjPref;
01254   mHeaders->setSubjectThreading(mFolderThreadSubjPref);
01255 }
01256 
01257 //-----------------------------------------------------------------------------
01258 void KMMainWidget::slotToggleShowQuickSearch()
01259 {
01260   GlobalSettings::self()->setQuickSearchActive( !GlobalSettings::self()->quickSearchActive() );
01261   if ( GlobalSettings::self()->quickSearchActive() )
01262     mSearchToolBar->show();
01263   else {
01264     mQuickSearchLine->reset();
01265     mSearchToolBar->hide();
01266   }
01267 }
01268 
01269 //-----------------------------------------------------------------------------
01270 void KMMainWidget::slotMessageQueuedOrDrafted()
01271 {
01272   if (!kmkernel->folderIsDraftOrOutbox(mFolder))
01273       return;
01274   if (mMsgView)
01275     mMsgView->update(true);
01276 }
01277 
01278 
01279 //-----------------------------------------------------------------------------
01280 void KMMainWidget::slotForwardInlineMsg()
01281 {
01282   KMMessageList* selected = mHeaders->selectedMsgs();
01283   KMCommand *command = 0L;
01284   if(selected && !selected->isEmpty()) {
01285     command = new KMForwardInlineCommand( this, *selected,
01286                                           mFolder->identity() );
01287   } else {
01288     command = new KMForwardInlineCommand( this, mHeaders->currentMsg(),
01289                                           mFolder->identity() );
01290   }
01291 
01292   command->start();
01293 }
01294 
01295 
01296 //-----------------------------------------------------------------------------
01297 void KMMainWidget::slotForwardAttachedMsg()
01298 {
01299   KMMessageList* selected = mHeaders->selectedMsgs();
01300   KMCommand *command = 0L;
01301   if(selected && !selected->isEmpty()) {
01302     command = new KMForwardAttachedCommand( this, *selected, mFolder->identity() );
01303   } else {
01304     command = new KMForwardAttachedCommand( this, mHeaders->currentMsg(), mFolder->identity() );
01305   }
01306 
01307   command->start();
01308 }
01309 
01310 //-----------------------------------------------------------------------------
01311 void KMMainWidget::slotForwardDigestMsg()
01312 {
01313   KMMessageList* selected = mHeaders->selectedMsgs();
01314   KMCommand *command = 0L;
01315   if(selected && !selected->isEmpty()) {
01316     command = new KMForwardDigestCommand( this, *selected, mFolder->identity() );
01317   } else {
01318     command = new KMForwardDigestCommand( this, mHeaders->currentMsg(), mFolder->identity() );
01319   }
01320 
01321   command->start();
01322 }
01323 
01324 //-----------------------------------------------------------------------------
01325 void KMMainWidget::slotEditMsg()
01326 {
01327   KMCommand *command = new KMEditMsgCommand( this, mHeaders->currentMsg() );
01328   command->start();
01329 }
01330 
01331 //-----------------------------------------------------------------------------
01332 void KMMainWidget::slotResendMsg()
01333 {
01334   KMCommand *command = new KMResendMessageCommand( this, mHeaders->currentMsg() );
01335   command->start();
01336 }
01337 
01338 
01339 //-----------------------------------------------------------------------------
01340 void KMMainWidget::slotTrashMsg()
01341 {
01342   mHeaders->deleteMsg();
01343 }
01344 
01345 //-----------------------------------------------------------------------------
01346 void KMMainWidget::slotDeleteMsg( bool confirmDelete )
01347 {
01348   mHeaders->moveMsgToFolder( 0, confirmDelete );
01349 }
01350 
01351 //-----------------------------------------------------------------------------
01352 void KMMainWidget::slotTrashThread()
01353 {
01354   mHeaders->highlightCurrentThread();
01355   mHeaders->deleteMsg();
01356 }
01357 
01358 //-----------------------------------------------------------------------------
01359 void KMMainWidget::slotDeleteThread( bool confirmDelete )
01360 {
01361   mHeaders->highlightCurrentThread();
01362   mHeaders->moveMsgToFolder( 0, confirmDelete );
01363 }
01364 
01365 //-----------------------------------------------------------------------------
01366 void KMMainWidget::slotReplyToMsg()
01367 {
01368   QString text = mMsgView? mMsgView->copyText() : "";
01369   KMCommand *command = new KMReplyToCommand( this, mHeaders->currentMsg(), text );
01370   command->start();
01371 }
01372 
01373 
01374 //-----------------------------------------------------------------------------
01375 void KMMainWidget::slotReplyAuthorToMsg()
01376 {
01377   QString text = mMsgView? mMsgView->copyText() : "";
01378   KMCommand *command = new KMReplyAuthorCommand( this, mHeaders->currentMsg(), text );
01379   command->start();
01380 }
01381 
01382 
01383 //-----------------------------------------------------------------------------
01384 void KMMainWidget::slotReplyAllToMsg()
01385 {
01386   QString text = mMsgView? mMsgView->copyText() : "";
01387   KMCommand *command = new KMReplyToAllCommand( this, mHeaders->currentMsg(), text );
01388   command->start();
01389 }
01390 
01391 
01392 //-----------------------------------------------------------------------------
01393 void KMMainWidget::slotRedirectMsg()
01394 {
01395   KMCommand *command = new KMRedirectCommand( this, mHeaders->currentMsg() );
01396   command->start();
01397 }
01398 
01399 //-----------------------------------------------------------------------------
01400 void KMMainWidget::slotReplyListToMsg()
01401 {
01402 
01403   QString text = mMsgView? mMsgView->copyText() : "";
01404   KMCommand *command = new KMReplyListCommand( this, mHeaders->currentMsg(),
01405                            text );
01406   command->start();
01407 }
01408 
01409 //-----------------------------------------------------------------------------
01410 void KMMainWidget::slotNoQuoteReplyToMsg()
01411 {
01412   KMCommand *command = new KMNoQuoteReplyToCommand( this, mHeaders->currentMsg() );
01413   command->start();
01414 }
01415 
01416 //-----------------------------------------------------------------------------
01417 void KMMainWidget::slotSubjectFilter()
01418 {
01419   KMMessage *msg = mHeaders->currentMsg();
01420   if (!msg)
01421     return;
01422 
01423   KMCommand *command = new KMFilterCommand( "Subject", msg->subject() );
01424   command->start();
01425 }
01426 
01427 //-----------------------------------------------------------------------------
01428 void KMMainWidget::slotMailingListFilter()
01429 {
01430   KMMessage *msg = mHeaders->currentMsg();
01431   if (!msg)
01432     return;
01433 
01434   KMCommand *command = new KMMailingListFilterCommand( this, msg );
01435   command->start();
01436 }
01437 
01438 //-----------------------------------------------------------------------------
01439 void KMMainWidget::slotFromFilter()
01440 {
01441   KMMessage *msg = mHeaders->currentMsg();
01442   if (!msg)
01443     return;
01444 
01445   AddrSpecList al = msg->extractAddrSpecs( "From" );
01446   KMCommand *command;
01447   if ( al.empty() )
01448     command = new KMFilterCommand( "From",  msg->from() );
01449   else
01450     command = new KMFilterCommand( "From",  al.front().asString() );
01451   command->start();
01452 }
01453 
01454 //-----------------------------------------------------------------------------
01455 void KMMainWidget::slotToFilter()
01456 {
01457   KMMessage *msg = mHeaders->currentMsg();
01458   if (!msg)
01459     return;
01460 
01461   KMCommand *command = new KMFilterCommand( "To",  msg->to() );
01462   command->start();
01463 }
01464 
01465 //-----------------------------------------------------------------------------
01466 void KMMainWidget::updateListFilterAction()
01467 {
01468   //Proxy the mListFilterAction to update the action text
01469   QCString name;
01470   QString value;
01471   QString lname = MailingList::name( mHeaders->currentMsg(), name, value );
01472   mListFilterAction->setText( i18n("Filter on Mailing-List...") );
01473   if ( lname.isNull() )
01474     mListFilterAction->setEnabled( false );
01475   else {
01476     mListFilterAction->setEnabled( true );
01477     mListFilterAction->setText( i18n( "Filter on Mailing-List %1..." ).arg( lname ) );
01478   }
01479 }
01480 
01481 
01482 //-----------------------------------------------------------------------------
01483 void KMMainWidget::slotUndo()
01484 {
01485     mHeaders->undo();
01486     updateMessageActions();
01487 }
01488 
01489 //-----------------------------------------------------------------------------
01490 void KMMainWidget::slotToggleUnread()
01491 {
01492   mFolderTree->toggleColumn(KMFolderTree::unread);
01493 }
01494 
01495 //-----------------------------------------------------------------------------
01496 void KMMainWidget::slotToggleTotalColumn()
01497 {
01498   mFolderTree->toggleColumn(KMFolderTree::total, true);
01499 }
01500 
01501 //-----------------------------------------------------------------------------
01502 void KMMainWidget::slotJumpToFolder()
01503 {
01504   KMail::KMFolderSelDlg dlg( this, i18n("Jump to Folder"), true );
01505   KMFolder* dest;
01506 
01507   if (!dlg.exec()) return;
01508   if (!(dest = dlg.folder())) return;
01509 
01510   slotSelectFolder( dest );
01511 }
01512 
01513 //-----------------------------------------------------------------------------
01514 void KMMainWidget::slotMoveMsg()
01515 {
01516   KMail::KMFolderSelDlg dlg( this, i18n("Move Message to Folder"), true );
01517   KMFolder* dest;
01518 
01519   if (!dlg.exec()) return;
01520   if (!(dest = dlg.folder())) return;
01521 
01522   mHeaders->moveMsgToFolder(dest);
01523 }
01524 
01525 //-----------------------------------------------------------------------------
01526 void KMMainWidget::slotMoveMsgToFolder( KMFolder *dest)
01527 {
01528   mHeaders->moveMsgToFolder(dest);
01529 }
01530 
01531 //-----------------------------------------------------------------------------
01532 void KMMainWidget::slotCopyMsgToFolder( KMFolder *dest)
01533 {
01534   mHeaders->copyMsgToFolder(dest);
01535 }
01536 
01537 //-----------------------------------------------------------------------------
01538 void KMMainWidget::slotApplyFilters()
01539 {
01540   mHeaders->applyFiltersOnMsg();
01541 }
01542 
01543 //-----------------------------------------------------------------------------
01544 void KMMainWidget::slotEditVacation()
01545 {
01546   if ( !kmkernel->askToGoOnline() ) {
01547     return;
01548   }
01549 
01550   if ( mVacation )
01551     return;
01552 
01553   mVacation = new Vacation( this );
01554   if ( mVacation->isUsable() ) {
01555     connect( mVacation, SIGNAL(result(bool)), mVacation, SLOT(deleteLater()) );
01556   } else {
01557     QString msg = i18n("KMail's Out of Office Reply functionality relies on "
01558                       "server-side filtering. You have not yet configured an "
01559                       "IMAP server for this.\n"
01560                       "You can do this on the \"Filtering\" tab of the IMAP "
01561                       "account configuration.");
01562     KMessageBox::sorry( this, msg, i18n("No Server-Side Filtering Configured") );
01563 
01564     delete mVacation; // QGuardedPtr sets itself to 0!
01565   }
01566 }
01567 
01568 //-----------------------------------------------------------------------------
01569 void KMMainWidget::slotDebugSieve()
01570 {
01571 #if !defined(NDEBUG)
01572   if ( mSieveDebugDialog )
01573     return;
01574 
01575   mSieveDebugDialog = new SieveDebugDialog( this );
01576   mSieveDebugDialog->exec();
01577   delete mSieveDebugDialog;
01578 #endif
01579 }
01580 
01581 //-----------------------------------------------------------------------------
01582 void KMMainWidget::slotStartCertManager()
01583 {
01584   KProcess certManagerProc; // save to create on the heap, since
01585   // there is no parent
01586   certManagerProc << "kleopatra";
01587 
01588   if( !certManagerProc.start( KProcess::DontCare ) )
01589     KMessageBox::error( this, i18n( "Could not start certificate manager; "
01590                                     "please check your installation." ),
01591                                     i18n( "KMail Error" ) );
01592   else
01593     kdDebug(5006) << "\nslotStartCertManager(): certificate manager started.\n" << endl;
01594   // process continues to run even after the KProcess object goes
01595   // out of scope here, since it is started in DontCare run mode.
01596 
01597 }
01598 
01599 //-----------------------------------------------------------------------------
01600 void KMMainWidget::slotStartWatchGnuPG()
01601 {
01602   KProcess certManagerProc;
01603   certManagerProc << "kwatchgnupg";
01604 
01605   if( !certManagerProc.start( KProcess::DontCare ) )
01606     KMessageBox::error( this, i18n( "Could not start GnuPG LogViewer (kwatchgnupg); "
01607                                     "please check your installation." ),
01608                                     i18n( "KMail Error" ) );
01609 }
01610 
01611 //-----------------------------------------------------------------------------
01612 void KMMainWidget::slotCopyMsg()
01613 {
01614   KMail::KMFolderSelDlg dlg( this, i18n("Copy Message to Folder"), true );
01615   KMFolder* dest;
01616 
01617   if (!dlg.exec()) return;
01618   if (!(dest = dlg.folder())) return;
01619 
01620   mHeaders->copyMsgToFolder(dest);
01621 }
01622 
01623 //-----------------------------------------------------------------------------
01624 void KMMainWidget::slotPrintMsg()
01625 {
01626   bool htmlOverride = mMsgView ? mMsgView->htmlOverride() : false;
01627   bool htmlLoadExtOverride = mMsgView ? mMsgView->htmlLoadExtOverride() : false;
01628   KConfigGroup reader( KMKernel::config(), "Reader" );
01629   bool useFixedFont = mMsgView ? mMsgView->isFixedFont()
01630                                : reader.readBoolEntry( "useFixedFont", false );
01631   KMCommand *command =
01632     new KMPrintCommand( this, mHeaders->currentMsg(),
01633                         htmlOverride, htmlLoadExtOverride,
01634                         useFixedFont, overrideEncoding() );
01635   command->start();
01636 }
01637 
01638 //-----------------------------------------------------------------------------
01639 void KMMainWidget::slotConfigChanged()
01640 {
01641   readConfig();
01642 }
01643 
01644 //-----------------------------------------------------------------------------
01645 void KMMainWidget::slotSaveMsg()
01646 {
01647   KMMessage *msg = mHeaders->currentMsg();
01648   if (!msg)
01649     return;
01650   KMSaveMsgCommand *saveCommand = new KMSaveMsgCommand( this,
01651     *mHeaders->selectedMsgs() );
01652 
01653   if (saveCommand->url().isEmpty())
01654     delete saveCommand;
01655   else
01656     saveCommand->start();
01657 }
01658 
01659 //-----------------------------------------------------------------------------
01660 void KMMainWidget::slotOpenMsg()
01661 {
01662   KMOpenMsgCommand *openCommand = new KMOpenMsgCommand( this, 0, overrideEncoding() );
01663 
01664   openCommand->start();
01665 }
01666 
01667 //-----------------------------------------------------------------------------
01668 void KMMainWidget::slotSaveAttachments()
01669 {
01670   KMMessage *msg = mHeaders->currentMsg();
01671   if (!msg)
01672     return;
01673   KMSaveAttachmentsCommand *saveCommand = new KMSaveAttachmentsCommand( this,
01674                                                                         *mHeaders->selectedMsgs() );
01675   saveCommand->start();
01676 }
01677 
01678 void KMMainWidget::slotOnlineStatus()
01679 {
01680   // KMKernel will emit a signal when we toggle the network state that is caught by
01681   // KMMainWidget::slotUpdateOnlineStatus to update our GUI
01682   if ( GlobalSettings::self()->networkState() == GlobalSettings::EnumNetworkState::Online ) {
01683     // if online; then toggle and set it offline.
01684     kmkernel->stopNetworkJobs();
01685   } else {
01686     kmkernel->resumeNetworkJobs();
01687   }
01688 }
01689 
01690 void KMMainWidget::slotUpdateOnlineStatus( GlobalSettings::EnumNetworkState::type )
01691 {
01692   if ( GlobalSettings::self()->networkState() == GlobalSettings::EnumNetworkState::Online )
01693     actionCollection()->action( "online_status" )->setText( i18n("Work Offline") );
01694   else
01695     actionCollection()->action( "online_status" )->setText( i18n("Work Online") );
01696 }
01697 
01698 
01699 //-----------------------------------------------------------------------------
01700 void KMMainWidget::slotSendQueued()
01701 {
01702   if ( !kmkernel->askToGoOnline() ) {
01703     return;
01704   }
01705 
01706   kmkernel->msgSender()->sendQueued();
01707 }
01708 
01709 //-----------------------------------------------------------------------------
01710 void KMMainWidget::slotSendQueuedVia( int item )
01711 {
01712   if ( !kmkernel->askToGoOnline() ) {
01713     return;
01714   }
01715 
01716   QStringList availTransports= KMail::TransportManager::transportNames();
01717   QString customTransport = availTransports[ item ];
01718 
01719   kmkernel->msgSender()->sendQueued( customTransport );
01720 }
01721 
01722 //-----------------------------------------------------------------------------
01723 void KMMainWidget::slotViewChange()
01724 {
01725   if(mBodyPartsMenu->isItemChecked(mBodyPartsMenu->idAt(0)))
01726   {
01727     mBodyPartsMenu->setItemChecked(mBodyPartsMenu->idAt(0),FALSE);
01728     mBodyPartsMenu->setItemChecked(mBodyPartsMenu->idAt(1),TRUE);
01729   }
01730   else if(mBodyPartsMenu->isItemChecked(mBodyPartsMenu->idAt(1)))
01731   {
01732     mBodyPartsMenu->setItemChecked(mBodyPartsMenu->idAt(1),FALSE);
01733     mBodyPartsMenu->setItemChecked(mBodyPartsMenu->idAt(0),TRUE);
01734   }
01735 
01736   //mMsgView->setInline(!mMsgView->isInline());
01737 }
01738 
01739 
01740 //-----------------------------------------------------------------------------
01741 void KMMainWidget::folderSelectedUnread( KMFolder* aFolder )
01742 {
01743   folderSelected( aFolder, true );
01744   slotChangeCaption( mFolderTree->currentItem() );
01745 }
01746 
01747 //-----------------------------------------------------------------------------
01748 void KMMainWidget::folderSelected()
01749 {
01750   folderSelected( mFolder );
01751   updateFolderMenu();
01752   // opened() before the getAndCheckFolder() in folderSelected
01753   if ( mFolder && mFolder->folderType() == KMFolderTypeImap )
01754     mFolder->close();
01755 }
01756 
01757 //-----------------------------------------------------------------------------
01758 void KMMainWidget::folderSelected( KMFolder* aFolder, bool forceJumpToUnread )
01759 {
01760   KCursorSaver busy(KBusyPtr::busy());
01761 
01762   if (mMsgView)
01763     mMsgView->clear(true);
01764 
01765   if ( mFolder && mFolder->folderType() == KMFolderTypeImap && !mFolder->noContent() )
01766   {
01767     KMFolderImap *imap = static_cast<KMFolderImap*>(mFolder->storage());
01768     if ( mFolder->needsCompacting() && imap->autoExpunge() )
01769       imap->expungeFolder(imap, TRUE);
01770   }
01771 
01772   // Re-enable the msg list and quicksearch if we're showing a splash
01773   // screen. This is true either if there's no active folder, or if we
01774   // have a timer that is no longer active (i.e. it has already fired)
01775   // To make the if() a bit more complicated, we suppress the hiding
01776   // when the new folder is also an IMAP folder, because that's an
01777   // async operation and we don't want flicker if it results in just
01778   // a new splash.
01779   bool newFolder = ( mFolder != aFolder );
01780   bool isNewImapFolder = aFolder && aFolder->folderType() == KMFolderTypeImap && newFolder;
01781   if( !mFolder
01782       || ( !isNewImapFolder && mShowBusySplashTimer && !mShowBusySplashTimer->isActive() )
01783       || ( newFolder && mShowingOfflineScreen && !( isNewImapFolder && kmkernel->isOffline() ) ) ) {
01784     if ( mMsgView ) {
01785       mMsgView->enableMsgDisplay();
01786       mMsgView->clear( true );
01787     }
01788     if( mSearchAndHeaders && mHeaders )
01789       mSearchAndHeaders->show();
01790     mShowingOfflineScreen = false;
01791   }
01792 
01793   // Delete any pending timer, if needed it will be recreated below
01794   delete mShowBusySplashTimer;
01795   mShowBusySplashTimer = 0;
01796 
01797   if ( newFolder )
01798     writeFolderConfig();
01799   if ( mFolder ) {
01800     disconnect( mFolder, SIGNAL( changed() ),
01801            this, SLOT( updateMarkAsReadAction() ) );
01802     disconnect( mFolder, SIGNAL( msgHeaderChanged( KMFolder*, int ) ),
01803            this, SLOT( updateMarkAsReadAction() ) );
01804     disconnect( mFolder, SIGNAL( msgAdded( int ) ),
01805            this, SLOT( updateMarkAsReadAction() ) );
01806     disconnect( mFolder, SIGNAL( msgRemoved( KMFolder * ) ),
01807            this, SLOT( updateMarkAsReadAction() ) );
01808   }
01809 
01810   mFolder = aFolder;
01811 
01812   if ( aFolder && aFolder->folderType() == KMFolderTypeImap )
01813   {
01814     if ( kmkernel->isOffline() ) {
01815       showOfflinePage();
01816       return;
01817     }
01818     KMFolderImap *imap = static_cast<KMFolderImap*>(aFolder->storage());
01819     if ( newFolder && !mFolder->noContent() )
01820     {
01821       imap->open(); // will be closed in the folderSelected slot
01822       // first get new headers before we select the folder
01823       imap->setSelected( true );
01824       connect( imap, SIGNAL( folderComplete( KMFolderImap*, bool ) ),
01825           this, SLOT( folderSelected() ) );
01826       imap->getAndCheckFolder();
01827       mHeaders->setFolder( 0 );
01828       updateFolderMenu();
01829       mForceJumpToUnread = forceJumpToUnread;
01830 
01831       // Set a timer to show a splash screen if fetching folder contents
01832       // takes more than the amount of seconds configured in the kmailrc (default 1000 msec)
01833       mShowBusySplashTimer = new QTimer( this );
01834       connect( mShowBusySplashTimer, SIGNAL( timeout() ), this, SLOT( slotShowBusySplash() ) );
01835       mShowBusySplashTimer->start( GlobalSettings::self()->folderLoadingTimeout(), true );
01836       return;
01837     } else {
01838       // the folder is complete now - so go ahead
01839       disconnect( imap, SIGNAL( folderComplete( KMFolderImap*, bool ) ),
01840           this, SLOT( folderSelected() ) );
01841       forceJumpToUnread = mForceJumpToUnread;
01842     }
01843   }
01844 
01845   if ( mFolder ) { // == 0 -> pointing to toplevel ("Welcome to KMail") folder
01846     connect( mFolder, SIGNAL( changed() ),
01847            this, SLOT( updateMarkAsReadAction() ) );
01848     connect( mFolder, SIGNAL( msgHeaderChanged( KMFolder*, int ) ),
01849            this, SLOT( updateMarkAsReadAction() ) );
01850     connect( mFolder, SIGNAL( msgAdded( int ) ),
01851            this, SLOT( updateMarkAsReadAction() ) );
01852     connect( mFolder, SIGNAL( msgRemoved(KMFolder *) ),
01853            this, SLOT( updateMarkAsReadAction() ) );
01854   }
01855   readFolderConfig();
01856   if (mMsgView)
01857   {
01858     mMsgView->setHtmlOverride(mFolderHtmlPref);
01859     mMsgView->setHtmlLoadExtOverride(mFolderHtmlLoadExtPref);
01860   }
01861   mHeaders->setFolder( mFolder, forceJumpToUnread );
01862   updateMessageActions();
01863   updateFolderMenu();
01864   if (!aFolder)
01865     slotIntro();
01866 }
01867 
01868 //-----------------------------------------------------------------------------
01869 void KMMainWidget::slotShowBusySplash()
01870 {
01871   if ( mReaderWindowActive )
01872   {
01873     mMsgView->displayBusyPage();
01874     // hide widgets that are in the way:
01875     if ( mSearchAndHeaders && mHeaders && mLongFolderList )
01876       mSearchAndHeaders->hide();
01877   }
01878 }
01879 
01880 void KMMainWidget::showOfflinePage()
01881 {
01882   if ( !mReaderWindowActive ) return;
01883   mShowingOfflineScreen = true;
01884 
01885   mMsgView->displayOfflinePage();
01886   // hide widgets that are in the way:
01887   if ( mSearchAndHeaders && mHeaders && mLongFolderList )
01888     mSearchAndHeaders->hide();
01889 }
01890 
01891 //-----------------------------------------------------------------------------
01892 void KMMainWidget::slotMsgSelected(KMMessage *msg)
01893 {
01894   if ( msg && msg->parent() && !msg->isComplete() )
01895   {
01896     if ( msg->transferInProgress() )
01897       return;
01898     mMsgView->clear();
01899     mMsgView->setWaitingForSerNum( msg->getMsgSerNum() );
01900 
01901     if ( mJob ) {
01902        disconnect( mJob, 0, mMsgView, 0 );
01903        delete mJob;
01904     }
01905     mJob = msg->parent()->createJob( msg, FolderJob::tGetMessage, 0,
01906           "STRUCTURE", mMsgView->attachmentStrategy() );
01907     connect(mJob, SIGNAL(messageRetrieved(KMMessage*)),
01908             mMsgView, SLOT(slotMessageArrived(KMMessage*)));
01909     mJob->start();
01910   } else {
01911     mMsgView->setMsg(msg);
01912   }
01913   // reset HTML override to the folder setting
01914   mMsgView->setHtmlOverride(mFolderHtmlPref);
01915   mMsgView->setHtmlLoadExtOverride(mFolderHtmlLoadExtPref);
01916 }
01917 
01918 //-----------------------------------------------------------------------------
01919 void KMMainWidget::slotMsgChanged()
01920 {
01921   mHeaders->msgChanged();
01922 }
01923 
01924 //-----------------------------------------------------------------------------
01925 void KMMainWidget::slotSelectFolder(KMFolder* folder)
01926 {
01927   QListViewItem* item = mFolderTree->indexOfFolder(folder);
01928   if ( item ) {
01929     mFolderTree->ensureItemVisible( item );
01930     mFolderTree->doFolderSelected( item );
01931   }
01932 }
01933 
01934 //-----------------------------------------------------------------------------
01935 void KMMainWidget::slotSelectMessage(KMMessage* msg)
01936 {
01937   int idx = mFolder->find(msg);
01938   if (idx != -1) {
01939     mHeaders->setCurrentMsg(idx);
01940     if (mMsgView)
01941       mMsgView->setMsg(msg);
01942   }
01943 }
01944 
01945 //-----------------------------------------------------------------------------
01946 void KMMainWidget::slotReplaceMsgByUnencryptedVersion()
01947 {
01948   kdDebug(5006) << "KMMainWidget::slotReplaceMsgByUnencryptedVersion()" << endl;
01949   KMMessage* oldMsg = mHeaders->currentMsg();
01950   if( oldMsg ) {
01951     kdDebug(5006) << "KMMainWidget  -  old message found" << endl;
01952     if( oldMsg->hasUnencryptedMsg() ) {
01953       kdDebug(5006) << "KMMainWidget  -  extra unencrypted message found" << endl;
01954       KMMessage* newMsg = oldMsg->unencryptedMsg();
01955       // adjust the message id
01956       {
01957         QString msgId( oldMsg->msgId() );
01958         QString prefix("DecryptedMsg.");
01959         int oldIdx = msgId.find(prefix, 0, false);
01960         if( -1 == oldIdx ) {
01961           int leftAngle = msgId.findRev( '<' );
01962           msgId = msgId.insert( (-1 == leftAngle) ? 0 : ++leftAngle, prefix );
01963         }
01964         else {
01965           // toggle between "DecryptedMsg." and "DeCryptedMsg."
01966           // to avoid same message id
01967           QCharRef c = msgId[ oldIdx+2 ];
01968           if( 'C' == c )
01969             c = 'c';
01970           else
01971             c = 'C';
01972         }
01973         newMsg->setMsgId( msgId );
01974         mMsgView->setIdOfLastViewedMessage( msgId );
01975       }
01976       // insert the unencrypted message
01977       kdDebug(5006) << "KMMainWidget  -  adding unencrypted message to folder" << endl;
01978       mFolder->addMsg( newMsg );
01979       /* Figure out its index in the folder for selecting. This must be count()-1,
01980        * since we append. Be safe and do find, though, just in case. */
01981       int newMsgIdx = mFolder->find( newMsg );
01982       Q_ASSERT( newMsgIdx != -1 );
01983       /* we need this unget, to have the message displayed correctly initially */
01984       mFolder->unGetMsg( newMsgIdx );
01985       int idx = mFolder->find( oldMsg );
01986       Q_ASSERT( idx != -1 );
01987       /* only select here, so the old one is not un-Gotten before, which would
01988        * render the pointer we hold invalid so that find would fail */
01989       mHeaders->setCurrentItemByIndex( newMsgIdx );
01990       // remove the old one
01991       if ( idx != -1 ) {
01992         kdDebug(5006) << "KMMainWidget  -  deleting encrypted message" << endl;
01993         mFolder->take( idx );
01994       }
01995 
01996       kdDebug(5006) << "KMMainWidget  -  updating message actions" << endl;
01997       updateMessageActions();
01998 
01999       kdDebug(5006) << "KMMainWidget  -  done." << endl;
02000     } else
02001       kdDebug(5006) << "KMMainWidget  -  NO EXTRA UNENCRYPTED MESSAGE FOUND" << endl;
02002   } else
02003     kdDebug(5006) << "KMMainWidget  -  PANIC: NO OLD MESSAGE FOUND" << endl;
02004 }
02005 
02006 //-----------------------------------------------------------------------------
02007 void KMMainWidget::slotSetMsgStatusNew()
02008 {
02009   mHeaders->setMsgStatus(KMMsgStatusNew);
02010 }
02011 
02012 //-----------------------------------------------------------------------------
02013 void KMMainWidget::slotSetMsgStatusUnread()
02014 {
02015   mHeaders->setMsgStatus(KMMsgStatusUnread);
02016 }
02017 
02018 //-----------------------------------------------------------------------------
02019 void KMMainWidget::slotSetMsgStatusRead()
02020 {
02021   mHeaders->setMsgStatus(KMMsgStatusRead);
02022 }
02023 
02024 //-----------------------------------------------------------------------------
02025 void KMMainWidget::slotSetMsgStatusFlag()
02026 {
02027   mHeaders->setMsgStatus(KMMsgStatusFlag, true);
02028 }
02029 
02030 //-----------------------------------------------------------------------------
02031 void KMMainWidget::slotSetMsgStatusTodo()
02032 {
02033   mHeaders->setMsgStatus(KMMsgStatusTodo, true);
02034 }
02035 
02036 //-----------------------------------------------------------------------------
02037 void KMMainWidget::slotSetMsgStatusSent()
02038 {
02039   mHeaders->setMsgStatus(KMMsgStatusSent, true);
02040 }
02041 
02042 //-----------------------------------------------------------------------------
02043 void KMMainWidget::slotSetThreadStatusNew()
02044 {
02045   mHeaders->setThreadStatus(KMMsgStatusNew);
02046 }
02047 
02048 //-----------------------------------------------------------------------------
02049 void KMMainWidget::slotSetThreadStatusUnread()
02050 {
02051   mHeaders->setThreadStatus(KMMsgStatusUnread);
02052 }
02053 
02054 //-----------------------------------------------------------------------------
02055 void KMMainWidget::slotSetThreadStatusFlag()
02056 {
02057   mHeaders->setThreadStatus(KMMsgStatusFlag, true);
02058 }
02059 
02060 //-----------------------------------------------------------------------------
02061 void KMMainWidget::slotSetThreadStatusRead()
02062 {
02063   mHeaders->setThreadStatus(KMMsgStatusRead);
02064 }
02065 
02066 //-----------------------------------------------------------------------------
02067 void KMMainWidget::slotSetThreadStatusTodo()
02068 {
02069   mHeaders->setThreadStatus(KMMsgStatusTodo, true);
02070 }
02071 
02072 //-----------------------------------------------------------------------------
02073 void KMMainWidget::slotSetThreadStatusWatched()
02074 {
02075   mHeaders->setThreadStatus(KMMsgStatusWatched, true);
02076   if (mWatchThreadAction->isChecked()) {
02077     mIgnoreThreadAction->setChecked(false);
02078   }
02079 }
02080 
02081 //-----------------------------------------------------------------------------
02082 void KMMainWidget::slotSetThreadStatusIgnored()
02083 {
02084   mHeaders->setThreadStatus(KMMsgStatusIgnored, true);
02085   if (mIgnoreThreadAction->isChecked()) {
02086     mWatchThreadAction->setChecked(false);
02087   }
02088 }
02089 
02090 //-----------------------------------------------------------------------------
02091 void KMMainWidget::slotNextMessage()       { mHeaders->nextMessage(); }
02092 void KMMainWidget::slotNextUnreadMessage()
02093 {
02094   if ( !mHeaders->nextUnreadMessage() )
02095     if ( GlobalSettings::self()->loopOnGotoUnread() == GlobalSettings::EnumLoopOnGotoUnread::LoopInAllFolders )
02096       mFolderTree->nextUnreadFolder(true);
02097 }
02098 void KMMainWidget::slotNextImportantMessage() {
02099   //mHeaders->nextImportantMessage();
02100 }
02101 void KMMainWidget::slotPrevMessage()       { mHeaders->prevMessage(); }
02102 void KMMainWidget::slotPrevUnreadMessage()
02103 {
02104   if ( !mHeaders->prevUnreadMessage() )
02105     if ( GlobalSettings::self()->loopOnGotoUnread() == GlobalSettings::EnumLoopOnGotoUnread::LoopInAllFolders )
02106       mFolderTree->prevUnreadFolder();
02107 }
02108 void KMMainWidget::slotPrevImportantMessage() {
02109   //mHeaders->prevImportantMessage();
02110 }
02111 
02112 void KMMainWidget::slotDisplayCurrentMessage()
02113 {
02114   if ( mHeaders->currentMsg() )
02115     slotMsgActivated( mHeaders->currentMsg() );
02116 }
02117 
02118 //-----------------------------------------------------------------------------
02119 //called from headers. Message must not be deleted on close
02120 void KMMainWidget::slotMsgActivated(KMMessage *msg)
02121 {
02122   if ( !msg ) return;
02123   if (msg->parent() && !msg->isComplete())
02124   {
02125     FolderJob *job = msg->parent()->createJob(msg);
02126     connect(job, SIGNAL(messageRetrieved(KMMessage*)),
02127             SLOT(slotMsgActivated(KMMessage*)));
02128     job->start();
02129     return;
02130   }
02131 
02132   if (kmkernel->folderIsDraftOrOutbox(mFolder))
02133   {
02134     slotEditMsg();
02135     return;
02136   }
02137 
02138   assert( msg != 0 );
02139   KMReaderMainWin *win = new KMReaderMainWin( mFolderHtmlPref, mFolderHtmlLoadExtPref );
02140   KConfigGroup reader( KMKernel::config(), "Reader" );
02141   bool useFixedFont = mMsgView ? mMsgView->isFixedFont()
02142                                : reader.readBoolEntry( "useFixedFont", false );
02143   win->setUseFixedFont( useFixedFont );
02144   KMMessage *newMessage = new KMMessage(*msg);
02145   newMessage->setParent( msg->parent() );
02146   newMessage->setMsgSerNum( msg->getMsgSerNum() );
02147   newMessage->setReadyToShow( true );
02148   win->showMsg( overrideEncoding(), newMessage );
02149   win->show();
02150 }
02151 
02152 //-----------------------------------------------------------------------------
02153 void KMMainWidget::slotMarkAll()
02154 {
02155   mHeaders->selectAll( TRUE );
02156 }
02157 
02158 //-----------------------------------------------------------------------------
02159 void KMMainWidget::slotMsgPopup(KMMessage&, const KURL &aUrl, const QPoint& aPoint)
02160 {
02161   KPopupMenu * menu = new KPopupMenu;
02162   updateMessageMenu();
02163   mUrlCurrent = aUrl;
02164 
02165   bool urlMenuAdded = false;
02166 
02167   if (!aUrl.isEmpty())
02168   {
02169     if (aUrl.protocol() == "mailto")
02170     {
02171       // popup on a mailto URL
02172       mMsgView->mailToComposeAction()->plug( menu );
02173       mMsgView->mailToReplyAction()->plug( menu );
02174       mMsgView->mailToForwardAction()->plug( menu );
02175 
02176       menu->insertSeparator();
02177       mMsgView->addAddrBookAction()->plug( menu );
02178       mMsgView->openAddrBookAction()->plug( menu );
02179       mMsgView->copyURLAction()->plug( menu );
02180       mMsgView->startImChatAction()->plug( menu );
02181       // only enable if our KIMProxy is functional
02182       mMsgView->startImChatAction()->setEnabled( kmkernel->imProxy()->initialize() );
02183 
02184     } else {
02185       // popup on a not-mailto URL
02186       mMsgView->urlOpenAction()->plug( menu );
02187       mMsgView->addBookmarksAction()->plug( menu );
02188       mMsgView->urlSaveAsAction()->plug( menu );
02189       mMsgView->copyURLAction()->plug( menu );
02190     }
02191     if ( aUrl.protocol() == "im" )
02192     {
02193       // popup on an IM address
02194       // no need to check the KIMProxy is initialized, as these protocols will
02195       // only be present if it is.
02196       mMsgView->startImChatAction()->plug( menu );
02197     }
02198 
02199     urlMenuAdded=true;
02200     kdDebug( 0 ) << k_funcinfo << " URL is: " << aUrl << endl;
02201   }
02202 
02203 
02204   if(mMsgView && !mMsgView->copyText().isEmpty()) {
02205     if ( urlMenuAdded )
02206       menu->insertSeparator();
02207     mReplyActionMenu->plug(menu);
02208     menu->insertSeparator();
02209 
02210     mMsgView->copyAction()->plug( menu );
02211     mMsgView->selectAllAction()->plug( menu );
02212   } else  if ( !urlMenuAdded )
02213   {
02214     // popup somewhere else (i.e., not a URL) on the message
02215 
02216     if (!mHeaders->currentMsg()) // no messages
02217     {
02218       delete menu;
02219       return;
02220     }
02221 
02222     if ( mFolder->isDrafts() || mFolder->isOutbox() ) {
02223       mEditAction->plug(menu);
02224     }
02225     else {
02226       if( !mFolder->isSent() )
02227         mReplyActionMenu->plug(menu);
02228       mForwardActionMenu->plug(menu);
02229     }
02230     menu->insertSeparator();
02231 
02232     mCopyActionMenu->plug( menu );
02233     mMoveActionMenu->plug( menu );
02234 
02235     menu->insertSeparator();
02236 
02237     mStatusMenu->plug( menu );
02238     menu->insertSeparator();
02239 
02240     viewSourceAction()->plug(menu);
02241     if(mMsgView) {
02242       mMsgView->toggleFixFontAction()->plug(menu);
02243     }
02244     menu->insertSeparator();
02245     mPrintAction->plug( menu );
02246     mSaveAsAction->plug( menu );
02247     mSaveAttachmentsAction->plug( menu );
02248 
02249     menu->insertSeparator();
02250     if( mFolder->isTrash() )
02251       mDeleteAction->plug( menu );
02252     else
02253       mTrashAction->plug( menu );
02254   }
02255   KAcceleratorManager::manage(menu);
02256   menu->exec(aPoint, 0);
02257   delete menu;
02258 }
02259 
02260 //-----------------------------------------------------------------------------
02261 void KMMainWidget::getAccountMenu()
02262 {
02263   QStringList actList;
02264 
02265   mActMenu->clear();
02266   actList = kmkernel->acctMgr()->getAccounts();
02267   QStringList::Iterator it;
02268   int id = 0;
02269   for(it = actList.begin(); it != actList.end() ; ++it, id++)
02270     mActMenu->insertItem((*it).replace("&", "&&"), id);
02271 }
02272 
02273 //-----------------------------------------------------------------------------
02274 void KMMainWidget::getTransportMenu()
02275 {
02276   QStringList availTransports;
02277 
02278   mSendMenu->clear();
02279   availTransports = KMail::TransportManager::transportNames();
02280   QStringList::Iterator it;
02281   int id = 0;
02282   for(it = availTransports.begin(); it != availTransports.end() ; ++it, id++)
02283     mSendMenu->insertItem((*it).replace("&", "&&"), id);
02284 }
02285 
02286 //-----------------------------------------------------------------------------
02287 void KMMainWidget::setupActions()
02288 {
02289   //----- File Menu
02290   mSaveAsAction = new KAction( i18n("Save &As..."), "filesave",
02291     KStdAccel::shortcut(KStdAccel::Save),
02292     this, SLOT(slotSaveMsg()), actionCollection(), "file_save_as" );
02293 
02294   mOpenAction = KStdAction::open( this, SLOT( slotOpenMsg() ),
02295                                   actionCollection() );
02296 
02297   (void) new KAction( i18n("&Compact All Folders"), 0,
02298               this, SLOT(slotCompactAll()),
02299               actionCollection(), "compact_all_folders" );
02300 
02301   (void) new KAction( i18n("&Expire All Folders"), 0,
02302               this, SLOT(slotExpireAll()),
02303               actionCollection(), "expire_all_folders" );
02304 
02305   (void) new KAction( i18n("&Refresh Local IMAP Cache"), "refresh",
02306               this, SLOT(slotInvalidateIMAPFolders()),
02307               actionCollection(), "file_invalidate_imap_cache" );
02308 
02309   (void) new KAction( i18n("Empty All &Trash Folders"), 0,
02310               KMKernel::self(), SLOT(slotEmptyTrash()),
02311               actionCollection(), "empty_trash" );
02312 
02313   (void) new KAction( i18n("Check &Mail"), "mail_get", CTRL+Key_L,
02314               this, SLOT(slotCheckMail()),
02315               actionCollection(), "check_mail" );
02316 
02317   KActionMenu *actActionMenu = new
02318     KActionMenu( i18n("Check Mail &In"), "mail_get", actionCollection(),
02319                     "check_mail_in" );
02320   actActionMenu->setDelayed(true); //needed for checking "all accounts"
02321 
02322   connect(actActionMenu,SIGNAL(activated()),this,SLOT(slotCheckMail()));
02323 
02324   mActMenu = actActionMenu->popupMenu();
02325   connect(mActMenu,SIGNAL(activated(int)),this,SLOT(slotCheckOneAccount(int)));
02326   connect(mActMenu,SIGNAL(aboutToShow()),this,SLOT(getAccountMenu()));
02327 
02328   (void) new KAction( i18n("&Send Queued Messages"), "mail_send", 0, this,
02329              SLOT(slotSendQueued()), actionCollection(), "send_queued");
02330 
02331   (void) new KAction( i18n("Online Status (unknown)"), "online_status", 0, this,
02332                      SLOT(slotOnlineStatus()), actionCollection(), "online_status");
02333 
02334   KActionMenu *sendActionMenu = new
02335     KActionMenu( i18n("Send Queued Messages Via"), "mail_send_via", actionCollection(),
02336                                        "send_queued_via" );
02337   sendActionMenu->setDelayed(true);
02338 
02339   mSendMenu = sendActionMenu->popupMenu();
02340   connect(mSendMenu,SIGNAL(activated(int)), this, SLOT(slotSendQueuedVia(int)));
02341   connect(mSendMenu,SIGNAL(aboutToShow()),this,SLOT(getTransportMenu()));
02342 
02343   KAction *act;
02344   //----- Tools menu
02345   if (parent()->inherits("KMMainWin")) {
02346     act =  new KAction( i18n("&Address Book..."), "contents", 0, this,
02347             SLOT(slotAddrBook()), actionCollection(), "addressbook" );
02348     if (KStandardDirs::findExe("kaddressbook").isEmpty()) act->setEnabled(false);
02349   }
02350 
02351   act = new KAction( i18n("Certificate Manager..."), "pgp-keys", 0, this,
02352              SLOT(slotStartCertManager()), actionCollection(), "tools_start_certman");
02353   // disable action if no certman binary is around
02354   if (KStandardDirs::findExe("kleopatra").isEmpty()) act->setEnabled(false);
02355 
02356   act = new KAction( i18n("GnuPG Log Viewer..."), "pgp-keys", 0, this,
02357              SLOT(slotStartWatchGnuPG()), actionCollection(), "tools_start_kwatchgnupg");
02358   // disable action if no kwatchgnupg binary is around
02359   if (KStandardDirs::findExe("kwatchgnupg").isEmpty()) act->setEnabled(false);
02360 
02361   act = new KAction( i18n("&Import Messages..."), "fileopen", 0, this,
02362              SLOT(slotImport()), actionCollection(), "import" );
02363   if (KStandardDirs::findExe("kmailcvt").isEmpty()) act->setEnabled(false);
02364 
02365 #if !defined(NDEBUG)
02366   (void) new KAction( i18n("&Debug Sieve..."),
02367               "idea", 0, this, SLOT(slotDebugSieve()),
02368               actionCollection(), "tools_debug_sieve" );
02369 #endif
02370 
02371   // @TODO (marc/bo): Test
02372   (void) new KAction( i18n("Edit \"Out of Office\" Replies..."),
02373               "configure", 0, this, SLOT(slotEditVacation()),
02374               actionCollection(), "tools_edit_vacation" );
02375 
02376   (void) new KAction( i18n("Filter &Log Viewer..."), 0, this,
02377               SLOT(slotFilterLogViewer()), actionCollection(), "filter_log_viewer" );
02378 
02379   (void) new KAction( i18n("&Anti-Spam Wizard..."), 0, this,
02380               SLOT(slotAntiSpamWizard()), actionCollection(), "antiSpamWizard" );
02381   (void) new KAction( i18n("&Anti-Virus Wizard..."), 0, this,
02382               SLOT(slotAntiVirusWizard()), actionCollection(), "antiVirusWizard" );
02383 
02384   //----- Edit Menu
02385   mTrashAction = new KAction( KGuiItem( i18n("&Move to Trash"), "edittrash",
02386                                        i18n("Move message to trashcan") ),
02387                              Key_Delete, this, SLOT(slotTrashMsg()),
02388                              actionCollection(), "move_to_trash" );
02389 
02390   /* The delete action is nowhere in the gui, by default, so we need to make
02391    * sure it is plugged into the KAccel now, since that won't happen on
02392    * XMLGui construction or manual ->plug(). This is only a problem when run
02393    * as a part, though. */
02394   mDeleteAction = new KAction( i18n("&Delete"), "editdelete", SHIFT+Key_Delete, this,
02395                               SLOT(slotDeleteMsg()), actionCollection(), "delete" );
02396   mDeleteAction->plugAccel( actionCollection()->kaccel() );
02397 
02398   mTrashThreadAction = new KAction( KGuiItem( i18n("M&ove Thread to Trash"), "edittrash",
02399                                        i18n("Move thread to trashcan") ),
02400                              CTRL+Key_Delete, this, SLOT(slotTrashThread()),
02401                              actionCollection(), "move_thread_to_trash" );
02402 
02403   mDeleteThreadAction = new KAction( i18n("Delete T&hread"), "editdelete", CTRL+SHIFT+Key_Delete, this,
02404                               SLOT(slotDeleteThread()), actionCollection(), "delete_thread" );
02405 
02406 
02407   (void) new KAction( i18n("&Find Messages..."), "mail_find", Key_S, this,
02408               SLOT(slotSearch()), actionCollection(), "search_messages" );
02409 
02410   mFindInMessageAction = new KAction( i18n("&Find in Message..."), "find", KStdAccel::shortcut(KStdAccel::Find), this,
02411               SLOT(slotFind()), actionCollection(), "find_in_messages" );
02412 
02413   (void) new KAction( i18n("Select &All Messages"), KStdAccel::selectAll(), this,
02414               SLOT(slotMarkAll()), actionCollection(), "mark_all_messages" );
02415 
02416   //----- Folder Menu
02417   (void) new KAction( i18n("&New Folder..."), "folder_new", 0, mFolderTree,
02418               SLOT(addChildFolder()), actionCollection(), "new_folder" );
02419 
02420   mModifyFolderAction = new KAction( i18n("&Properties"), "configure", 0, this,
02421               SLOT(slotModifyFolder()), actionCollection(), "modify" );
02422 
02423   mFolderMailingListPropertiesAction = new KAction( i18n("&Mailing List Management"),
02424       /*"folder_mailinglist_properties",*/ 0, this, SLOT( slotFolderMailingListProperties() ),
02425       actionCollection(), "folder_mailinglist_properties" );
02426 
02427   mFolderShortCutCommandAction = new KAction( i18n("&Assign Shortcut..."), "configure_shortcuts",
02428                       0, this, SLOT( slotFolderShortcutCommand() ), actionCollection(),
02429                       "folder_shortcut_command" );
02430 
02431 
02432   mMarkAllAsReadAction = new KAction( i18n("Mark All Messages as &Read"), "goto", 0, this,
02433               SLOT(slotMarkAllAsRead()), actionCollection(), "mark_all_as_read" );
02434 
02435   mExpireFolderAction = new KAction(i18n("&Expiration Settings"), 0, this, SLOT(slotExpireFolder()),
02436                    actionCollection(), "expire");
02437 
02438   mCompactFolderAction = new KAction( i18n("&Compact Folder"), 0, this,
02439               SLOT(slotCompactFolder()), actionCollection(), "compact" );
02440 
02441   mRefreshFolderAction = new KAction( i18n("Check Mail &in This Folder"), "reload",
02442                                       KStdAccel::shortcut( KStdAccel::Reload ), this,
02443                                       SLOT(slotRefreshFolder()),
02444                                       actionCollection(), "refresh_folder" );
02445   mTroubleshootFolderAction = 0; // set in initializeIMAPActions
02446 
02447   mEmptyFolderAction = new KAction( "foo", "edittrash", 0, this,
02448               SLOT(slotEmptyFolder()), actionCollection(), "empty" );
02449 
02450   mRemoveFolderAction = new KAction( "foo", "editdelete", 0, this,
02451               SLOT(slotRemoveFolder()), actionCollection(), "delete_folder" );
02452 
02453   mPreferHtmlAction = new KToggleAction( i18n("Prefer &HTML to Plain Text"), 0, this,
02454               SLOT(slotOverrideHtml()), actionCollection(), "prefer_html" );
02455 
02456   mPreferHtmlLoadExtAction = new KToggleAction( i18n("Load E&xternal References"), 0, this,
02457               SLOT(slotOverrideHtmlLoadExt()), actionCollection(), "prefer_html_external_refs" );
02458 
02459   mThreadMessagesAction = new KToggleAction( i18n("&Thread Messages"), 0, this,
02460               SLOT(slotOverrideThread()), actionCollection(), "thread_messages" );
02461 
02462   mThreadBySubjectAction = new KToggleAction( i18n("Thread Messages also by &Subject"), 0, this,
02463               SLOT(slotToggleSubjectThreading()), actionCollection(), "thread_messages_by_subject" );
02464 
02465 
02466   //----- Message Menu
02467   (void) new KAction( i18n("&New Message..."), "mail_new", KStdAccel::shortcut(KStdAccel::New), this,
02468               SLOT(slotCompose()), actionCollection(), "new_message" );
02469 
02470   (void) new KAction( i18n("New Message t&o Mailing-List..."), "mail_post_to",
02471                       CTRL+SHIFT+Key_N, this,
02472               SLOT(slotPostToML()), actionCollection(), "post_message" );
02473 
02474   mForwardActionMenu = new KActionMenu( i18n("Message->","&Forward"),
02475                     "mail_forward", actionCollection(),
02476                     "message_forward" );
02477   connect( mForwardActionMenu, SIGNAL(activated()), this,
02478        SLOT(slotForwardInlineMsg()) );
02479 
02480   mForwardAttachedAction = new KAction( i18n("Message->Forward->","As &Attachment..."),
02481                        "mail_forward", Key_F, this,
02482                     SLOT(slotForwardAttachedMsg()),
02483                                         actionCollection(),
02484                     "message_forward_as_attachment" );
02485   mForwardActionMenu->insert( forwardAttachedAction() );
02486   mForwardInlineAction = new KAction( i18n("&Inline..."), "mail_forward",
02487                                       SHIFT+Key_F, this,
02488                                       SLOT(slotForwardInlineMsg()),
02489                                       actionCollection(),
02490                                       "message_forward_inline" );
02491 
02492   mForwardActionMenu->insert( forwardInlineAction() );
02493   mForwardDigestAction = new KAction( i18n("Message->Forward->","As Di&gest..."),
02494                                       "mail_forward", 0, this,
02495                                       SLOT(slotForwardDigestMsg()),
02496                                       actionCollection(),
02497                                       "message_forward_as_digest" );
02498   mForwardActionMenu->insert( forwardDigestAction() );
02499   mRedirectAction = new KAction( i18n("Message->Forward->","&Redirect..."),
02500                                  "mail_forward", Key_E, this,
02501                                  SLOT(slotRedirectMsg()),
02502                  actionCollection(),
02503                                  "message_forward_redirect" );
02504   mForwardActionMenu->insert( redirectAction() );
02505 
02506 
02507   mSendAgainAction = new KAction( i18n("Send A&gain..."), 0, this,
02508               SLOT(slotResendMsg()), actionCollection(), "send_again" );
02509 
02510   mReplyActionMenu = new KActionMenu( i18n("Message->","&Reply"),
02511                                       "mail_reply", actionCollection(),
02512                                       "message_reply_menu" );
02513   connect( mReplyActionMenu, SIGNAL(activated()), this,
02514        SLOT(slotReplyToMsg()) );
02515 
02516   mReplyAction = new KAction( i18n("&Reply..."), "mail_reply", Key_R, this,
02517                   SLOT(slotReplyToMsg()), actionCollection(), "reply" );
02518   mReplyActionMenu->insert( mReplyAction );
02519 
02520   mReplyAuthorAction = new KAction( i18n("Reply to A&uthor..."), "mail_reply",
02521                                     SHIFT+Key_A, this,
02522                                     SLOT(slotReplyAuthorToMsg()),
02523                                     actionCollection(), "reply_author" );
02524   mReplyActionMenu->insert( mReplyAuthorAction );
02525 
02526   mReplyAllAction = new KAction( i18n("Reply to &All..."), "mail_replyall",
02527                  Key_A, this, SLOT(slotReplyAllToMsg()),
02528                  actionCollection(), "reply_all" );
02529   mReplyActionMenu->insert( mReplyAllAction );
02530 
02531   mReplyListAction = new KAction( i18n("Reply to Mailing-&List..."),
02532                   "mail_replylist", Key_L, this,
02533                   SLOT(slotReplyListToMsg()), actionCollection(),
02534                   "reply_list" );
02535   mReplyActionMenu->insert( mReplyListAction );
02536 
02537   mNoQuoteReplyAction = new KAction( i18n("Reply Without &Quote..."), SHIFT+Key_R,
02538     this, SLOT(slotNoQuoteReplyToMsg()), actionCollection(), "noquotereply" );
02539 
02540   //----- Create filter actions
02541   mFilterMenu = new KActionMenu( i18n("&Create Filter"), "filter", actionCollection(), "create_filter" );
02542   connect( mFilterMenu, SIGNAL(activated()), this,
02543        SLOT(slotFilter()) );
02544   mSubjectFilterAction = new KAction( i18n("Filter on &Subject..."), 0, this,
02545                       SLOT(slotSubjectFilter()),
02546                       actionCollection(), "subject_filter");
02547   mFilterMenu->insert( mSubjectFilterAction );
02548 
02549   mFromFilterAction = new KAction( i18n("Filter on &From..."), 0, this,
02550                    SLOT(slotFromFilter()),
02551                    actionCollection(), "from_filter");
02552   mFilterMenu->insert( mFromFilterAction );
02553 
02554   mToFilterAction = new KAction( i18n("Filter on &To..."), 0, this,
02555                  SLOT(slotToFilter()),
02556                  actionCollection(), "to_filter");
02557   mFilterMenu->insert( mToFilterAction );
02558 
02559   mListFilterAction = new KAction( i18n("Filter on Mailing-&List..."), 0, this,
02560                                    SLOT(slotMailingListFilter()), actionCollection(),
02561                                    "mlist_filter");
02562   mFilterMenu->insert( mListFilterAction );
02563 
02564   mPrintAction = KStdAction::print (this, SLOT(slotPrintMsg()), actionCollection());
02565 
02566   mEditAction = new KAction( i18n("&Edit Message"), "edit", Key_T, this,
02567                             SLOT(slotEditMsg()), actionCollection(), "edit" );
02568   mEditAction->plugAccel( actionCollection()->kaccel() );
02569 
02570   //----- "Mark Message" submenu
02571   mStatusMenu = new KActionMenu ( i18n( "Mar&k Message" ),
02572                                  actionCollection(), "set_status" );
02573 
02574   mStatusMenu->insert(new KAction(KGuiItem(i18n("Mark Message as &Read"), "kmmsgread",
02575                                           i18n("Mark selected messages as read")),
02576                                  0, this, SLOT(slotSetMsgStatusRead()),
02577                                  actionCollection(), "status_read"));
02578 
02579   mStatusMenu->insert(new KAction(KGuiItem(i18n("Mark Message as &New"), "kmmsgnew",
02580                                           i18n("Mark selected messages as new")),
02581                                  0, this, SLOT(slotSetMsgStatusNew()),
02582                                  actionCollection(), "status_new" ));
02583 
02584   mStatusMenu->insert(new KAction(KGuiItem(i18n("Mark Message as &Unread"), "kmmsgunseen",
02585                                           i18n("Mark selected messages as unread")),
02586                                  0, this, SLOT(slotSetMsgStatusUnread()),
02587                                  actionCollection(), "status_unread"));
02588 
02589   mStatusMenu->insert( new KActionSeparator( this ) );
02590 
02591   // -------- Toggle Actions
02592   mToggleFlagAction = new KToggleAction(i18n("Mark Message as &Important"), "mail_flag",
02593                                  0, this, SLOT(slotSetMsgStatusFlag()),
02594                                  actionCollection(), "status_flag");
02595   mToggleFlagAction->setCheckedState( i18n("Remove &Important Message Mark") );
02596   mStatusMenu->insert( mToggleFlagAction );
02597 
02598   mToggleTodoAction = new KToggleAction(i18n("Mark Message as &To-do"), "mail_todo",
02599                                  0, this, SLOT(slotSetMsgStatusTodo()),
02600                                  actionCollection(), "status_todo");
02601   mToggleTodoAction->setCheckedState( i18n("Remove &To-do Message Mark") );
02602   mStatusMenu->insert( mToggleTodoAction );
02603 
02604   mToggleSentAction = new KToggleAction(i18n("Mark Message as &Sent"), "kmmsgsent",
02605                                  0, this, SLOT(slotSetMsgStatusSent()),
02606                                  actionCollection(), "status_sent");
02607   mToggleSentAction->setCheckedState( i18n("Remove &Sent Mark") );
02608 
02609 
02610   //----- "Mark Thread" submenu
02611   mThreadStatusMenu = new KActionMenu ( i18n( "Mark &Thread" ),
02612                                        actionCollection(), "thread_status" );
02613 
02614   mMarkThreadAsReadAction = new KAction(KGuiItem(i18n("Mark Thread as &Read"), "kmmsgread",
02615                                                 i18n("Mark all messages in the selected thread as read")),
02616                                                 0, this, SLOT(slotSetThreadStatusRead()),
02617                                                 actionCollection(), "thread_read");
02618   mThreadStatusMenu->insert( mMarkThreadAsReadAction );
02619 
02620   mMarkThreadAsNewAction = new KAction(KGuiItem(i18n("Mark Thread as &New"), "kmmsgnew",
02621                                                i18n("Mark all messages in the selected thread as new")),
02622                                                0, this, SLOT(slotSetThreadStatusNew()),
02623                                                actionCollection(), "thread_new");
02624   mThreadStatusMenu->insert( mMarkThreadAsNewAction );
02625 
02626   mMarkThreadAsUnreadAction = new KAction(KGuiItem(i18n("Mark Thread as &Unread"), "kmmsgunseen",
02627                                                 i18n("Mark all messages in the selected thread as unread")),
02628                                                 0, this, SLOT(slotSetThreadStatusUnread()),
02629                                                 actionCollection(), "thread_unread");
02630   mThreadStatusMenu->insert( mMarkThreadAsUnreadAction );
02631 
02632   mThreadStatusMenu->insert( new KActionSeparator( this ) );
02633 
02634   //----- "Mark Thread" toggle actions
02635   mToggleThreadFlagAction = new KToggleAction(i18n("Mark Thread as &Important"), "mail_flag",
02636                                        0, this, SLOT(slotSetThreadStatusFlag()),
02637                                        actionCollection(), "thread_flag");
02638   mToggleThreadFlagAction->setCheckedState( i18n("Remove &Important Thread Mark") );
02639   mThreadStatusMenu->insert( mToggleThreadFlagAction );
02640 
02641   mToggleThreadTodoAction = new KToggleAction(i18n("Mark Thread as &To-do"), "mail_todo",
02642                                        0, this, SLOT(slotSetThreadStatusTodo()),
02643                                        actionCollection(), "thread_todo");
02644   mToggleThreadTodoAction->setCheckedState( i18n("Remove &To-do Thread Mark") );
02645   mThreadStatusMenu->insert( mToggleThreadTodoAction );
02646 
02647   //------- "Watch and ignore thread" actions
02648   mWatchThreadAction = new KToggleAction(i18n("&Watch Thread"), "kmmsgwatched",
02649                                        0, this, SLOT(slotSetThreadStatusWatched()),
02650                                        actionCollection(), "thread_watched");
02651 
02652   mIgnoreThreadAction = new KToggleAction(i18n("&Ignore Thread"), "mail_ignore",
02653                                        0, this, SLOT(slotSetThreadStatusIgnored()),
02654                                        actionCollection(), "thread_ignored");
02655 
02656   mSaveAttachmentsAction = new KAction( i18n("Save A&ttachments..."), "attach",
02657                                 0, this, SLOT(slotSaveAttachments()),
02658                                 actionCollection(), "file_save_attachments" );
02659 
02660   mMoveActionMenu = new KActionMenu( i18n("&Move To" ),
02661                                     actionCollection(), "move_to" );
02662 
02663   mCopyActionMenu = new KActionMenu( i18n("&Copy To" ),
02664                                     actionCollection(), "copy_to" );
02665 
02666   mApplyAllFiltersAction = new KAction( i18n("Appl&y All Filters"), "filter",
02667                     CTRL+Key_J, this,
02668                     SLOT(slotApplyFilters()),
02669                     actionCollection(), "apply_filters" );
02670 
02671   mApplyFilterActionsMenu = new KActionMenu( i18n("A&pply Filter" ),
02672                         actionCollection(),
02673                         "apply_filter_actions" );
02674 
02675   //----- View Menu
02676   // Unread Submenu
02677   KActionMenu * unreadMenu =
02678     new KActionMenu( i18n("View->", "&Unread Count"),
02679              actionCollection(), "view_unread" );
02680   unreadMenu->setToolTip( i18n("Choose how to display the count of unread messages") );
02681 
02682   mUnreadColumnToggle = new KRadioAction( i18n("View->Unread Count", "View in &Separate Column"), 0, this,
02683                    SLOT(slotToggleUnread()),
02684                    actionCollection(), "view_unread_column" );
02685   mUnreadColumnToggle->setExclusiveGroup( "view_unread_group" );
02686   unreadMenu->insert( mUnreadColumnToggle );
02687 
02688   mUnreadTextToggle = new KRadioAction( i18n("View->Unread Count", "View After &Folder Name"), 0, this,
02689                    SLOT(slotToggleUnread()),
02690                    actionCollection(), "view_unread_text" );
02691   mUnreadTextToggle->setExclusiveGroup( "view_unread_group" );
02692   unreadMenu->insert( mUnreadTextToggle );
02693 
02694   // toggle for total column
02695   mTotalColumnToggle = new KToggleAction( i18n("View->", "&Total Column"), 0, this,
02696                    SLOT(slotToggleTotalColumn()),
02697                    actionCollection(), "view_columns_total" );
02698   mTotalColumnToggle->setToolTip( i18n("Toggle display of column showing the "
02699                                       "total number of messages in folders.") );
02700 
02701   (void)new KAction( KGuiItem( i18n("View->","&Expand Thread"), QString::null,
02702                    i18n("Expand the current thread") ),
02703              Key_Period, this,
02704              SLOT(slotExpandThread()),
02705              actionCollection(), "expand_thread" );
02706 
02707   (void)new KAction( KGuiItem( i18n("View->","&Collapse Thread"), QString::null,
02708                    i18n("Collapse the current thread") ),
02709              Key_Comma, this,
02710              SLOT(slotCollapseThread()),
02711              actionCollection(), "collapse_thread" );
02712 
02713   (void)new KAction( KGuiItem( i18n("View->","Ex&pand All Threads"), QString::null,
02714                    i18n("Expand all threads in the current folder") ),
02715              CTRL+Key_Period, this,
02716              SLOT(slotExpandAllThreads()),
02717              actionCollection(), "expand_all_threads" );
02718 
02719   (void)new KAction( KGuiItem( i18n("View->","C&ollapse All Threads"), QString::null,
02720                    i18n("Collapse all threads in the current folder") ),
02721              CTRL+Key_Comma, this,
02722              SLOT(slotCollapseAllThreads()),
02723              actionCollection(), "collapse_all_threads" );
02724 
02725   mViewSourceAction = new KAction( i18n("&View Source"), Key_V, this,
02726                                    SLOT(slotShowMsgSrc()), actionCollection(),
02727                                    "view_source" );
02728 
02729   KAction* dukeOfMonmoth = new KAction( i18n("&Display Message"), Key_Return, this,
02730                         SLOT( slotDisplayCurrentMessage() ), actionCollection(),
02731                         "display_message" );
02732   dukeOfMonmoth->plugAccel( actionCollection()->kaccel() );
02733 
02734   //----- Go Menu
02735   new KAction( KGuiItem( i18n("&Next Message"), QString::null,
02736                          i18n("Go to the next message") ),
02737                          "N;Right", this, SLOT(slotNextMessage()),
02738                          actionCollection(), "go_next_message" );
02739 
02740   new KAction( KGuiItem( i18n("Next &Unread Message"),
02741                          QApplication::reverseLayout() ? "previous" : "next",
02742                          i18n("Go to the next unread message") ),
02743                          Key_Plus, this, SLOT(slotNextUnreadMessage()),
02744                          actionCollection(), "go_next_unread_message" );
02745 
02746   /* ### needs better support from folders:
02747   new KAction( KGuiItem( i18n("Next &Important Message"), QString::null,
02748                          i18n("Go to the next important message") ),
02749                          0, this, SLOT(slotNextImportantMessage()),
02750                          actionCollection(), "go_next_important_message" );
02751   */
02752 
02753   new KAction( KGuiItem( i18n("&Previous Message"), QString::null,
02754                          i18n("Go to the previous message") ),
02755                          "P;Left", this, SLOT(slotPrevMessage()),
02756                          actionCollection(), "go_prev_message" );
02757 
02758   new KAction( KGuiItem( i18n("Previous Unread &Message"),
02759                          QApplication::reverseLayout() ? "next" : "previous",
02760                          i18n("Go to the previous unread message") ),
02761                          Key_Minus, this, SLOT(slotPrevUnreadMessage()),
02762                          actionCollection(), "go_prev_unread_message" );
02763 
02764   /* needs better support from folders:
02765   new KAction( KGuiItem( i18n("Previous I&mportant Message"), QString::null,
02766                          i18n("Go to the previous important message") ),
02767                          0, this, SLOT(slotPrevImportantMessage()),
02768                          actionCollection(), "go_prev_important_message" );
02769   */
02770 
02771   KAction *action =
02772     new KAction( KGuiItem( i18n("Next Unread &Folder"), QString::null,
02773                            i18n("Go to the next folder with unread messages") ),
02774                            ALT+Key_Plus, this, SLOT(slotNextUnreadFolder()),
02775                            actionCollection(), "go_next_unread_folder" );
02776   KShortcut shortcut = action->shortcut();
02777   shortcut.append( KKey( CTRL+Key_Plus ) );
02778   action->setShortcut( shortcut );
02779 
02780   action =
02781     new KAction( KGuiItem( i18n("Previous Unread F&older"), QString::null,
02782                            i18n("Go to the previous folder with unread messages") ),
02783                            ALT+Key_Minus, this, SLOT(slotPrevUnreadFolder()),
02784                            actionCollection(), "go_prev_unread_folder" );
02785   shortcut = action->shortcut();
02786   shortcut.append( KKey( CTRL+Key_Minus ) );
02787   action->setShortcut( shortcut );
02788 
02789   new KAction( KGuiItem( i18n("Go->","Next Unread &Text"), QString::null,
02790                          i18n("Go to the next unread text"),
02791                          i18n("Scroll down current message. "
02792                               "If at end of current message, "
02793                               "go to next unread message.") ),
02794                          Key_Space, this, SLOT(slotReadOn()),
02795                          actionCollection(), "go_next_unread_text" );
02796 
02797   //----- Settings Menu
02798   mToggleShowQuickSearchAction = new KToggleAction(i18n("Show Quick Search"), QString::null,
02799                                        0, this, SLOT(slotToggleShowQuickSearch()),
02800                                        actionCollection(), "show_quick_search");
02801   mToggleShowQuickSearchAction->setChecked( GlobalSettings::self()->quickSearchActive() );
02802   mToggleShowQuickSearchAction->setWhatsThis(
02803         i18n( GlobalSettings::self()->quickSearchActiveItem()->whatsThis().utf8() ) );
02804 
02805   (void) new KAction( i18n("Configure &Filters..."), 0, this,
02806               SLOT(slotFilter()), actionCollection(), "filter" );
02807   (void) new KAction( i18n("Configure &POP Filters..."), 0, this,
02808               SLOT(slotPopFilter()), actionCollection(), "popFilter" );
02809   (void) new KAction( i18n("Manage &Sieve Scripts..."), 0, this,
02810                       SLOT(slotManageSieveScripts()), actionCollection(), "sieveFilters" );
02811 
02812   (void) new KAction( KGuiItem( i18n("KMail &Introduction"), 0,
02813                 i18n("Display KMail's Welcome Page") ),
02814               0, this, SLOT(slotIntro()),
02815               actionCollection(), "help_kmail_welcomepage" );
02816 
02817   // ----- Standard Actions
02818 //  KStdAction::configureNotifications(this, SLOT(slotEditNotifications()), actionCollection());
02819   (void) new KAction( i18n("Configure &Notifications..."),
02820               "knotify", 0, this,
02821               SLOT(slotEditNotifications()), actionCollection(),
02822               "kmail_configure_notifications" );
02823 //  KStdAction::preferences(this, SLOT(slotSettings()), actionCollection());
02824   (void) new KAction( i18n("&Configure KMail..."),
02825               "configure", 0, kmkernel,
02826                       SLOT(slotShowConfigurationDialog()), actionCollection(),
02827                       "kmail_configure_kmail" );
02828 
02829   KStdAction::undo(this, SLOT(slotUndo()), actionCollection(), "kmail_undo");
02830 
02831   KStdAction::tipOfDay( this, SLOT( slotShowTip() ), actionCollection() );
02832 
02833   menutimer = new QTimer( this, "menutimer" );
02834   connect( menutimer, SIGNAL( timeout() ), SLOT( updateMessageActions() ) );
02835   connect( kmkernel->undoStack(),
02836            SIGNAL( undoStackChanged() ), this, SLOT( slotUpdateUndo() ));
02837 
02838   initializeIMAPActions( false ); // don't set state, config not read yet
02839   updateMessageActions();
02840 }
02841 
02842 //-----------------------------------------------------------------------------
02843 void KMMainWidget::slotEditNotifications()
02844 {
02845   if(kmkernel->xmlGuiInstance())
02846     KNotifyDialog::configure(this, 0, kmkernel->xmlGuiInstance()->aboutData());
02847   else
02848     KNotifyDialog::configure(this);
02849 }
02850 
02851 void KMMainWidget::slotEditKeys()
02852 {
02853   KKeyDialog::configure( actionCollection(),
02854              true /*allow one-letter shortcuts*/
02855              );
02856 }
02857 
02858 //-----------------------------------------------------------------------------
02859 void KMMainWidget::slotReadOn()
02860 {
02861     if ( !mMsgView )
02862         return;
02863 
02864     if ( !mMsgView->atBottom() ) {
02865         mMsgView->slotJumpDown();
02866         return;
02867     }
02868     slotNextUnreadMessage();
02869 }
02870 
02871 void KMMainWidget::slotNextUnreadFolder() {
02872   if ( !mFolderTree ) return;
02873   mFolderTree->nextUnreadFolder();
02874 }
02875 
02876 void KMMainWidget::slotPrevUnreadFolder() {
02877   if ( !mFolderTree ) return;
02878   mFolderTree->prevUnreadFolder();
02879 }
02880 
02881 void KMMainWidget::slotExpandThread()
02882 {
02883   mHeaders->slotExpandOrCollapseThread( true ); // expand
02884 }
02885 
02886 void KMMainWidget::slotCollapseThread()
02887 {
02888   mHeaders->slotExpandOrCollapseThread( false ); // collapse
02889 }
02890 
02891 void KMMainWidget::slotExpandAllThreads()
02892 {
02893   mHeaders->slotExpandOrCollapseAllThreads( true ); // expand
02894 }
02895 
02896 void KMMainWidget::slotCollapseAllThreads()
02897 {
02898   mHeaders->slotExpandOrCollapseAllThreads( false ); // collapse
02899 }
02900 
02901 //-----------------------------------------------------------------------------
02902 void KMMainWidget::slotShowMsgSrc()
02903 {
02904   if ( mMsgView )
02905     mMsgView->setUpdateAttachment( false );
02906   KMMessage *msg = mHeaders->currentMsg();
02907   if ( !msg )
02908     return;
02909   KMCommand *command = new KMShowMsgSrcCommand( this, msg,
02910                                                 mMsgView
02911                                                 ? mMsgView->isFixedFont()
02912                                                 : false );
02913   command->start();
02914 }
02915 
02916 
02917 //-----------------------------------------------------------------------------
02918 void KMMainWidget::moveSelectedToFolder( int menuId )
02919 {
02920   if (mMenuToFolder[menuId])
02921     mHeaders->moveMsgToFolder( mMenuToFolder[menuId] );
02922 }
02923 
02924 
02925 //-----------------------------------------------------------------------------
02926 void KMMainWidget::copySelectedToFolder(int menuId )
02927 {
02928   if (mMenuToFolder[menuId])
02929     mHeaders->copyMsgToFolder( mMenuToFolder[menuId] );
02930 }
02931 
02932 
02933 //-----------------------------------------------------------------------------
02934 void KMMainWidget::updateMessageMenu()
02935 {
02936   mMenuToFolder.clear();
02937   folderTree()->folderToPopupMenu( KMFolderTree::MoveMessage, this,
02938       &mMenuToFolder, mMoveActionMenu->popupMenu() );
02939   folderTree()->folderToPopupMenu( KMFolderTree::CopyMessage, this,
02940       &mMenuToFolder, mCopyActionMenu->popupMenu() );
02941   updateMessageActions();
02942 }
02943 
02944 void KMMainWidget::startUpdateMessageActionsTimer()
02945 {
02946     menutimer->stop();
02947     menutimer->start( 20, true );
02948 }
02949 
02950 void KMMainWidget::updateMessageActions()
02951 {
02952     int count = 0;
02953     QPtrList<QListViewItem> selectedItems;
02954 
02955     if ( mFolder ) {
02956       for (QListViewItem *item = mHeaders->firstChild(); item; item = item->itemBelow())
02957         if (item->isSelected() )
02958           selectedItems.append(item);
02959       if ( selectedItems.isEmpty() && mFolder->count() ) // there will always be one in mMsgView
02960         count = 1;
02961       else
02962         count = selectedItems.count();
02963     }
02964 
02965     updateListFilterAction();
02966 
02967     bool allSelectedInCommonThread = false;
02968     if ( mHeaders->isThreaded() && count > 1 ) {
02969       allSelectedInCommonThread = true;
02970       QListViewItem * curItemParent = mHeaders->currentItem();
02971       while ( curItemParent->parent() )
02972         curItemParent = curItemParent->parent();
02973       for ( QPtrListIterator<QListViewItem> it( selectedItems ) ;
02974             it.current() ; ++ it ) {
02975         QListViewItem * item = *it;
02976         while ( item->parent() )
02977           item = item->parent();
02978         if ( item != curItemParent ) {
02979           allSelectedInCommonThread = false;
02980           break;
02981         }
02982       }
02983     }
02984     else if ( mHeaders->isThreaded() && count == 1 ) {
02985       allSelectedInCommonThread = true;
02986     }
02987 
02988     QListViewItem *curItemParent = mHeaders->currentItem();
02989     bool parent_thread = 0;
02990     if ( curItemParent && curItemParent->firstChild() != 0 ) parent_thread = 1;
02991 
02992     bool mass_actions = count >= 1;
02993     bool thread_actions = mass_actions && allSelectedInCommonThread &&
02994                           mHeaders->isThreaded();
02995     mStatusMenu->setEnabled( mass_actions );
02996     mThreadStatusMenu->setEnabled( thread_actions );
02997     // these need to be handled individually, the user might have them
02998     // in the toolbar
02999     mWatchThreadAction->setEnabled( thread_actions );
03000     mIgnoreThreadAction->setEnabled( thread_actions );
03001     mMarkThreadAsNewAction->setEnabled( thread_actions );
03002     mMarkThreadAsReadAction->setEnabled( thread_actions );
03003     mMarkThreadAsUnreadAction->setEnabled( thread_actions );
03004     mToggleThreadTodoAction->setEnabled( thread_actions );
03005     mToggleThreadFlagAction->setEnabled( thread_actions );
03006     mTrashThreadAction->setEnabled( thread_actions && !mFolder->isReadOnly() );
03007     mDeleteThreadAction->setEnabled( thread_actions && !mFolder->isReadOnly() );
03008 
03009     if (mFolder && mHeaders && mHeaders->currentMsg()) {
03010       mToggleTodoAction->setChecked(mHeaders->currentMsg()->isTodo());
03011       mToggleSentAction->setChecked(mHeaders->currentMsg()->isSent());
03012       mToggleFlagAction->setChecked(mHeaders->currentMsg()->isImportant());
03013       if (thread_actions) {
03014         mToggleThreadTodoAction->setChecked(mHeaders->currentMsg()->isTodo());
03015         mToggleThreadFlagAction->setChecked(mHeaders->currentMsg()->isImportant());
03016         mWatchThreadAction->setChecked( mHeaders->currentMsg()->isWatched());
03017         mIgnoreThreadAction->setChecked( mHeaders->currentMsg()->isIgnored());
03018       }
03019     }
03020 
03021     mMoveActionMenu->setEnabled( mass_actions && !mFolder->isReadOnly() );
03022     mCopyActionMenu->setEnabled( mass_actions );
03023     mTrashAction->setEnabled( mass_actions && !mFolder->isReadOnly() );
03024     mDeleteAction->setEnabled( mass_actions && !mFolder->isReadOnly() );
03025     mFindInMessageAction->setEnabled( mass_actions );
03026     mForwardInlineAction->setEnabled( mass_actions );
03027     mForwardAttachedAction->setEnabled( mass_actions );
03028     mForwardDigestAction->setEnabled( count > 1 || parent_thread );
03029 
03030     forwardMenu()->setEnabled( mass_actions );
03031 
03032     bool single_actions = count == 1;
03033     mEditAction->setEnabled( single_actions &&
03034     kmkernel->folderIsDraftOrOutbox(mFolder));
03035     replyMenu()->setEnabled( single_actions );
03036     filterMenu()->setEnabled( single_actions );
03037     replyAction()->setEnabled( single_actions );
03038     noQuoteReplyAction()->setEnabled( single_actions );
03039     replyAuthorAction()->setEnabled( single_actions );
03040     replyAllAction()->setEnabled( single_actions );
03041     replyListAction()->setEnabled( single_actions );
03042     redirectAction()->setEnabled( single_actions );
03043     printAction()->setEnabled( single_actions );
03044     viewSourceAction()->setEnabled( single_actions );
03045 
03046     mSendAgainAction->setEnabled( single_actions &&
03047              ( mHeaders->currentMsg() && mHeaders->currentMsg()->isSent() )
03048           || ( mFolder && mHeaders->currentMsg() &&
03049               ( kmkernel->folderIsDraftOrOutbox( mFolder )
03050              || kmkernel->folderIsSentMailFolder( mFolder ) ) ) );
03051     mSaveAsAction->setEnabled( mass_actions );
03052     bool mails = mFolder && mFolder->count();
03053     bool enable_goto_unread = mails
03054        || (GlobalSettings::self()->loopOnGotoUnread() == GlobalSettings::EnumLoopOnGotoUnread::LoopInAllFolders);
03055     actionCollection()->action( "go_next_message" )->setEnabled( mails );
03056     actionCollection()->action( "go_next_unread_message" )->setEnabled( enable_goto_unread );
03057     actionCollection()->action( "go_prev_message" )->setEnabled( mails );
03058     actionCollection()->action( "go_prev_unread_message" )->setEnabled( enable_goto_unread );
03059     actionCollection()->action( "send_queued" )->setEnabled( kmkernel->outboxFolder()->count() > 0 );
03060     actionCollection()->action( "send_queued_via" )->setEnabled( kmkernel->outboxFolder()->count() > 0 );
03061     slotUpdateOnlineStatus( static_cast<GlobalSettingsBase::EnumNetworkState::type>( GlobalSettings::self()->networkState() ) );
03062     if (action( "edit_undo" ))
03063       action( "edit_undo" )->setEnabled( mHeaders->canUndo() );
03064 
03065     if ( count == 1 ) {
03066       KMMessage *msg;
03067       int aIdx;
03068       if((aIdx = mHeaders->currentItemIndex()) <= -1)
03069         return;
03070       if(!(msg = mFolder->getMsg(aIdx)))
03071         return;
03072 
03073       if (mFolder == kmkernel->outboxFolder())
03074         mEditAction->setEnabled( !msg->transferInProgress() );
03075     }
03076 
03077     mApplyAllFiltersAction->setEnabled(count);
03078     mApplyFilterActionsMenu->setEnabled(count);
03079 }
03080 
03081 // This needs to be updated more often, so it is in its method.
03082 void KMMainWidget::updateMarkAsReadAction()
03083 {
03084   mMarkAllAsReadAction->setEnabled( mFolder && (mFolder->countUnread() > 0) );
03085 }
03086 
03087 //-----------------------------------------------------------------------------
03088 void KMMainWidget::updateFolderMenu()
03089 {
03090   bool folderWithContent = mFolder && !mFolder->noContent();
03091   mModifyFolderAction->setEnabled( folderWithContent );
03092   mFolderMailingListPropertiesAction->setEnabled( folderWithContent );
03093   mCompactFolderAction->setEnabled( folderWithContent );
03094 
03095   // This is the refresh-folder action in the menu. See kmfoldertree for the one in the RMB...
03096   bool imap = mFolder && mFolder->folderType() == KMFolderTypeImap;
03097   bool cachedImap = mFolder && mFolder->folderType() == KMFolderTypeCachedImap;
03098   // For dimap, check that the imap path is known before allowing "check mail in this folder".
03099   bool knownImapPath = cachedImap && !static_cast<KMFolderCachedImap*>( mFolder->storage() )->imapPath().isEmpty();
03100   mRefreshFolderAction->setEnabled( folderWithContent && ( imap
03101                                                            || ( cachedImap && knownImapPath ) ) );
03102   if ( mTroubleshootFolderAction )
03103     mTroubleshootFolderAction->setEnabled( folderWithContent && ( cachedImap && knownImapPath ) );
03104   mEmptyFolderAction->setEnabled( folderWithContent && ( mFolder->count() > 0 ) && !mFolder->isReadOnly() );
03105   mEmptyFolderAction->setText( (mFolder && kmkernel->folderIsTrash(mFolder))
03106     ? i18n("E&mpty Trash") : i18n("&Move All Messages to Trash") );
03107   mRemoveFolderAction->setEnabled( mFolder && !mFolder->isSystemFolder() && !mFolder->isReadOnly() );
03108   if(mFolder) {
03109     mRemoveFolderAction->setText( mFolder->folderType() == KMFolderTypeSearch
03110         ? i18n("&Delete Search") : i18n("&Delete Folder") );
03111   }
03112   mExpireFolderAction->setEnabled( mFolder && mFolder->isAutoExpire() );
03113   updateMarkAsReadAction();
03114   // the visual ones only make sense if we are showing a message list
03115   mPreferHtmlAction->setEnabled( mHeaders->folder() ? true : false );
03116   mPreferHtmlLoadExtAction->setEnabled( mHeaders->folder() && (mHtmlPref ? !mFolderHtmlPref : mFolderHtmlPref) ? true : false );
03117   mThreadMessagesAction->setEnabled( mHeaders->folder() ? true : false );
03118 
03119   mPreferHtmlAction->setChecked( mHtmlPref ? !mFolderHtmlPref : mFolderHtmlPref );
03120   mPreferHtmlLoadExtAction->setChecked( mHtmlLoadExtPref ? !mFolderHtmlLoadExtPref : mFolderHtmlLoadExtPref );
03121   mThreadMessagesAction->setChecked(
03122       mThreadPref ? !mFolderThreadPref : mFolderThreadPref );
03123   mThreadBySubjectAction->setEnabled(
03124       mHeaders->folder() ? ( mThreadMessagesAction->isChecked()) : false );
03125   mThreadBySubjectAction->setChecked( mFolderThreadSubjPref );
03126 }
03127 
03128 
03129 #ifdef MALLOC_DEBUG
03130 static QString fmt(long n) {
03131   char buf[32];
03132 
03133   if(n > 1024*1024*1024)
03134     sprintf(buf, "%0.2f GB", ((double)n)/1024.0/1024.0/1024.0);
03135   else if(n > 1024*1024)
03136     sprintf(buf, "%0.2f MB", ((double)n)/1024.0/1024.0);
03137   else if(n > 1024)
03138     sprintf(buf, "%0.2f KB", ((double)n)/1024.0);
03139   else
03140     sprintf(buf, "%ld Byte", n);
03141   return QString(buf);
03142 }
03143 #endif
03144 
03145 void KMMainWidget::slotMemInfo() {
03146 #ifdef MALLOC_DEBUG
03147   struct mallinfo mi;
03148 
03149   mi = mallinfo();
03150   QString s = QString("\nMALLOC - Info\n\n"
03151               "Number of mmapped regions : %1\n"
03152               "Memory allocated in use   : %2\n"
03153               "Memory allocated, not used: %3\n"
03154               "Memory total allocated    : %4\n"
03155               "Max. freeable memory      : %5\n")
03156     .arg(mi.hblks).arg(fmt(mi.uordblks)).arg(fmt(mi.fordblks))
03157     .arg(fmt(mi.arena)).arg(fmt(mi.keepcost));
03158   KMessageBox::information(0, s, "Malloc information", s);
03159 #endif
03160 }
03161 
03162 
03163 //-----------------------------------------------------------------------------
03164 void KMMainWidget::slotIntro()
03165 {
03166   if ( !mMsgView ) return;
03167 
03168   mMsgView->clear( true );
03169   // hide widgets that are in the way:
03170   if ( mSearchAndHeaders && mHeaders && mLongFolderList )
03171     mSearchAndHeaders->hide();
03172 
03173 
03174   mMsgView->displayAboutPage();
03175 
03176   mFolder = 0;
03177 }
03178 
03179 void KMMainWidget::slotShowStartupFolder()
03180 {
03181   if ( mFolderTree ) {
03182     mFolderTree->reload();
03183     mFolderTree->readConfig();
03184     // get rid of old-folders
03185     mFolderTree->cleanupConfigFile();
03186   }
03187 
03188   connect( kmkernel->filterMgr(), SIGNAL( filterListUpdated() ),
03189        this, SLOT( initializeFilterActions() ));
03190 
03191   // plug shortcut filter actions now
03192   initializeFilterActions();
03193 
03194   // plug folder shortcut actions
03195   initializeFolderShortcutActions();
03196 
03197   QString newFeaturesMD5 = KMReaderWin::newFeaturesMD5();
03198   if ( kmkernel->firstStart() ||
03199        GlobalSettings::self()->previousNewFeaturesMD5() != newFeaturesMD5 ) {
03200     GlobalSettings::self()->setPreviousNewFeaturesMD5( newFeaturesMD5 );
03201     slotIntro();
03202     return;
03203   }
03204 
03205   KMFolder* startup = 0;
03206   if ( !mStartupFolder.isEmpty() ) {
03207     // find the startup-folder
03208     startup = kmkernel->findFolderById( mStartupFolder );
03209   }
03210   if ( !startup )
03211     startup = kmkernel->inboxFolder();
03212 
03213   if ( mFolderTree ) {
03214     mFolderTree->showFolder( startup );
03215   }
03216 }
03217 
03218 void KMMainWidget::slotShowTip()
03219 {
03220   KTipDialog::showTip( this, QString::null, true );
03221 }
03222 
03223 //-----------------------------------------------------------------------------
03224 void KMMainWidget::slotChangeCaption(QListViewItem * i)
03225 {
03226   if ( !i ) return;
03227   // set the caption to the current full path
03228   QStringList names;
03229   for ( QListViewItem * item = i ; item ; item = item->parent() )
03230     names.prepend( item->text(0) );
03231   emit captionChangeRequest( names.join( "/" ) );
03232 }
03233 
03234 //-----------------------------------------------------------------------------
03235 void KMMainWidget::removeDuplicates()
03236 {
03237   if (!mFolder)
03238     return;
03239   KMFolder *oFolder = mFolder;
03240   mHeaders->setFolder(0);
03241   QMap< QString, QValueList<int> > idMD5s;
03242   QValueList<int> redundantIds;
03243   QValueList<int>::Iterator kt;
03244   mFolder->open();
03245   for (int i = mFolder->count() - 1; i >= 0; --i) {
03246     QString id = (*mFolder)[i]->msgIdMD5();
03247     if ( !id.isEmpty() ) {
03248       QString subjMD5 = (*mFolder)[i]->strippedSubjectMD5();
03249       int other = -1;
03250       if ( idMD5s.contains(id) )
03251         other = idMD5s[id].first();
03252       else
03253         idMD5s[id].append( i );
03254       if ( other != -1 ) {
03255         QString otherSubjMD5 = (*mFolder)[other]->strippedSubjectMD5();
03256         if (otherSubjMD5 == subjMD5)
03257           idMD5s[id].append( i );
03258       }
03259     }
03260   }
03261   QMap< QString, QValueList<int> >::Iterator it;
03262   for ( it = idMD5s.begin(); it != idMD5s.end() ; ++it ) {
03263     QValueList<int>::Iterator jt;
03264     bool finished = false;
03265     for ( jt = (*it).begin(); jt != (*it).end() && !finished; ++jt )
03266       if (!((*mFolder)[*jt]->isUnread())) {
03267         (*it).remove( jt );
03268         (*it).prepend( *jt );
03269         finished = true;
03270       }
03271     for ( jt = (*it).begin(), ++jt; jt != (*it).end(); ++jt )
03272       redundantIds.append( *jt );
03273   }
03274   qHeapSort( redundantIds );
03275   kt = redundantIds.end();
03276   int numDuplicates = 0;
03277   if (kt != redundantIds.begin()) do {
03278     mFolder->removeMsg( *(--kt) );
03279     ++numDuplicates;
03280   }
03281   while (kt != redundantIds.begin());
03282 
03283   mFolder->close();
03284   mHeaders->setFolder(oFolder);
03285   QString msg;
03286   if ( numDuplicates )
03287     msg = i18n("Removed %n duplicate message.",
03288                "Removed %n duplicate messages.", numDuplicates );
03289     else
03290       msg = i18n("No duplicate messages found.");
03291   BroadcastStatus::instance()->setStatusMsg( msg );
03292 }
03293 
03294 
03295 //-----------------------------------------------------------------------------
03296 void KMMainWidget::slotUpdateUndo()
03297 {
03298     if (actionCollection()->action( "edit_undo" ))
03299         actionCollection()->action( "edit_undo" )->setEnabled( mHeaders->canUndo() );
03300 }
03301 
03302 
03303 //-----------------------------------------------------------------------------
03304 void KMMainWidget::clearFilterActions()
03305 {
03306   if ( !mFilterTBarActions.isEmpty() ) {
03307     if ( mGUIClient->factory() )
03308       mGUIClient->unplugActionList( "toolbar_filter_actions" );
03309     mFilterTBarActions.clear();
03310   }
03311   mApplyFilterActionsMenu->popupMenu()->clear();
03312   if ( !mFilterMenuActions.isEmpty() ) {
03313     if ( mGUIClient->factory() )
03314       mGUIClient->unplugActionList( "menu_filter_actions" );
03315     mFilterMenuActions.clear();
03316   }
03317   mFilterCommands.clear();
03318 }
03319 
03320 //-----------------------------------------------------------------------------
03321 void KMMainWidget::initializeFolderShortcutActions()
03322 {
03323 
03324   // If we are loaded as a part, this will be set to fals, since the part
03325   // does xml loading. Temporarily set to true, in that case, so the
03326   // accels are added to the collection as expected.
03327   bool old = actionCollection()->isAutoConnectShortcuts();
03328 
03329   actionCollection()->setAutoConnectShortcuts( true );
03330   QValueList< QGuardedPtr< KMFolder > > folders = kmkernel->allFolders();
03331   QValueList< QGuardedPtr< KMFolder > >::Iterator it = folders.begin();
03332   while ( it != folders.end() ) {
03333     KMFolder *folder = (*it);
03334     ++it;
03335     slotShortcutChanged( folder ); // load the initial accel
03336   }
03337   actionCollection()->setAutoConnectShortcuts( old );
03338 }
03339 
03340 
03341 //-----------------------------------------------------------------------------
03342 void KMMainWidget::initializeFilterActions()
03343 {
03344   QString filterName, normalizedName;
03345   KMMetaFilterActionCommand *filterCommand;
03346   KAction *filterAction = 0;
03347 
03348   clearFilterActions();
03349   mApplyAllFiltersAction->plug(mApplyFilterActionsMenu->popupMenu());
03350   bool addedSeparator = false;
03351   QValueListConstIterator<KMFilter*> it = kmkernel->filterMgr()->filters().constBegin();
03352   for ( ;it != kmkernel->filterMgr()->filters().constEnd(); ++it ) {
03353     if (!(*it)->isEmpty() && (*it)->configureShortcut()) {
03354       filterName = QString("Filter %1").arg((*it)->name());
03355       normalizedName = filterName.replace(" ", "_");
03356       if (action(normalizedName.utf8()))
03357         continue;
03358       filterCommand = new KMMetaFilterActionCommand(*it, mHeaders, this);
03359       mFilterCommands.append(filterCommand);
03360       QString as = i18n("Filter %1").arg((*it)->name());
03361       QString icon = (*it)->icon();
03362       if ( icon.isEmpty() )
03363         icon = "gear";
03364       filterAction = new KAction(as, icon, (*it)->shortcut(), filterCommand,
03365                                  SLOT(start()), actionCollection(),
03366                                  normalizedName.local8Bit());
03367       if(!addedSeparator) {
03368         mApplyFilterActionsMenu->popupMenu()->insertSeparator();
03369         addedSeparator = !addedSeparator;
03370     mFilterMenuActions.append( new KActionSeparator());
03371       }
03372       filterAction->plug( mApplyFilterActionsMenu->popupMenu() );
03373       mFilterMenuActions.append(filterAction);
03374       if ( (*it)->configureToolbar() )
03375         mFilterTBarActions.append(filterAction);
03376     }
03377   }
03378   if ( !mFilterMenuActions.isEmpty() && mGUIClient->factory() )
03379     mGUIClient->plugActionList( "menu_filter_actions", mFilterMenuActions );
03380   if ( !mFilterTBarActions.isEmpty() && mGUIClient->factory() ) {
03381     mFilterTBarActions.prepend( mToolbarActionSeparator );
03382     mGUIClient->plugActionList( "toolbar_filter_actions", mFilterTBarActions );
03383   }
03384 }
03385 
03386 void KMMainWidget::slotFolderRemoved( KMFolder *folder )
03387 {
03388   mFolderShortcutCommands.remove( folder->idString() );
03389 }
03390 
03391 //-----------------------------------------------------------------------------
03392 void KMMainWidget::initializeIMAPActions( bool setState /* false the first time, true later on */ )
03393 {
03394   bool hasImapAccount = false;
03395   for( KMAccount *a = kmkernel->acctMgr()->first(); a;
03396        a = kmkernel->acctMgr()->next() ) {
03397     if ( a->type() == "cachedimap" ) {
03398       hasImapAccount = true;
03399       break;
03400     }
03401   }
03402   if ( hasImapAccount == ( mTroubleshootFolderAction != 0 ) )
03403     return; // nothing to do
03404 
03405   KXMLGUIFactory* factory = mGUIClient->factory();
03406   if ( factory )
03407     factory->removeClient( mGUIClient );
03408 
03409   if ( !mTroubleshootFolderAction ) {
03410     mTroubleshootFolderAction = new KAction( i18n("&Troubleshoot IMAP Cache..."), "wizard", 0,
03411      this, SLOT(slotTroubleshootFolder()), actionCollection(), "troubleshoot_folder" );
03412     if ( setState )
03413       updateFolderMenu(); // set initial state of the action
03414   } else {
03415     delete mTroubleshootFolderAction ;
03416     mTroubleshootFolderAction = 0;
03417   }
03418 
03419   if ( factory )
03420     factory->addClient( mGUIClient );
03421 }
03422 
03423 bool KMMainWidget::shortcutIsValid( const KShortcut &sc ) const
03424 {
03425   KActionPtrList actions = actionCollection()->actions();
03426   KActionPtrList::Iterator it( actions.begin() );
03427   for ( ; it != actions.end(); it++ ) {
03428     if ( (*it)->shortcut() == sc ) return false;
03429   }
03430   return true;
03431 }
03432 
03433 void KMMainWidget::slotShortcutChanged( KMFolder *folder )
03434 {
03435   // remove the old one, autodelete
03436   mFolderShortcutCommands.remove( folder->idString() );
03437   if ( folder->shortcut().isNull() )
03438     return;
03439 
03440   FolderShortcutCommand *c = new FolderShortcutCommand( this, folder );
03441   mFolderShortcutCommands.insert( folder->idString(), c );
03442 
03443   QString actionlabel = QString( "FolderShortcut %1").arg( folder->prettyURL() );
03444   QString actionname = QString( "FolderShortcut %1").arg( folder->idString() );
03445   QString normalizedName = actionname.replace(" ", "_");
03446   KAction* action =
03447     new KAction(actionlabel, folder->shortcut(), c, SLOT(start()),
03448                 actionCollection(), normalizedName.local8Bit());
03449   action->setIcon( folder->unreadIconPath() );
03450   c->setAction( action ); // will be deleted along with the command
03451 }
03452 
03453 //-----------------------------------------------------------------------------
03454 void KMMainWidget::slotSubscriptionDialog()
03455 {
03456   if (!mFolder) return;
03457 
03458   if ( !kmkernel->askToGoOnline() ) {
03459     return;
03460   }
03461 
03462   ImapAccountBase* account;
03463   QString startPath;
03464   if (mFolder->folderType() == KMFolderTypeImap)
03465   {
03466     startPath = static_cast<KMFolderImap*>(mFolder->storage())->imapPath();
03467     account = static_cast<KMFolderImap*>(mFolder->storage())->account();
03468   } else if (mFolder->folderType() == KMFolderTypeCachedImap)
03469   {
03470     startPath = static_cast<KMFolderCachedImap*>(mFolder->storage())->imapPath();
03471     account = static_cast<KMFolderCachedImap*>(mFolder->storage())->account();
03472   } else
03473     return;
03474 
03475   if ( !account ) return;
03476 
03477   SubscriptionDialog *dialog = new SubscriptionDialog(this,
03478       i18n("Subscription"),
03479       account, startPath);
03480   // start a new listing
03481   if ( dialog->exec() ) {
03482     if (mFolder->folderType() == KMFolderTypeImap)
03483       static_cast<KMFolderImap*>(mFolder->storage())->account()->listDirectory();
03484   }
03485 }
03486 
03487 //-----------------------------------------------------------------------------
03488 void KMMainWidget::slotFolderTreeColumnsChanged()
03489 {
03490   mTotalColumnToggle->setChecked( mFolderTree->isTotalActive() );
03491   mUnreadColumnToggle->setChecked( mFolderTree->isUnreadActive() );
03492 }
03493 
03494 void KMMainWidget::toggleSystemTray()
03495 {
03496   if ( !mSystemTray && GlobalSettings::self()->systemTrayEnabled() ) {
03497     mSystemTray = new KMSystemTray();
03498   }
03499   else if ( mSystemTray && !GlobalSettings::self()->systemTrayEnabled() ) {
03500     // Get rid of system tray on user's request
03501     kdDebug(5006) << "deleting systray" << endl;
03502     delete mSystemTray;
03503     mSystemTray = 0;
03504   }
03505 
03506   // Set mode of systemtray. If mode has changed, tray will handle this.
03507   if ( mSystemTray )
03508     mSystemTray->setMode( GlobalSettings::self()->systemTrayPolicy() );
03509 }
03510 
03511 //-----------------------------------------------------------------------------
03512 void KMMainWidget::slotAntiSpamWizard()
03513 {
03514   AntiSpamWizard wiz( AntiSpamWizard::AntiSpam, this, folderTree() );
03515   wiz.exec();
03516 }
03517 
03518 //-----------------------------------------------------------------------------
03519 void KMMainWidget::slotAntiVirusWizard()
03520 {
03521   AntiSpamWizard wiz( AntiSpamWizard::AntiVirus, this, folderTree() );
03522   wiz.exec();
03523 }
03524 
03525 //-----------------------------------------------------------------------------
03526 void KMMainWidget::slotFilterLogViewer()
03527 {
03528   FilterLogDialog * dlg = new FilterLogDialog( 0 );
03529   dlg->show();
03530 }
03531 
03532 //-----------------------------------------------------------------------------
03533 void KMMainWidget::updateFileMenu()
03534 {
03535   QStringList actList = kmkernel->acctMgr()->getAccounts();
03536 
03537   actionCollection()->action("check_mail")->setEnabled( actList.size() > 0 );
03538   actionCollection()->action("check_mail_in")->setEnabled( actList.size() > 0 );
03539 }
03540 
03541 
03542 //-----------------------------------------------------------------------------
03543 void KMMainWidget::setAccelsEnabled( bool enabled )
03544 {
03545   actionCollection()->kaccel()->setEnabled( enabled );
03546 }
03547 
03548 
03549 //-----------------------------------------------------------------------------
03550 KMSystemTray *KMMainWidget::systray() const
03551 {
03552   return mSystemTray;
03553 }
03554 
03555 //-----------------------------------------------------------------------------
03556 QString KMMainWidget::overrideEncoding() const
03557 {
03558   if ( mMsgView )
03559     return mMsgView->overrideEncoding();
03560   else
03561     return GlobalSettings::self()->overrideCharacterEncoding();
03562 }
KDE Home | KDE Accessibility Home | Description of Access Keys