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