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