kmail

kmmainwidget.cpp

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