kmail

kmmainwidget.cpp

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