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