kmail

kmmainwidget.cpp

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