kmail

kmmainwidget.cpp

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