kmail

kmmainwidget.cpp

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