kmail

kmmainwidget.cpp

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