kmail

kmmainwidget.cpp

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