kmail Library API Documentation

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 
00018 #include <kopenwith.h>
00019 
00020 #include <kmessagebox.h>
00021 
00022 #include <kaccelmanager.h>
00023 #include <kglobalsettings.h>
00024 #include <kstdaccel.h>
00025 #include <kkeydialog.h>
00026 #include <kcharsets.h>
00027 #include <knotifyclient.h>
00028 #include <kdebug.h>
00029 #include <kapplication.h>
00030 #include <kfiledialog.h>
00031 #include <ktip.h>
00032 #include <knotifydialog.h>
00033 #include <kstandarddirs.h>
00034 #include <dcopclient.h>
00035 
00036 #include "kcursorsaver.h"
00037 #include "kmbroadcaststatus.h"
00038 #include "kmfoldermgr.h"
00039 #include "kmfolderdia.h"
00040 #include "kmacctmgr.h"
00041 #include "kmfilter.h"
00042 #include "kmfoldertree.h"
00043 #include "kmreadermainwin.h"
00044 #include "kmfoldercachedimap.h"
00045 #include "kmacctcachedimap.h"
00046 #include "kmcomposewin.h"
00047 #include "kmfolderseldlg.h"
00048 #include "kmfiltermgr.h"
00049 #include "kmsender.h"
00050 #include "kmaddrbook.h"
00051 #include "kmversion.h"
00052 #include "kmfldsearch.h"
00053 #include "kmacctfolder.h"
00054 #include "undostack.h"
00055 #include "kmcommands.h"
00056 #include "kmmainwidget.h"
00057 #include "kmmainwin.h"
00058 #include "kmsystemtray.h"
00059 #include "vacation.h"
00060 using KMail::Vacation;
00061 #include "subscriptiondialog.h"
00062 using KMail::SubscriptionDialog;
00063 #include "attachmentstrategy.h"
00064 using KMail::AttachmentStrategy;
00065 #include "headerstrategy.h"
00066 using KMail::HeaderStrategy;
00067 #include "headerstyle.h"
00068 using KMail::HeaderStyle;
00069 #include "folderjob.h"
00070 using KMail::FolderJob;
00071 #include "mailinglist-magic.h"
00072 #include "kmgroupware.h"
00073 
00074 #include <assert.h>
00075 #include <kstatusbar.h>
00076 
00077 #include <kmime_mdn.h>
00078 #include <kmime_header_parsing.h>
00079 using namespace KMime;
00080 using KMime::Types::AddrSpecList;
00081 
00082 #include "kmmainwidget.moc"
00083 
00084 //-----------------------------------------------------------------------------
00085 KMMainWidget::KMMainWidget(QWidget *parent, const char *name,
00086                KActionCollection *actionCollection, KConfig* config ) :
00087     QWidget(parent, name)
00088 {
00089   // must be the first line of the constructor:
00090   mSearchWin = 0;
00091   mStartupDone = FALSE;
00092   mIntegrated  = TRUE;
00093   mFolder = 0;
00094   mFolderThreadPref = false;
00095   mFolderThreadSubjPref = true;
00096   mReaderWindowActive = true;
00097   mReaderWindowBelow = true;
00098   mFolderHtmlPref = false;
00099   mCountJobs = 0;
00100   mSystemTray = 0;
00101   mDestructed = false;
00102   mActionCollection = actionCollection;
00103   mTopLayout = new QVBoxLayout(this);
00104   mFilterActions.setAutoDelete(true);
00105   mFilterCommands.setAutoDelete(true);
00106   mJob = 0;
00107   mConfig = config;
00108 
00109   mPanner1Sep << 1 << 1;
00110   mPanner2Sep << 1 << 1;
00111 
00112   setMinimumSize(400, 300);
00113 
00114   kmkernel->groupware().setMainWidget( this );
00115 
00116   readPreConfig();
00117   createWidgets();
00118 
00119   setupStatusBar();
00120   setupActions();
00121 
00122   readConfig();
00123 
00124   activatePanners();
00125 
00126   QTimer::singleShot( 0, this, SLOT( slotShowStartupFolder() ));
00127 
00128   connect(kmkernel->acctMgr(), SIGNAL( checkedMail(bool, bool)),
00129           SLOT( slotMailChecked(bool, bool)));
00130 
00131   connect(kmkernel, SIGNAL( configChanged() ),
00132           this, SLOT( slotConfigChanged() ));
00133 
00134   // display the full path to the folder in the caption
00135   connect(mFolderTree, SIGNAL(currentChanged(QListViewItem*)),
00136       this, SLOT(slotChangeCaption(QListViewItem*)));
00137   connect( KMBroadcastStatus::instance(), SIGNAL(statusMsg( const QString& )),
00138        this, SLOT(statusMsg( const QString& )));
00139 
00140   if ( kmkernel->firstInstance() )
00141     QTimer::singleShot( 200, this, SLOT(slotShowTipOnStart()) );
00142 
00143   toggleSystray(mSystemTrayOnNew, mSystemTrayMode);
00144 
00145   // must be the last line of the constructor:
00146   mStartupDone = TRUE;
00147 }
00148 
00149 
00150 //-----------------------------------------------------------------------------
00151 //The kernel may have already been deleted when this method is called,
00152 //perform all cleanup that requires the kernel in destruct()
00153 KMMainWidget::~KMMainWidget()
00154 {
00155   destruct();
00156 }
00157 
00158 
00159 //-----------------------------------------------------------------------------
00160 //This method performs all cleanup that requires the kernel to exist.
00161 void KMMainWidget::destruct()
00162 {
00163   if (mDestructed)
00164     return;
00165   if (mSearchWin)
00166     mSearchWin->close();
00167   writeConfig();
00168   writeFolderConfig();
00169   delete mHeaders;
00170   delete mFolderTree;
00171   delete mSystemTray;
00172   delete mMsgView;
00173   mDestructed = true;
00174 }
00175 
00176 
00177 //-----------------------------------------------------------------------------
00178 void KMMainWidget::readPreConfig(void)
00179 {
00180   const KConfigGroup geometry( KMKernel::config(), "Geometry" );
00181   const KConfigGroup general( KMKernel::config(), "General" );
00182 
00183   mLongFolderList = geometry.readEntry( "FolderList", "long" ) != "short";
00184   mEncodingStr = general.readEntry("encoding", "").latin1();
00185   mReaderWindowActive = geometry.readEntry( "readerWindowMode", "below" ) != "hide";
00186   mReaderWindowBelow = geometry.readEntry( "readerWindowMode", "below" ) == "below";
00187 }
00188 
00189 
00190 //-----------------------------------------------------------------------------
00191 void KMMainWidget::readFolderConfig(void)
00192 {
00193   if (!mFolder)
00194     return;
00195 
00196   KConfig *config = KMKernel::config();
00197   KConfigGroupSaver saver(config, "Folder-" + mFolder->idString());
00198   mFolderThreadPref = config->readBoolEntry( "threadMessagesOverride", false );
00199   mFolderThreadSubjPref = config->readBoolEntry( "threadMessagesBySubject", true );
00200   mFolderHtmlPref = config->readBoolEntry( "htmlMailOverride", false );
00201 }
00202 
00203 
00204 //-----------------------------------------------------------------------------
00205 void KMMainWidget::writeFolderConfig(void)
00206 {
00207   if (!mFolder)
00208     return;
00209 
00210   KConfig *config = KMKernel::config();
00211   KConfigGroupSaver saver(config, "Folder-" + mFolder->idString());
00212   config->writeEntry( "threadMessagesOverride", mFolderThreadPref );
00213   config->writeEntry( "threadMessagesBySubject", mFolderThreadSubjPref );
00214   config->writeEntry( "htmlMailOverride", mFolderHtmlPref );
00215 }
00216 
00217 
00218 //-----------------------------------------------------------------------------
00219 void KMMainWidget::readConfig(void)
00220 {
00221   KConfig *config = KMKernel::config();
00222 
00223   bool oldLongFolderList =  mLongFolderList;
00224   bool oldReaderWindowActive = mReaderWindowActive;
00225   bool oldReaderWindowBelow = mReaderWindowBelow;
00226 
00227   QString str;
00228   QSize siz;
00229 
00230   if (mStartupDone)
00231   {
00232     writeConfig();
00233 
00234     readPreConfig();
00235     mHeaders->refreshNestedState();
00236 
00237     bool layoutChanged = ( oldLongFolderList != mLongFolderList )
00238                     || ( oldReaderWindowActive != mReaderWindowActive )
00239                     || ( oldReaderWindowBelow != mReaderWindowBelow );
00240 
00241 
00242     if( layoutChanged ) {
00243       hide();
00244       // delete all panners
00245       delete mPanner1; // will always delete the others
00246       createWidgets();
00247     }
00248 
00249   }
00250 
00251   // read "Reader" config options
00252   KConfigGroup readerConfig( config, "Reader" );
00253   mHtmlPref = readerConfig.readBoolEntry( "htmlMail", false );
00254   // restore the toggle action to the saved value; this is also read during
00255   // the reader initialization
00256   if (mMsgView)
00257     toggleFixFontAction()->setChecked( readerConfig.readBoolEntry( "useFixedFont",
00258                                                                false ) );
00259 
00260   mHtmlPref = readerConfig.readBoolEntry( "htmlMail", false );
00261 
00262   { // area for config group "Geometry"
00263     KConfigGroupSaver saver(config, "Geometry");
00264     mThreadPref = config->readBoolEntry( "nestedMessages", false );
00265     // size of the mainwin
00266     QSize defaultSize(750,560);
00267     siz = config->readSizeEntry("MainWin", &defaultSize);
00268     if (!siz.isEmpty())
00269       resize(siz);
00270     // default width of the foldertree
00271     static const int folderpanewidth = 250;
00272 
00273     const int folderW = config->readNumEntry( "FolderPaneWidth", folderpanewidth );
00274     const int headerW = config->readNumEntry( "HeaderPaneWidth", width()-folderpanewidth );
00275     const int headerH = config->readNumEntry( "HeaderPaneHeight", 180 );
00276     const int readerH = config->readNumEntry( "ReaderPaneHeight", 280 );
00277 
00278     mPanner1Sep.clear();
00279     mPanner2Sep.clear();
00280     QValueList<int> & widths = mLongFolderList ? mPanner1Sep : mPanner2Sep ;
00281     QValueList<int> & heights = mLongFolderList ? mPanner2Sep : mPanner1Sep ;
00282 
00283     widths << folderW << headerW;
00284     heights << headerH << readerH;
00285 
00286     bool layoutChanged = ( oldLongFolderList != mLongFolderList )
00287                     || ( oldReaderWindowActive != mReaderWindowActive )
00288                     || ( oldReaderWindowBelow != mReaderWindowBelow );
00289 
00290     if (!mStartupDone || layoutChanged )
00291     {
00295       // The columns are shown by default.
00296       int unreadColumn = config->readNumEntry("UnreadColumn", -1);
00297       int totalColumn = config->readNumEntry("TotalColumn", -1);
00298 
00299       /* we need to _activate_ them in the correct order
00300       * this is ugly because we can't use header()->moveSection
00301       * but otherwise the restoreLayout from KMFolderTree
00302       * doesn't know that to do */
00303       if (unreadColumn != -1 && unreadColumn < totalColumn)
00304         mFolderTree->toggleColumn(KMFolderTree::unread);
00305       if (totalColumn != -1)
00306         mFolderTree->toggleColumn(KMFolderTree::total);
00307       if (unreadColumn != -1 && unreadColumn > totalColumn)
00308         mFolderTree->toggleColumn(KMFolderTree::unread);
00309 
00310     }
00311   }
00312 
00313   if (mMsgView)
00314     mMsgView->readConfig();
00315   slotSetEncoding();
00316   mHeaders->readConfig();
00317   mHeaders->restoreLayout(KMKernel::config(), "Header-Geometry");
00318   mFolderTree->readConfig();
00319 
00320   { // area for config group "General"
00321     KConfigGroupSaver saver(config, "General");
00322     mSendOnCheck = config->readBoolEntry("sendOnCheck",false);
00323     mBeepOnNew = config->readBoolEntry("beep-on-mail", false);
00324     mSystemTrayOnNew = config->readBoolEntry("systray-on-mail", false);
00325     mSystemTrayMode = config->readBoolEntry("systray-on-new", true) ?
00326       KMSystemTray::OnNewMail :
00327       KMSystemTray::AlwaysOn;
00328     mConfirmEmpty = config->readBoolEntry("confirm-before-empty", true);
00329     // startup-Folder, defaults to system-inbox
00330     mStartupFolder = config->readEntry("startupFolder", kmkernel->inboxFolder()->idString());
00331     if (!mStartupDone)
00332     {
00333       // check mail on startup
00334       bool check = config->readBoolEntry("checkmail-startup", false);
00335       if (check) slotCheckMail();
00336     }
00337   }
00338 
00339   // Re-activate panners
00340   if (mStartupDone)
00341   {
00342 
00343     // Update systray
00344     toggleSystray(mSystemTrayOnNew, mSystemTrayMode);
00345 
00346     bool layoutChanged = ( oldLongFolderList != mLongFolderList )
00347                     || ( oldReaderWindowActive != mReaderWindowActive )
00348                     || ( oldReaderWindowBelow != mReaderWindowBelow );
00349     if ( layoutChanged ) {
00350       activatePanners();
00351     }
00352 
00353     //    kmkernel->kbp()->busy(); //Crashes KMail
00354     mFolderTree->reload();
00355     QListViewItem *qlvi = mFolderTree->indexOfFolder(mFolder);
00356     if (qlvi!=0) {
00357       mFolderTree->setCurrentItem(qlvi);
00358       mFolderTree->setSelected(qlvi,TRUE);
00359     }
00360 
00361 
00362     // sanders - New code
00363     mHeaders->setFolder(mFolder, true);
00364     if (mMsgView) {
00365       int aIdx = mHeaders->currentItemIndex();
00366       if (aIdx != -1)
00367         mMsgView->setMsg( mFolder->getMsg(aIdx), true );
00368       else
00369         mMsgView->clear( true );
00370     }
00371     updateMessageActions();
00372     show();
00373     // sanders - Maybe this fixes a bug?
00374 
00375   }
00376   updateMessageMenu();
00377 }
00378 
00379 
00380 //-----------------------------------------------------------------------------
00381 void KMMainWidget::writeConfig(void)
00382 {
00383   QString s;
00384   KConfig *config = KMKernel::config();
00385   KConfigGroup geometry( config, "Geometry" );
00386   KConfigGroup general( config, "General" );
00387 
00388   if (mMsgView)
00389     mMsgView->writeConfig();
00390 
00391   mFolderTree->writeConfig();
00392 
00393   geometry.writeEntry( "MainWin", this->geometry().size() );
00394 
00395   const QValueList<int> widths = ( mLongFolderList ? mPanner1 : mPanner2 )->sizes();
00396   const QValueList<int> heights = ( mLongFolderList ? mPanner2 : mPanner1 )->sizes();
00397 
00398   geometry.writeEntry( "FolderPaneWidth", widths[0] );
00399   geometry.writeEntry( "HeaderPaneWidth", widths[1] );
00400   geometry.writeEntry( "HeaderPaneHeight", heights[0] );
00401   geometry.writeEntry( "ReaderPaneHeight", heights[1] );
00402 
00403   // save the state of the unread/total-columns
00404   geometry.writeEntry( "UnreadColumn", mFolderTree->unreadIndex() );
00405   geometry.writeEntry( "TotalColumn", mFolderTree->totalIndex() );
00406 
00407   general.writeEntry("encoding", QString(mEncodingStr));
00408 }
00409 
00410 
00411 //-----------------------------------------------------------------------------
00412 void KMMainWidget::createWidgets(void)
00413 {
00414   QAccel *accel = new QAccel(this, "createWidgets()");
00415 
00416   // Create the splitters according to the layout settings
00417   QWidget *headerParent = 0, *folderParent = 0,
00418             *mimeParent = 0, *messageParent = 0;
00419 
00420 #if KDE_IS_VERSION( 3, 1, 92 )
00421   const bool opaqueResize = KGlobalSettings::opaqueResize();
00422 #else
00423   const bool opaqueResize = true;
00424 #endif
00425   if ( mLongFolderList ) {
00426     // superior splitter: folder tree vs. rest
00427     // inferior splitter: headers vs. message vs. mime tree
00428     mPanner1 = new QSplitter( Qt::Horizontal, this, "panner 1" );
00429     mPanner1->setOpaqueResize( opaqueResize );
00430     Qt::Orientation orientation = mReaderWindowBelow ? Qt::Vertical : Qt::Horizontal;
00431     mPanner2 = new QSplitter( orientation, mPanner1, "panner 2" );
00432     mPanner2->setOpaqueResize( opaqueResize );
00433     folderParent = mPanner1;
00434     headerParent = mimeParent = messageParent = mPanner2;
00435   } else /* !mLongFolderList */ {
00436     // superior splitter: ( folder tree + headers ) vs. message vs. mime
00437     // inferior splitter: folder tree vs. headers
00438     mPanner1 = new QSplitter( Qt::Vertical, this, "panner 1" );
00439     mPanner1->setOpaqueResize( opaqueResize );
00440     mPanner2 = new QSplitter( Qt::Horizontal, mPanner1, "panner 2" );
00441     mPanner2->setOpaqueResize( opaqueResize );
00442     headerParent = folderParent = mPanner2;
00443     mimeParent = messageParent = mPanner1;
00444   }
00445 
00446 #ifndef NDEBUG
00447   if( mPanner1 ) mPanner1->dumpObjectTree();
00448   if( mPanner2 ) mPanner2->dumpObjectTree();
00449 #endif
00450 
00451   mTopLayout->add( mPanner1 );
00452 
00453   // BUG -sanders these accelerators stop working after switching
00454   // between long/short folder layout
00455   // Probably need to disconnect them first.
00456 
00457   // create list of messages
00458 #ifndef NDEBUG
00459   headerParent->dumpObjectTree();
00460 #endif
00461   mHeaders = new KMHeaders(this, headerParent, "headers");
00462   mHeaders->setFullWidth(true);
00463   if (mReaderWindowActive) {
00464     connect(mHeaders, SIGNAL(selected(KMMessage*)),
00465             this, SLOT(slotMsgSelected(KMMessage*)));
00466   }
00467   connect(mHeaders, SIGNAL(activated(KMMessage*)),
00468       this, SLOT(slotMsgActivated(KMMessage*)));
00469   connect( mHeaders, SIGNAL( selectionChanged() ),
00470            SLOT( startUpdateMessageActionsTimer() ) );
00471   accel->connectItem(accel->insertItem(SHIFT+Key_Left),
00472                      mHeaders, SLOT(selectPrevMessage()));
00473   accel->connectItem(accel->insertItem(SHIFT+Key_Right),
00474                      mHeaders, SLOT(selectNextMessage()));
00475 
00476   if (!mEncodingStr.isEmpty())
00477     mCodec = KMMsgBase::codecForName(mEncodingStr);
00478   else mCodec = 0;
00479 
00480   if (mReaderWindowActive) {
00481     mMsgView = new KMReaderWin(messageParent, this, actionCollection(), 0 );
00482 
00483     connect(mMsgView, SIGNAL(replaceMsgByUnencryptedVersion()),
00484         this, SLOT(slotReplaceMsgByUnencryptedVersion()));
00485     connect(mMsgView, SIGNAL(popupMenu(KMMessage&,const KURL&,const QPoint&)),
00486         this, SLOT(slotMsgPopup(KMMessage&,const KURL&,const QPoint&)));
00487     connect(mMsgView, SIGNAL(urlClicked(const KURL&,int)),
00488         mMsgView, SLOT(slotUrlClicked()));
00489     connect(mHeaders, SIGNAL(maybeDeleting()),
00490         mMsgView, SLOT(clearCache()));
00491     connect(mMsgView, SIGNAL(noDrag()),
00492         mHeaders, SLOT(slotNoDrag()));
00493     connect(mMsgView, SIGNAL(statusMsg(const QString&)),
00494         this, SLOT(statusMsg(const QString&)));
00495     accel->connectItem(accel->insertItem(Key_Up),
00496         mMsgView, SLOT(slotScrollUp()));
00497     accel->connectItem(accel->insertItem(Key_Down),
00498         mMsgView, SLOT(slotScrollDown()));
00499     accel->connectItem(accel->insertItem(Key_Prior),
00500         mMsgView, SLOT(slotScrollPrior()));
00501     accel->connectItem(accel->insertItem(Key_Next),
00502         mMsgView, SLOT(slotScrollNext()));
00503   } else {
00504     mMsgView = NULL;
00505   }
00506 
00507   new KAction( i18n("Move Message to Folder"), Key_M, this,
00508                SLOT(slotMoveMsg()), actionCollection(),
00509                "move_message_to_folder" );
00510   new KAction( i18n("Copy Message to Folder"), Key_C, this,
00511                SLOT(slotCopyMsg()), actionCollection(),
00512                "copy_message_to_folder" );
00513   accel->connectItem(accel->insertItem(Key_M),
00514              this, SLOT(slotMoveMsg()) );
00515   accel->connectItem(accel->insertItem(Key_C),
00516              this, SLOT(slotCopyMsg()) );
00517 
00518   // create list of folders
00519   mFolderTree = new KMFolderTree(this, folderParent, "folderTree");
00520 
00521   connect(mFolderTree, SIGNAL(folderSelected(KMFolder*)),
00522       this, SLOT(folderSelected(KMFolder*)));
00523   connect(mFolderTree, SIGNAL(folderSelectedUnread(KMFolder*)),
00524       this, SLOT(folderSelectedUnread(KMFolder*)));
00525   connect(mFolderTree, SIGNAL(folderDrop(KMFolder*)),
00526       this, SLOT(slotMoveMsgToFolder(KMFolder*)));
00527   connect(mFolderTree, SIGNAL(folderDropCopy(KMFolder*)),
00528           this, SLOT(slotCopyMsgToFolder(KMFolder*)));
00529   connect(mFolderTree, SIGNAL(columnsChanged()),
00530           this, SLOT(slotFolderTreeColumnsChanged()));
00531 
00532   //Commands not worthy of menu items, but that deserve configurable keybindings
00533   new KAction(
00534     i18n("Remove Duplicate Messages"), CTRL+Key_Asterisk, this,
00535     SLOT(removeDuplicates()), actionCollection(), "remove_duplicate_messages");
00536 
00537   new KAction(
00538    i18n("Focus on Next Folder"), CTRL+Key_Right, mFolderTree,
00539    SLOT(incCurrentFolder()), actionCollection(), "inc_current_folder");
00540   accel->connectItem(accel->insertItem(CTRL+Key_Right),
00541                      mFolderTree, SLOT(incCurrentFolder()));
00542 
00543 
00544   new KAction(
00545    i18n("Focus on Previous Folder"), CTRL+Key_Left, mFolderTree,
00546    SLOT(decCurrentFolder()), actionCollection(), "dec_current_folder");
00547   accel->connectItem(accel->insertItem(CTRL+Key_Left),
00548                      mFolderTree, SLOT(decCurrentFolder()));
00549 
00550   new KAction(
00551    i18n("Select Folder with Focus"), CTRL+Key_Space, mFolderTree,
00552    SLOT(selectCurrentFolder()), actionCollection(), "select_current_folder");
00553   accel->connectItem(accel->insertItem(CTRL+Key_Space),
00554                      mFolderTree, SLOT(selectCurrentFolder()));
00555 
00556   connect( kmkernel->outboxFolder(), SIGNAL( msgRemoved(int, QString, QString) ),
00557            SLOT( startUpdateMessageActionsTimer() ) );
00558   connect( kmkernel->outboxFolder(), SIGNAL( msgAdded(int) ),
00559            SLOT( startUpdateMessageActionsTimer() ) );
00560 }
00561 
00562 
00563 //-----------------------------------------------------------------------------
00564 void KMMainWidget::activatePanners(void)
00565 {
00566   if (mMsgView) {
00567     QObject::disconnect( actionCollection()->action( "kmail_copy" ),
00568         SIGNAL( activated() ),
00569         mMsgView, SLOT( slotCopySelectedText() ));
00570   }
00571   if ( mLongFolderList ) {
00572     mHeaders->reparent( mPanner2, 0, QPoint( 0, 0 ) );
00573     if (mMsgView) {
00574       mMsgView->reparent( mPanner2, 0, QPoint( 0, 0 ) );
00575       mPanner2->moveToLast( mMsgView );
00576     }
00577     mFolderTree->reparent( mPanner1, 0, QPoint( 0, 0 ) );
00578     mPanner1->moveToLast( mPanner2 );
00579     mPanner1->setSizes( mPanner1Sep );
00580     mPanner1->setResizeMode( mFolderTree, QSplitter::KeepSize );
00581     mPanner2->setSizes( mPanner2Sep );
00582     mPanner2->setResizeMode( mHeaders, QSplitter::KeepSize );
00583   } else /* !mLongFolderList */ {
00584     mFolderTree->reparent( mPanner2, 0, QPoint( 0, 0 ) );
00585     mHeaders->reparent( mPanner2, 0, QPoint( 0, 0 ) );
00586     mPanner2->moveToLast( mHeaders );
00587     mPanner1->moveToFirst( mPanner2 );
00588     if (mMsgView) {
00589       mMsgView->reparent( mPanner1, 0, QPoint( 0, 0 ) );
00590       mPanner1->moveToLast( mMsgView );
00591     }
00592     mPanner1->setSizes( mPanner1Sep );
00593     mPanner2->setSizes( mPanner2Sep );
00594     mPanner1->setResizeMode( mPanner2, QSplitter::KeepSize );
00595     mPanner2->setResizeMode( mFolderTree, QSplitter::KeepSize );
00596   }
00597 
00598   if (mMsgView) {
00599     QObject::connect( actionCollection()->action( "kmail_copy" ),
00600             SIGNAL( activated() ),
00601             mMsgView, SLOT( slotCopySelectedText() ));
00602   }
00603 }
00604 
00605 
00606 //-----------------------------------------------------------------------------
00607 void KMMainWidget::slotSetEncoding()
00608 {
00609     mEncodingStr = KGlobal::charsets()->encodingForName(mEncoding->currentText()).latin1();
00610     if (mEncoding->currentItem() == 0) // Auto
00611     {
00612       mCodec = 0;
00613       mEncodingStr = "";
00614     }
00615     else
00616       mCodec = KMMsgBase::codecForName( mEncodingStr );
00617     if (mMsgView)
00618       mMsgView->setOverrideCodec(mCodec);
00619     return;
00620 }
00621 
00622 //-----------------------------------------------------------------------------
00623 void KMMainWidget::hide()
00624 {
00625   QWidget::hide();
00626 }
00627 
00628 
00629 //-----------------------------------------------------------------------------
00630 void KMMainWidget::show()
00631 {
00632   QWidget::show();
00633 }
00634 
00635 //-------------------------------------------------------------------------
00636 void KMMainWidget::slotSearch()
00637 {
00638   if(!mSearchWin)
00639   {
00640     mSearchWin = new KMFldSearch(this, "Search", mFolder, false);
00641     connect(mSearchWin, SIGNAL(destroyed()),
00642         this, SLOT(slotSearchClosed()));
00643   }
00644   else
00645   {
00646     mSearchWin->activateFolder(mFolder);
00647   }
00648 
00649   mSearchWin->show();
00650   KWin::activateWindow( mSearchWin->winId() );
00651 }
00652 
00653 
00654 //-------------------------------------------------------------------------
00655 void KMMainWidget::slotSearchClosed()
00656 {
00657   mSearchWin = 0;
00658 }
00659 
00660 
00661 //-------------------------------------------------------------------------
00662 void KMMainWidget::slotFind()
00663 {
00664   if( mMsgView )
00665     mMsgView->slotFind();
00666 }
00667 
00668 
00669 //-----------------------------------------------------------------------------
00670 void KMMainWidget::slotHelp()
00671 {
00672   kapp->invokeHelp();
00673 }
00674 
00675 
00676 //-----------------------------------------------------------------------------
00677 void KMMainWidget::slotNewMailReader()
00678 {
00679   KMMainWin *d;
00680 
00681   d = new KMMainWin();
00682   d->show();
00683   d->resize(d->size());
00684 }
00685 
00686 
00687 //-----------------------------------------------------------------------------
00688 void KMMainWidget::slotFilter()
00689 {
00690   kmkernel->filterMgr()->openDialog( this );
00691 }
00692 
00693 
00694 //-----------------------------------------------------------------------------
00695 void KMMainWidget::slotPopFilter()
00696 {
00697   kmkernel->popFilterMgr()->openDialog( this );
00698 }
00699 
00700 
00701 //-----------------------------------------------------------------------------
00702 void KMMainWidget::slotAddrBook()
00703 {
00704   KMAddrBookExternal::openAddressBook(this);
00705 }
00706 
00707 
00708 //-----------------------------------------------------------------------------
00709 void KMMainWidget::slotImport()
00710 {
00711   KRun::runCommand("kmailcvt");
00712 }
00713 
00714 
00715 //-----------------------------------------------------------------------------
00716 void KMMainWidget::slotAddFolder()
00717 {
00718   KMFolderDialog *d;
00719 
00720   d = new KMFolderDialog(0, &(kmkernel->folderMgr()->dir()),
00721              this, i18n("Create Folder"));
00722   if (d->exec()) {
00723     mFolderTree->reload();
00724     QListViewItem *qlvi = mFolderTree->indexOfFolder( mFolder );
00725     if (qlvi) {
00726       qlvi->setOpen(TRUE);
00727       mFolderTree->setCurrentItem( qlvi );
00728     }
00729   }
00730   delete d;
00731 }
00732 
00733 
00734 //-----------------------------------------------------------------------------
00735 void KMMainWidget::slotCheckMail()
00736 {
00737  kmkernel->acctMgr()->checkMail(true);
00738 }
00739 
00740 
00741 //-----------------------------------------------------------------------------
00742 void KMMainWidget::slotCheckOneAccount(int item)
00743 {
00744   kmkernel->acctMgr()->intCheckMail(item);
00745 }
00746 
00747 //-----------------------------------------------------------------------------
00748 void KMMainWidget::slotMailChecked(bool newMail, bool sendOnCheck)
00749 {
00750   if(mSendOnCheck && sendOnCheck)
00751     slotSendQueued();
00752 
00753   if (!newMail)
00754     return;
00755 
00756   if(kmkernel->xmlGuiInstance()) {
00757     KNotifyClient::Instance instance(kmkernel->xmlGuiInstance());
00758     KNotifyClient::event(topLevelWidget()->winId(), "new-mail-arrived", 
00759       i18n("New mail arrived"));
00760   }
00761   else
00762     KNotifyClient::event(topLevelWidget()->winId(), "new-mail-arrived", 
00763       i18n("New mail arrived"));
00764   if (mBeepOnNew) {
00765     KNotifyClient::beep();
00766   }
00767   kapp->dcopClient()->emitDCOPSignal( "unreadCountChanged()", QByteArray() );
00768 
00769   // Todo:
00770   // scroll mHeaders to show new items if current item would
00771   // still be visible
00772   //  mHeaders->showNewMail();
00773 }
00774 
00775 
00776 //-----------------------------------------------------------------------------
00777 void KMMainWidget::slotCompose()
00778 {
00779   KMComposeWin *win;
00780   KMMessage* msg = new KMMessage;
00781 
00782   if ( mFolder ) {
00783       msg->initHeader( mFolder->identity() );
00784       win = new KMComposeWin(msg, mFolder->identity());
00785   } else {
00786       msg->initHeader();
00787       win = new KMComposeWin(msg);
00788   }
00789 
00790   win->show();
00791 
00792 }
00793 
00794 
00795 //-----------------------------------------------------------------------------
00796 void KMMainWidget::slotPostToML()
00797 {
00798   KMComposeWin *win;
00799   KMMessage* msg = new KMMessage;
00800 
00801   if ( mFolder ) {
00802       msg->initHeader( mFolder->identity() );
00803 
00804       if (mFolder->isMailingList()) {
00805           kdDebug(5006)<<QString("mFolder->isMailingList() %1").arg( mFolder->mailingListPostAddress().latin1())<<endl;
00806 
00807           msg->setTo(mFolder->mailingListPostAddress());
00808       }
00809       win = new KMComposeWin(msg, mFolder->identity());
00810       win->setFocusToSubject();
00811   } else {
00812       msg->initHeader();
00813       win = new KMComposeWin(msg);
00814   }
00815 
00816   win->show();
00817 
00818 }
00819 
00820 
00821 //-----------------------------------------------------------------------------
00822 void KMMainWidget::slotModifyFolder()
00823 {
00824   if (!mFolderTree) return;
00825   KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( mFolderTree->currentItem() );
00826   if ( item )
00827     item->properties();
00828 }
00829 
00830 //-----------------------------------------------------------------------------
00831 void KMMainWidget::slotExpireFolder()
00832 {
00833   QString     str;
00834   bool        canBeExpired = true;
00835 
00836   if (!mFolder) return;
00837 
00838   if (!mFolder->isAutoExpire()) {
00839     canBeExpired = false;
00840   } else if (mFolder->getUnreadExpireUnits()==expireNever &&
00841          mFolder->getReadExpireUnits()==expireNever) {
00842     canBeExpired = false;
00843   }
00844 
00845   if (!canBeExpired) {
00846     str = i18n("This folder does not have any expiry options set");
00847     KMessageBox::information(this, str);
00848     return;
00849   }
00850   KConfig           *config = KMKernel::config();
00851   KConfigGroupSaver saver(config, "General");
00852 
00853   if (config->readBoolEntry("warn-before-expire", true)) {
00854     str = i18n("<qt>Are you sure you want to expire the folder <b>%1</b>?</qt>").arg(mFolder->label());
00855     if (KMessageBox::warningContinueCancel(this, str, i18n("Expire Folder"),
00856                        i18n("&Expire"))
00857     != KMessageBox::Continue) return;
00858   }
00859 
00860   mFolder->expireOldMessages();
00861 }
00862 
00863 //-----------------------------------------------------------------------------
00864 void KMMainWidget::slotEmptyFolder()
00865 {
00866   QString str;
00867   KMMessage* msg;
00868 
00869   if (!mFolder) return;
00870   bool isTrash = kmkernel->folderIsTrash(mFolder);
00871 
00872   if (mConfirmEmpty)
00873   {
00874     QString title = (isTrash) ? i18n("Empty Trash") : i18n("Move to Trash");
00875     QString text = (isTrash) ?
00876       i18n("Are you sure you want to empty the trash folder?") :
00877       i18n("<qt>Are you sure you want to move all messages from "
00878            "folder <b>%1</b> to the trash?</qt>").arg(mFolder->label());
00879 
00880     if (KMessageBox::warningContinueCancel(this, text, title, title)
00881       != KMessageBox::Continue) return;
00882   }
00883 
00884   if (mFolder->folderType() == KMFolderTypeImap
00885       || mFolder->folderType() == KMFolderTypeSearch)
00886   {
00887     slotMarkAll();
00888     if (isTrash)
00889       slotDeleteMsg();
00890     else
00891       slotTrashMsg();
00892     return;
00893   }
00894 
00895   if (mMsgView)
00896     mMsgView->clearCache();
00897 
00898   KCursorSaver busy(KBusyPtr::busy());
00899 
00900   // begin of critical part
00901   // from here to "end..." no signal may change to another mFolder, otherwise
00902   // the wrong folder will be truncated in expunge (dnaber, 1999-08-29)
00903   mFolder->open();
00904   mHeaders->setFolder(0);
00905   if (mMsgView)
00906     mMsgView->clear();
00907 
00908   if (mFolder != kmkernel->trashFolder())
00909   {
00910     // FIXME: If we run out of disk space mail may be lost rather
00911     // than moved into the trash -sanders
00912     while ((msg = mFolder->take(0)) != 0) {
00913       kmkernel->trashFolder()->addMsg(msg);
00914       kmkernel->trashFolder()->unGetMsg(kmkernel->trashFolder()->count()-1);
00915     }
00916   }
00917 
00918   mFolder->close();
00919   mFolder->expunge();
00920   // end of critical
00921   if (mFolder != kmkernel->trashFolder())
00922     statusMsg(i18n("Moved all messages to the trash"));
00923 
00924   mHeaders->setFolder(mFolder);
00925   updateMessageActions();
00926 }
00927 
00928 
00929 //-----------------------------------------------------------------------------
00930 void KMMainWidget::slotRemoveFolder()
00931 {
00932   QString str;
00933   QDir dir;
00934 
00935   if (!mFolder) return;
00936   if (mFolder->isSystemFolder()) return;
00937 
00938   if ( mFolder->folderType() == KMFolderTypeSearch ) {
00939      str = i18n("<qt>Are you sure you want to delete the search folder "
00940                 "<b>%1</b>? The messages displayed in it will not be deleted "
00941                 "if you do so, as they are stored in a different folder.</qt>")
00942 
00943            .arg(mFolder->label());
00944   } else {
00945     if ( mFolder->count() == 0 ) {
00946       if ( !mFolder->child() || mFolder->child()->isEmpty() ) {
00947         str = i18n("<qt>Are you sure you want to delete the empty folder "
00948                    "<b>%1</b>?</qt>")
00949               .arg(mFolder->label());
00950       }
00951       else {
00952         str = i18n("<qt>Are you sure you want to delete the empty folder "
00953                    "<b>%1</b> and all its subfolders? Those subfolders "
00954                    "might not be empty and their  contents will be "
00955                    "discarded as well.</qt>")
00956               .arg(mFolder->label());
00957       }
00958     } else {
00959       if ( !mFolder->child() || mFolder->child()->isEmpty() ) {
00960         str = i18n("<qt>Are you sure you want to delete the folder "
00961                  "<b>%1</b>, discarding its contents?</qt>")
00962               .arg(mFolder->label());
00963       }
00964       else {
00965         str = i18n("<qt>Are you sure you want to delete the folder "
00966                  "<b>%1</b> and all its subfolders, discarding their "
00967                  "contents?</qt>")
00968             .arg(mFolder->label());
00969       }
00970     }
00971   }
00972 
00973   if (KMessageBox::warningContinueCancel(this, str, i18n("Delete Folder"),
00974                                          i18n("&Delete"))
00975       == KMessageBox::Continue)
00976   {
00977     if (mFolder->hasAccounts())
00978     {
00979       // this folder has an account, so we need to change that to the inbox
00980       KMAccount* acct = 0;
00981       KMAcctFolder* acctFolder = static_cast<KMAcctFolder*>(mFolder);
00982       for ( acct = acctFolder->account(); acct; acct = acctFolder->nextAccount() )
00983       {
00984         acct->setFolder(kmkernel->inboxFolder());
00985         KMessageBox::information(this,
00986             i18n("<qt>The destination folder of the account <b>%1</b> was restored to the inbox.</qt>").arg(acct->name()));
00987       }
00988     }
00989     if (mFolder->folderType() == KMFolderTypeImap)
00990       static_cast<KMFolderImap*>(mFolder)->removeOnServer();
00991     else if (mFolder->folderType() == KMFolderTypeSearch)
00992       kmkernel->searchFolderMgr()->remove(mFolder);
00993     else
00994       kmkernel->folderMgr()->remove(mFolder);
00995   }
00996 }
00997 
00998 //-----------------------------------------------------------------------------
00999 void KMMainWidget::slotMarkAllAsRead()
01000 {
01001   if (!mFolder)
01002     return;
01003   mFolder->markUnreadAsRead();
01004 }
01005 
01006 //-----------------------------------------------------------------------------
01007 void KMMainWidget::slotCompactFolder()
01008 {
01009   int idx = mHeaders->currentItemIndex();
01010   if (mFolder)
01011   {
01012       KCursorSaver busy(KBusyPtr::busy());
01013       mFolder->compact();
01014   }
01015   mHeaders->setCurrentItemByIndex(idx);
01016 }
01017 
01018 
01019 //-----------------------------------------------------------------------------
01020 void KMMainWidget::slotRefreshFolder()
01021 {
01022   if (mFolder)
01023   {
01024     if (mFolder->folderType() == KMFolderTypeImap)
01025     {
01026       KMFolderImap *imap = static_cast<KMFolderImap*>(mFolder);
01027       imap->getAndCheckFolder();
01028     }
01029   }
01030 }
01031 
01032 void KMMainWidget::slotInvalidateIMAPFolders() {
01033   if ( KMessageBox::warningContinueCancel( this,
01034           i18n("Are you sure you want to refresh the IMAP cache?\n"
01035            "This will remove all changes that you have done "
01036            "locally to your IMAP folders."),
01037       i18n("Refresh IMAP Cache"), i18n("&Refresh") ) == KMessageBox::Continue )
01038     kmkernel->acctMgr()->invalidateIMAPFolders();
01039 }
01040 
01041 //-----------------------------------------------------------------------------
01042 void KMMainWidget::slotExpireAll() {
01043   KConfig    *config = KMKernel::config();
01044   int        ret = 0;
01045 
01046   KConfigGroupSaver saver(config, "General");
01047 
01048   if (config->readBoolEntry("warn-before-expire", true)) {
01049     ret = KMessageBox::warningContinueCancel(KMainWindow::memberList->first(),
01050              i18n("Are you sure you want to expire all old messages?"),
01051              i18n("Expire old Messages?"), i18n("Expire"));
01052     if (ret != KMessageBox::Continue) {
01053       return;
01054     }
01055   }
01056 
01057   kmkernel->folderMgr()->expireAllFolders();
01058 }
01059 
01060 //-----------------------------------------------------------------------------
01061 void KMMainWidget::slotCompactAll()
01062 {
01063   KCursorSaver busy(KBusyPtr::busy());
01064   QStringList strList;
01065   QValueList<QGuardedPtr<KMFolder> > folders;
01066   KMFolder *folder;
01067   mFolderTree->createFolderList(&strList, &folders);
01068   for (int i = 0; folders.at(i) != folders.end(); i++)
01069   {
01070     folder = *folders.at(i);
01071     if (!folder || folder->isDir()) continue;
01072     folder->compact();
01073   }
01074 }
01075 
01076 
01077 //-----------------------------------------------------------------------------
01078 void KMMainWidget::slotOverrideHtml()
01079 {
01080   if( mHtmlPref == mFolderHtmlPref ) {
01081     int result = KMessageBox::warningContinueCancel( this,
01082       // the warning text is taken from configuredialog.cpp:
01083       i18n( "Use of HTML in mail will make you more vulnerable to "
01084         "\"spam\" and may increase the likelihood that your system will be "
01085         "compromised by other present and anticipated security exploits." ),
01086       i18n( "Security Warning" ),
01087       i18n( "Continue" ),
01088       "OverrideHtmlWarning", false);
01089     if( result == KMessageBox::Cancel ) {
01090       mPreferHtmlAction->setChecked( false );
01091       return;
01092     }
01093   }
01094   mFolderHtmlPref = !mFolderHtmlPref;
01095   if (mMsgView) {
01096     mMsgView->setHtmlOverride(mFolderHtmlPref);
01097     mMsgView->update( true );
01098   }
01099 }
01100 
01101 //-----------------------------------------------------------------------------
01102 void KMMainWidget::slotOverrideThread()
01103 {
01104   mFolderThreadPref = !mFolderThreadPref;
01105   mHeaders->setNestedOverride(mFolderThreadPref);
01106   mThreadBySubjectAction->setEnabled(mThreadMessagesAction->isChecked());
01107 }
01108 
01109 //-----------------------------------------------------------------------------
01110 void KMMainWidget::slotToggleSubjectThreading()
01111 {
01112   mFolderThreadSubjPref = !mFolderThreadSubjPref;
01113   mHeaders->setSubjectThreading(mFolderThreadSubjPref);
01114 }
01115 
01116 //-----------------------------------------------------------------------------
01117 void KMMainWidget::slotMessageQueuedOrDrafted()
01118 {
01119   if (!kmkernel->folderIsDraftOrOutbox(mFolder))
01120       return;
01121   if (mMsgView)
01122     mMsgView->update(true);
01123 }
01124 
01125 
01126 //-----------------------------------------------------------------------------
01127 void KMMainWidget::slotForwardMsg()
01128 {
01129   KMCommand *command =
01130     new KMForwardCommand( this, *mHeaders->selectedMsgs(), mFolder->identity() );
01131   command->start();
01132 }
01133 
01134 
01135 //-----------------------------------------------------------------------------
01136 void KMMainWidget::slotForwardAttachedMsg()
01137 {
01138   KMCommand *command =
01139     new KMForwardAttachedCommand( this, *mHeaders->selectedMsgs(), mFolder->identity() );
01140   command->start();
01141 }
01142 
01143 
01144 //-----------------------------------------------------------------------------
01145 void KMMainWidget::slotEditMsg()
01146 {
01147   KMCommand *command = new KMEditMsgCommand( this, mHeaders->currentMsg() );
01148   command->start();
01149 }
01150 
01151 
01152 
01153 
01154 
01155 //-----------------------------------------------------------------------------
01156 void KMMainWidget::slotResendMsg()
01157 {
01158   mHeaders->resendMsg();
01159 }
01160 
01161 
01162 //-----------------------------------------------------------------------------
01163 void KMMainWidget::slotTrashMsg()
01164 {
01165   mHeaders->deleteMsg();
01166   updateMessageActions();
01167 }
01168 
01169 //-----------------------------------------------------------------------------
01170 void KMMainWidget::slotDeleteMsg()
01171 {
01172   mHeaders->moveMsgToFolder(0);
01173   updateMessageActions();
01174 }
01175 
01176 
01177 //-----------------------------------------------------------------------------
01178 void KMMainWidget::slotReplyToMsg()
01179 {
01180   QString text = mMsgView? mMsgView->copyText() : "";
01181   KMCommand *command = new KMReplyToCommand( this, mHeaders->currentMsg(), text );
01182   command->start();
01183 }
01184 
01185 
01186 //-----------------------------------------------------------------------------
01187 void KMMainWidget::slotReplyAuthorToMsg()
01188 {
01189   QString text = mMsgView? mMsgView->copyText() : "";
01190   KMCommand *command = new KMReplyAuthorCommand( this, mHeaders->currentMsg(), text );
01191   command->start();
01192 }
01193 
01194 
01195 //-----------------------------------------------------------------------------
01196 void KMMainWidget::slotReplyAllToMsg()
01197 {
01198   QString text = mMsgView? mMsgView->copyText() : "";
01199   KMCommand *command = new KMReplyToAllCommand( this, mHeaders->currentMsg(), text );
01200   command->start();
01201 }
01202 
01203 
01204 //-----------------------------------------------------------------------------
01205 void KMMainWidget::slotRedirectMsg()
01206 {
01207   KMCommand *command = new KMRedirectCommand( this, mHeaders->currentMsg() );
01208   command->start();
01209 }
01210 
01211 
01212 //-----------------------------------------------------------------------------
01213 void KMMainWidget::slotBounceMsg()
01214 {
01215   KMCommand *command = new KMBounceCommand( this, mHeaders->currentMsg() );
01216   command->start();
01217 }
01218 
01219 
01220 //-----------------------------------------------------------------------------
01221 void KMMainWidget::slotReplyListToMsg()
01222 {
01223 
01224   QString text = mMsgView? mMsgView->copyText() : "";
01225   KMCommand *command = new KMReplyListCommand( this, mHeaders->currentMsg(),
01226                            text );
01227   command->start();
01228 }
01229 
01230 //-----------------------------------------------------------------------------
01231 void KMMainWidget::slotNoQuoteReplyToMsg()
01232 {
01233   KMCommand *command = new KMNoQuoteReplyToCommand( this, mHeaders->currentMsg() );
01234   command->start();
01235 }
01236 
01237 //-----------------------------------------------------------------------------
01238 void KMMainWidget::slotSubjectFilter()
01239 {
01240   KMMessage *msg = mHeaders->currentMsg();
01241   if (!msg)
01242     return;
01243 
01244   KMCommand *command = new KMFilterCommand( "Subject", msg->subject() );
01245   command->start();
01246 }
01247 
01248 //-----------------------------------------------------------------------------
01249 void KMMainWidget::slotMailingListFilter()
01250 {
01251   KMMessage *msg = mHeaders->currentMsg();
01252   if (!msg)
01253     return;
01254 
01255   KMCommand *command = new KMMailingListFilterCommand( this, msg );
01256   command->start();
01257 }
01258 
01259 //-----------------------------------------------------------------------------
01260 void KMMainWidget::slotFromFilter()
01261 {
01262   KMMessage *msg = mHeaders->currentMsg();
01263   if (!msg)
01264     return;
01265 
01266   AddrSpecList al = msg->extractAddrSpecs( "From" );
01267   if ( al.empty() )
01268     return;
01269   KMCommand *command = new KMFilterCommand( "From",  al.front().asString() );
01270   command->start();
01271 }
01272 
01273 //-----------------------------------------------------------------------------
01274 void KMMainWidget::slotToFilter()
01275 {
01276   KMMessage *msg = mHeaders->currentMsg();
01277   if (!msg)
01278     return;
01279 
01280   KMCommand *command = new KMFilterCommand( "To",  msg->to() );
01281   command->start();
01282 }
01283 
01284 //-----------------------------------------------------------------------------
01285 void KMMainWidget::updateListFilterAction()
01286 {
01287   //Proxy the mListFilterAction to update the action text
01288   QCString name;
01289   QString value;
01290   QString lname = KMMLInfo::name( mHeaders->currentMsg(), name, value );
01291   mListFilterAction->setText( i18n("Filter on Mailing-List...") );
01292   if ( lname.isNull() )
01293     mListFilterAction->setEnabled( false );
01294   else {
01295     mListFilterAction->setEnabled( true );
01296     mListFilterAction->setText( i18n( "Filter on Mailing-List %1..." ).arg( lname ) );
01297   }
01298 }
01299 
01300 
01301 //-----------------------------------------------------------------------------
01302 void KMMainWidget::slotUndo()
01303 {
01304     mHeaders->undo();
01305     updateMessageActions();
01306 }
01307 
01308 //-----------------------------------------------------------------------------
01309 void KMMainWidget::slotToggleUnread()
01310 {
01311   mFolderTree->toggleColumn(KMFolderTree::unread);
01312 }
01313 
01314 //-----------------------------------------------------------------------------
01315 void KMMainWidget::slotToggleTotalColumn()
01316 {
01317   mFolderTree->toggleColumn(KMFolderTree::total, true);
01318 }
01319 
01320 //-----------------------------------------------------------------------------
01321 void KMMainWidget::slotMoveMsg()
01322 {
01323   KMFolderSelDlg dlg(this,i18n("Move Message to Folder"));
01324   KMFolder* dest;
01325 
01326   if (!dlg.exec()) return;
01327   if (!(dest = dlg.folder())) return;
01328 
01329   mHeaders->moveMsgToFolder(dest);
01330 }
01331 
01332 //-----------------------------------------------------------------------------
01333 void KMMainWidget::slotMoveMsgToFolder( KMFolder *dest)
01334 {
01335   mHeaders->moveMsgToFolder(dest);
01336 }
01337 
01338 //-----------------------------------------------------------------------------
01339 void KMMainWidget::slotCopyMsgToFolder( KMFolder *dest)
01340 {
01341   mHeaders->copyMsgToFolder(dest);
01342 }
01343 
01344 //-----------------------------------------------------------------------------
01345 void KMMainWidget::slotApplyFilters()
01346 {
01347   mHeaders->applyFiltersOnMsg();
01348 }
01349 
01350 //-----------------------------------------------------------------------------
01351 void KMMainWidget::slotEditVacation()
01352 {
01353   if ( mVacation )
01354     return;
01355 
01356   mVacation = new Vacation( this );
01357   if ( mVacation->isUsable() ) {
01358     connect( mVacation, SIGNAL(result(bool)), mVacation, SLOT(deleteLater()) );
01359   } else {
01360     QString msg = i18n("KMail's Out of Office Reply functionality relies on "
01361                       "server-side filtering. You have not yet configured an "
01362                       "IMAP server for this.\n"
01363                       "You can do this on the \"Filtering\" tab of the IMAP "
01364                       "account configuration.");
01365     KMessageBox::sorry( this, msg, i18n("No Server-Side Filtering Configured") );
01366 
01367     delete mVacation; // QGuardedPtr sets itself to 0!
01368   }
01369 }
01370 
01371 //-----------------------------------------------------------------------------
01372 void KMMainWidget::slotCopyMsg()
01373 {
01374   KMFolderSelDlg dlg(this,i18n("Copy Message to Folder"));
01375   KMFolder* dest;
01376 
01377   if (!dlg.exec()) return;
01378   if (!(dest = dlg.folder())) return;
01379 
01380   mHeaders->copyMsgToFolder(dest);
01381 }
01382 
01383 //-----------------------------------------------------------------------------
01384 void KMMainWidget::slotPrintMsg()
01385 {
01386   bool htmlOverride = mMsgView ? mMsgView->htmlOverride() : false;
01387   KMCommand *command = new KMPrintCommand( this, mHeaders->currentMsg(),
01388       htmlOverride );
01389   command->start();
01390 }
01391 
01392 //-----------------------------------------------------------------------------
01393 void KMMainWidget::slotConfigChanged()
01394 {
01395   readConfig();
01396 }
01397 
01398 //-----------------------------------------------------------------------------
01399 void KMMainWidget::slotSaveMsg()
01400 {
01401   KMMessage *msg = mHeaders->currentMsg();
01402   if (!msg)
01403     return;
01404   KMSaveMsgCommand *saveCommand = new KMSaveMsgCommand( this,
01405     *mHeaders->selectedMsgs() );
01406 
01407   if (saveCommand->url().isEmpty())
01408     delete saveCommand;
01409   else
01410     saveCommand->start();
01411 }
01412 
01413 //-----------------------------------------------------------------------------
01414 void KMMainWidget::slotSaveAttachments()
01415 {
01416   KMMessage *msg = mHeaders->currentMsg();
01417   if (!msg)
01418     return;
01419   KMSaveAttachmentsCommand *saveCommand = new KMSaveAttachmentsCommand( this,
01420                                                                         *mHeaders->selectedMsgs() );
01421   saveCommand->start();
01422 }
01423 
01424 
01425 //-----------------------------------------------------------------------------
01426 void KMMainWidget::slotSendQueued()
01427 {
01428   kmkernel->msgSender()->sendQueued();
01429 }
01430 
01431 
01432 //-----------------------------------------------------------------------------
01433 void KMMainWidget::slotViewChange()
01434 {
01435   if(mBodyPartsMenu->isItemChecked(mBodyPartsMenu->idAt(0)))
01436   {
01437     mBodyPartsMenu->setItemChecked(mBodyPartsMenu->idAt(0),FALSE);
01438     mBodyPartsMenu->setItemChecked(mBodyPartsMenu->idAt(1),TRUE);
01439   }
01440   else if(mBodyPartsMenu->isItemChecked(mBodyPartsMenu->idAt(1)))
01441   {
01442     mBodyPartsMenu->setItemChecked(mBodyPartsMenu->idAt(1),FALSE);
01443     mBodyPartsMenu->setItemChecked(mBodyPartsMenu->idAt(0),TRUE);
01444   }
01445 
01446   //mMsgView->setInline(!mMsgView->isInline());
01447 }
01448 
01449 
01450 void KMMainWidget::slotFancyHeaders() {
01451   mMsgView->setHeaderStyleAndStrategy( HeaderStyle::fancy(),
01452                        HeaderStrategy::rich() );
01453 }
01454 
01455 void KMMainWidget::slotBriefHeaders() {
01456   mMsgView->setHeaderStyleAndStrategy( HeaderStyle::brief(),
01457                        HeaderStrategy::brief() );
01458 }
01459 
01460 void KMMainWidget::slotStandardHeaders() {
01461   mMsgView->setHeaderStyleAndStrategy( HeaderStyle::plain(),
01462                        HeaderStrategy::standard());
01463 }
01464 
01465 void KMMainWidget::slotLongHeaders() {
01466   mMsgView->setHeaderStyleAndStrategy( HeaderStyle::plain(),
01467                        HeaderStrategy::rich() );
01468 }
01469 
01470 void KMMainWidget::slotAllHeaders() {
01471   mMsgView->setHeaderStyleAndStrategy( HeaderStyle::plain(),
01472                        HeaderStrategy::all() );
01473 }
01474 
01475 void KMMainWidget::slotCycleHeaderStyles() {
01476   const HeaderStrategy * strategy = mMsgView->headerStrategy();
01477   const HeaderStyle * style = mMsgView->headerStyle();
01478 
01479   const char * actionName = 0;
01480   if ( style == HeaderStyle::fancy() ) {
01481     slotBriefHeaders();
01482     actionName = "view_headers_brief";
01483   } else if ( style == HeaderStyle::brief() ) {
01484     slotStandardHeaders();
01485     actionName = "view_headers_standard";
01486   } else if ( style == HeaderStyle::plain() ) {
01487     if ( strategy == HeaderStrategy::standard() ) {
01488       slotLongHeaders();
01489       actionName = "view_headers_long";
01490     } else if ( strategy == HeaderStrategy::rich() ) {
01491       slotAllHeaders();
01492       actionName = "view_headers_all";
01493     } else if ( strategy == HeaderStrategy::all() ) {
01494       slotFancyHeaders();
01495       actionName = "view_headers_fancy";
01496     }
01497   }
01498 
01499   if ( actionName )
01500     static_cast<KRadioAction*>( actionCollection()->action( actionName ) )->setChecked( true );
01501 }
01502 
01503 
01504 void KMMainWidget::slotIconicAttachments() {
01505   mMsgView->setAttachmentStrategy( AttachmentStrategy::iconic() );
01506 }
01507 
01508 void KMMainWidget::slotSmartAttachments() {
01509   mMsgView->setAttachmentStrategy( AttachmentStrategy::smart() );
01510 }
01511 
01512 void KMMainWidget::slotInlineAttachments() {
01513   mMsgView->setAttachmentStrategy( AttachmentStrategy::inlined() );
01514 }
01515 
01516 void KMMainWidget::slotHideAttachments() {
01517   mMsgView->setAttachmentStrategy( AttachmentStrategy::hidden() );
01518 }
01519 
01520 void KMMainWidget::slotCycleAttachmentStrategy() {
01521   mMsgView->setAttachmentStrategy( mMsgView->attachmentStrategy()->next() );
01522   KRadioAction * action = actionForAttachmentStrategy( mMsgView->attachmentStrategy() );
01523   assert( action );
01524   action->setChecked( true );
01525 }
01526 
01527 void KMMainWidget::folderSelected(KMFolder* aFolder)
01528 {
01529     folderSelected( aFolder, false );
01530 }
01531 
01532 KMLittleProgressDlg* KMMainWidget::progressDialog() const
01533 {
01534     return mLittleProgress;
01535 }
01536 
01537 void KMMainWidget::folderSelectedUnread(KMFolder* aFolder)
01538 {
01539     mHeaders->blockSignals( true );
01540     folderSelected( aFolder, true );
01541     QListViewItem *item = mHeaders->firstChild();
01542     while (item && item->itemAbove())
01543     item = item->itemAbove();
01544     mHeaders->setCurrentItem( item );
01545     mHeaders->nextUnreadMessage(true);
01546     mHeaders->blockSignals( false );
01547     mHeaders->highlightMessage( mHeaders->currentItem() );
01548     slotChangeCaption(mFolderTree->currentItem());
01549 }
01550 
01551 //-----------------------------------------------------------------------------
01552 void KMMainWidget::folderSelected(KMFolder* aFolder, bool jumpToUnread)
01553 {
01554   if( aFolder && mFolder == aFolder )
01555     return;
01556 
01557   KCursorSaver busy(KBusyPtr::busy());
01558 
01559   if (mMsgView)
01560     mMsgView->clear(true);
01561 
01562   if( !mFolder ) {
01563     if (mMsgView) {
01564       mMsgView->enableMsgDisplay();
01565       mMsgView->clear(true);
01566     }
01567     if( mHeaders )
01568       mHeaders->show();
01569   }
01570 
01571   if (mFolder && mFolder->needsCompacting() && (mFolder->folderType() == KMFolderTypeImap))
01572   {
01573     KMFolderImap *imap = static_cast<KMFolderImap*>(mFolder);
01574     if (imap->autoExpunge())
01575       imap->expungeFolder(imap, TRUE);
01576   }
01577   writeFolderConfig();
01578   if ( mFolder ) {
01579      disconnect( mFolder, SIGNAL( changed() ),
01580            this, SLOT( updateMarkAsReadAction() ) );
01581      disconnect( mFolder, SIGNAL( msgHeaderChanged( KMFolder*, int ) ),
01582            this, SLOT( updateMarkAsReadAction() ) );
01583      disconnect( mFolder, SIGNAL( msgAdded( int ) ),
01584            this, SLOT( updateMarkAsReadAction() ) );
01585      disconnect( mFolder, SIGNAL( msgRemoved( KMFolder * ) ),
01586            this, SLOT( updateMarkAsReadAction() ) );
01587 
01588   }
01589   mFolder = (KMFolder*)aFolder;
01590   if ( mFolder ) { // == 0 -> pointing to toplevel ("Welcome to KMail") folder
01591   connect( mFolder, SIGNAL( changed() ),
01592            this, SLOT( updateMarkAsReadAction() ) );
01593   connect( mFolder, SIGNAL( msgHeaderChanged( KMFolder*, int ) ),
01594            this, SLOT( updateMarkAsReadAction() ) );
01595   connect( mFolder, SIGNAL( msgAdded( int ) ),
01596            this, SLOT( updateMarkAsReadAction() ) );
01597   connect( mFolder, SIGNAL( msgRemoved(KMFolder *) ),
01598            this, SLOT( updateMarkAsReadAction() ) );
01599   }
01600 
01601   readFolderConfig();
01602   if (mMsgView)
01603     mMsgView->setHtmlOverride(mFolderHtmlPref);
01604   mHeaders->setFolder( mFolder, jumpToUnread );
01605   updateMessageActions();
01606   updateFolderMenu();
01607   if (!aFolder)
01608     slotIntro();
01609 }
01610 
01611 //-----------------------------------------------------------------------------
01612 void KMMainWidget::slotMsgSelected(KMMessage *msg)
01613 {
01614   if ( msg && msg->parent() && !msg->isComplete() )
01615   {
01616     if ( msg->transferInProgress() )
01617       return;
01618     mMsgView->clear();
01619     if ( mJob )
01620       disconnect( mJob, 0, this, 0 );
01621     mJob = msg->parent()->createJob( msg, FolderJob::tGetMessage, 0,
01622           "STRUCTURE", mMsgView->attachmentStrategy() );
01623     connect(mJob, SIGNAL(messageRetrieved(KMMessage*)),
01624             SLOT(slotUpdateImapMessage(KMMessage*)));
01625     mJob->start();
01626   } else {
01627     mMsgView->setMsg(msg);
01628   }
01629   // reset HTML override to the folder setting
01630   mMsgView->setHtmlOverride(mFolderHtmlPref);
01631 }
01632 
01633 //-----------------------------------------------------------------------------
01634 void KMMainWidget::slotMsgChanged()
01635 {
01636   mHeaders->msgChanged();
01637 }
01638 
01639 //-----------------------------------------------------------------------------
01640 void KMMainWidget::slotSelectFolder(KMFolder* folder)
01641 {
01642   QListViewItem* item = mFolderTree->indexOfFolder(folder);
01643   if (item)
01644     mFolderTree->doFolderSelected( item );
01645 }
01646 
01647 //-----------------------------------------------------------------------------
01648 void KMMainWidget::slotSelectMessage(KMMessage* msg)
01649 {
01650   int idx = mFolder->find(msg);
01651   if (idx != -1) {
01652     mHeaders->setCurrentMsg(idx);
01653     if (mMsgView)
01654       mMsgView->setMsg(msg);
01655   }
01656 }
01657 
01658 //-----------------------------------------------------------------------------
01659 void KMMainWidget::slotReplaceMsgByUnencryptedVersion()
01660 {
01661   kdDebug(5006) << "KMMainWidget::slotReplaceMsgByUnencryptedVersion()" << endl;
01662   KMMessage* oldMsg = mHeaders->currentMsg();
01663   if( oldMsg ) {
01664     kdDebug(5006) << "KMMainWidget  -  old message found" << endl;
01665     if( oldMsg->hasUnencryptedMsg() ) {
01666       kdDebug(5006) << "KMMainWidget  -  extra unencrypted message found" << endl;
01667       KMMessage* newMsg = oldMsg->unencryptedMsg();
01668       // adjust the message id
01669       {
01670         QString msgId( oldMsg->msgId() );
01671         QString prefix("DecryptedMsg.");
01672         int oldIdx = msgId.find(prefix, 0, false);
01673         if( -1 == oldIdx ) {
01674           int leftAngle = msgId.findRev( '<' );
01675           msgId = msgId.insert( (-1 == leftAngle) ? 0 : ++leftAngle, prefix );
01676         }
01677         else {
01678           // toggle between "DecryptedMsg." and "DeCryptedMsg."
01679           // to avoid same message id
01680           QCharRef c = msgId[ oldIdx+2 ];
01681           if( 'C' == c )
01682             c = 'c';
01683           else
01684             c = 'C';
01685         }
01686         newMsg->setMsgId( msgId );
01687         mMsgView->setIdOfLastViewedMessage( msgId );
01688       }
01689       const QString newMsgIdMD5( newMsg->msgIdMD5() );
01690       // insert the unencrypted message
01691       kdDebug(5006) << "KMMainWidget  -  copying unencrypted message to same folder" << endl;
01692       mHeaders->copyMsgToFolder(mFolder, newMsg);
01693       // delete the encrypted message - this will also delete newMsg
01694       kdDebug(5006) << "KMMainWidget  -  deleting encrypted message" << endl;
01695       mHeaders->deleteMsg();
01696       kdDebug(5006) << "KMMainWidget  -  updating message actions" << endl;
01697       updateMessageActions();
01698 
01699       // find and select and show the new message
01700       int idx = mHeaders->currentItemIndex();
01701       if( -1 != idx ) {
01702         mHeaders->setCurrentMsg( idx );
01703         mMsgView->setMsg( mHeaders->currentMsg() );
01704       } else {
01705         kdDebug(5006) << "KMMainWidget  -  SORRY, could not store unencrypted message!" << endl;
01706       }
01707 
01708       kdDebug(5006) << "KMMainWidget  -  done." << endl;
01709     } else
01710       kdDebug(5006) << "KMMainWidget  -  NO EXTRA UNENCRYPTED MESSAGE FOUND" << endl;
01711   } else
01712     kdDebug(5006) << "KMMainWidget  -  PANIC: NO OLD MESSAGE FOUND" << endl;
01713 }
01714 
01715 
01716 
01717 //-----------------------------------------------------------------------------
01718 void KMMainWidget::slotUpdateImapMessage(KMMessage *msg)
01719 {
01720   if (msg && ((KMMsgBase*)msg)->isMessage()) {
01721     // don't update if we have since left the folder
01722     if ( mFolder &&
01723        ( mFolder == msg->parent()
01724       || mFolder->folderType() == KMFolderTypeSearch ) )
01725     {
01726       mMsgView->setMsg(msg, TRUE);
01727     } else {
01728       kdDebug( 5006 ) <<  "KMMainWidget::slotUpdateImapMessage - ignoring update for already left folder" << endl;
01729     }
01730   }  else {
01731     // force an update of the folder
01732     if ( mFolder && mFolder->folderType() == KMFolderTypeImap )
01733       static_cast<KMFolderImap*>(mFolder)->getFolder(true);
01734   }
01735 }
01736 
01737 //-----------------------------------------------------------------------------
01738 void KMMainWidget::slotSetMsgStatusNew()
01739 {
01740   mHeaders->setMsgStatus(KMMsgStatusNew);
01741 }
01742 
01743 //-----------------------------------------------------------------------------
01744 void KMMainWidget::slotSetMsgStatusUnread()
01745 {
01746   mHeaders->setMsgStatus(KMMsgStatusUnread);
01747 }
01748 
01749 //-----------------------------------------------------------------------------
01750 void KMMainWidget::slotSetMsgStatusRead()
01751 {
01752   mHeaders->setMsgStatus(KMMsgStatusRead);
01753 }
01754 
01755 //-----------------------------------------------------------------------------
01756 void KMMainWidget::slotSetMsgStatusFlag()
01757 {
01758   mHeaders->setMsgStatus(KMMsgStatusFlag, true);
01759 }
01760 
01761 //-----------------------------------------------------------------------------
01762 void KMMainWidget::slotSetMsgStatusSpam()
01763 {
01764   mHeaders->setMsgStatus( KMMsgStatusSpam, true );
01765 }
01766 
01767 //-----------------------------------------------------------------------------
01768 void KMMainWidget::slotSetMsgStatusHam()
01769 {
01770   mHeaders->setMsgStatus( KMMsgStatusHam, true );
01771 }
01772 
01773 //-----------------------------------------------------------------------------
01774 void KMMainWidget::slotSetMsgStatusReplied()
01775 {
01776   mHeaders->setMsgStatus(KMMsgStatusReplied, true);
01777 }
01778 
01779 //-----------------------------------------------------------------------------
01780 void KMMainWidget::slotSetMsgStatusForwarded()
01781 {
01782   mHeaders->setMsgStatus(KMMsgStatusForwarded, true);
01783 }
01784 
01785 //-----------------------------------------------------------------------------
01786 void KMMainWidget::slotSetMsgStatusQueued()
01787 {
01788   mHeaders->setMsgStatus(KMMsgStatusQueued, true);
01789 }
01790 
01791 //-----------------------------------------------------------------------------
01792 void KMMainWidget::slotSetMsgStatusSent()
01793 {
01794   mHeaders->setMsgStatus(KMMsgStatusSent, true);
01795 }
01796 
01797 //-----------------------------------------------------------------------------
01798 void KMMainWidget::slotSetThreadStatusNew()
01799 {
01800   mHeaders->setThreadStatus(KMMsgStatusNew);
01801 }
01802 
01803 //-----------------------------------------------------------------------------
01804 void KMMainWidget::slotSetThreadStatusUnread()
01805 {
01806   mHeaders->setThreadStatus(KMMsgStatusUnread);
01807 }
01808 
01809 //-----------------------------------------------------------------------------
01810 void KMMainWidget::slotSetThreadStatusFlag()
01811 {
01812   mHeaders->setThreadStatus(KMMsgStatusFlag, true);
01813 }
01814 
01815 //-----------------------------------------------------------------------------
01816 void KMMainWidget::slotSetThreadStatusRead()
01817 {
01818   mHeaders->setThreadStatus(KMMsgStatusRead);
01819 }
01820 
01821 //-----------------------------------------------------------------------------
01822 void KMMainWidget::slotSetThreadStatusReplied()
01823 {
01824   mHeaders->setThreadStatus(KMMsgStatusReplied, true);
01825 }
01826 
01827 //-----------------------------------------------------------------------------
01828 void KMMainWidget::slotSetThreadStatusForwarded()
01829 {
01830   mHeaders->setThreadStatus(KMMsgStatusForwarded, true);
01831 }
01832 
01833 //-----------------------------------------------------------------------------
01834 void KMMainWidget::slotSetThreadStatusQueued()
01835 {
01836   mHeaders->setThreadStatus(KMMsgStatusQueued, true);
01837 }
01838 
01839 //-----------------------------------------------------------------------------
01840 void KMMainWidget::slotSetThreadStatusSent()
01841 {
01842   mHeaders->setThreadStatus(KMMsgStatusSent, true);
01843 }
01844 
01845 //-----------------------------------------------------------------------------
01846 void KMMainWidget::slotSetThreadStatusWatched()
01847 {
01848   mHeaders->setThreadStatus(KMMsgStatusWatched, true);
01849   if (mWatchThreadAction->isChecked()) {
01850     mIgnoreThreadAction->setChecked(false);
01851   }
01852 }
01853 
01854 //-----------------------------------------------------------------------------
01855 void KMMainWidget::slotSetThreadStatusIgnored()
01856 {
01857   mHeaders->setThreadStatus(KMMsgStatusIgnored, true);
01858   if (mIgnoreThreadAction->isChecked()) {
01859     mWatchThreadAction->setChecked(false);
01860   }
01861 }
01862 
01863 //-----------------------------------------------------------------------------
01864 void KMMainWidget::slotSetThreadStatusSpam()
01865 {
01866   mHeaders->setThreadStatus( KMMsgStatusSpam, true );
01867 }
01868 
01869 //-----------------------------------------------------------------------------
01870 void KMMainWidget::slotSetThreadStatusHam()
01871 {
01872   mHeaders->setThreadStatus( KMMsgStatusHam, true );
01873 }
01874 
01875 //-----------------------------------------------------------------------------
01876 void KMMainWidget::slotNextMessage()       { mHeaders->nextMessage(); }
01877 void KMMainWidget::slotNextUnreadMessage()
01878 {
01879   if ( !mHeaders->nextUnreadMessage() )
01880     if ( mHeaders->loopOnGotoUnread() == LoopInAllFolders )
01881       mFolderTree->nextUnreadFolder(true);
01882 }
01883 void KMMainWidget::slotNextImportantMessage() {
01884   //mHeaders->nextImportantMessage();
01885 }
01886 void KMMainWidget::slotPrevMessage()       { mHeaders->prevMessage(); }
01887 void KMMainWidget::slotPrevUnreadMessage()
01888 {
01889   if ( !mHeaders->prevUnreadMessage() )
01890     if ( mHeaders->loopOnGotoUnread() == LoopInAllFolders )
01891       mFolderTree->prevUnreadFolder();
01892 }
01893 void KMMainWidget::slotPrevImportantMessage() {
01894   //mHeaders->prevImportantMessage();
01895 }
01896 
01897 //-----------------------------------------------------------------------------
01898 //called from headers. Message must not be deleted on close
01899 void KMMainWidget::slotMsgActivated(KMMessage *msg)
01900 {
01901   if (msg->parent() && !msg->isComplete())
01902   {
01903     FolderJob *job = msg->parent()->createJob(msg);
01904     connect(job, SIGNAL(messageRetrieved(KMMessage*)),
01905             SLOT(slotMsgActivated(KMMessage*)));
01906     job->start();
01907     return;
01908   }
01909 
01910   if (kmkernel->folderIsDraftOrOutbox(mFolder))
01911   {
01912     slotEditMsg();
01913     return;
01914   }
01915 
01916   assert( msg != 0 );
01917   KMReaderMainWin *win = new KMReaderMainWin( mFolderHtmlPref );
01918   KMMessage *newMessage = new KMMessage(*msg);
01919   newMessage->setParent( msg->parent() );
01920   newMessage->setMsgSerNum( msg->getMsgSerNum() );
01921   newMessage->setReadyToShow( true );
01922   win->showMsg( mCodec, newMessage );
01923   win->resize( 550, 600 );
01924   win->show();
01925 }
01926 
01927 //-----------------------------------------------------------------------------
01928 void KMMainWidget::slotMarkAll()
01929 {
01930   mHeaders->selectAll( TRUE );
01931 }
01932 
01933 //-----------------------------------------------------------------------------
01934 void KMMainWidget::slotMsgPopup(KMMessage&, const KURL &aUrl, const QPoint& aPoint)
01935 {
01936   KPopupMenu * menu = new KPopupMenu;
01937   updateMessageMenu();
01938   mUrlCurrent = aUrl;
01939 
01940   if (!aUrl.isEmpty())
01941   {
01942     if (aUrl.protocol() == "mailto")
01943     {
01944       // popup on a mailto URL
01945       mMsgView->mailToComposeAction()->plug( menu );
01946       if ( mMsgCurrent ) {
01947     mMsgView->mailToReplyAction()->plug( menu );
01948     mMsgView->mailToForwardAction()->plug( menu );
01949         menu->insertSeparator();
01950       }
01951       mMsgView->addAddrBookAction()->plug( menu );
01952       mMsgView->openAddrBookAction()->plug( menu );
01953       mMsgView->copyAction()->plug( menu );
01954     } else {
01955       // popup on a not-mailto URL
01956       mMsgView->urlOpenAction()->plug( menu );
01957       mMsgView->urlSaveAsAction()->plug( menu );
01958       mMsgView->copyURLAction()->plug( menu );
01959       mMsgView->addBookmarksAction()->plug( menu );
01960     }
01961   }
01962   else
01963   {
01964     // popup somewhere else (i.e., not a URL) on the message
01965 
01966     if (!mHeaders->currentMsg()) // no messages
01967     {
01968       delete menu;
01969       return;
01970     }
01971 
01972     bool out_folder = kmkernel->folderIsDraftOrOutbox(mFolder);
01973     if ( out_folder ) {
01974       mEditAction->plug(menu);
01975     }
01976     else {
01977       mReplyAction->plug(menu);
01978       mReplyAllAction->plug(menu);
01979       mReplyAuthorAction->plug( menu );
01980       mReplyListAction->plug( menu );
01981       mForwardActionMenu->plug(menu);
01982       mBounceAction->plug(menu);
01983     }
01984     menu->insertSeparator();
01985     if ( !out_folder ) {
01986       //   mFilterMenu()->plug( menu );
01987       mStatusMenu->plug( menu );
01988       mThreadStatusMenu->plug( menu );
01989     }
01990 
01991     mCopyActionMenu->plug( menu );
01992     mMoveActionMenu->plug( menu );
01993 
01994     menu->insertSeparator();
01995     mWatchThreadAction->plug( menu );
01996     mIgnoreThreadAction->plug( menu );
01997 
01998     menu->insertSeparator();
01999 
02000     // these two only make sense if there is a reader window.
02001     // I guess. Not sure about view source ;). Till
02002     if (mMsgView) {
02003       toggleFixFontAction()->plug(menu);
02004       viewSourceAction()->plug(menu);
02005     }
02006 
02007     menu->insertSeparator();
02008     mPrintAction->plug( menu );
02009     mSaveAsAction->plug( menu );
02010     mSaveAttachmentsAction->plug( menu );
02011     menu->insertSeparator();
02012     mTrashAction->plug( menu );
02013     mDeleteAction->plug( menu );
02014   }
02015   KAcceleratorManager::manage(menu);
02016   menu->exec(aPoint, 0);
02017   delete menu;
02018 }
02019 
02020 //-----------------------------------------------------------------------------
02021 void KMMainWidget::getAccountMenu()
02022 {
02023   QStringList actList;
02024 
02025   mActMenu->clear();
02026   actList = kmkernel->acctMgr()->getAccounts(false);
02027   QStringList::Iterator it;
02028   int id = 0;
02029   for(it = actList.begin(); it != actList.end() ; ++it, id++)
02030     mActMenu->insertItem((*it).replace("&", "&&"), id);
02031 }
02032 
02033 // little helper function
02034 KRadioAction * KMMainWidget::actionForHeaderStyle( const HeaderStyle * style, const HeaderStrategy * strategy ) {
02035   const char * actionName = 0;
02036   if ( style == HeaderStyle::fancy() )
02037     actionName = "view_headers_fancy";
02038   else if ( style == HeaderStyle::brief() )
02039     actionName = "view_headers_brief";
02040   else if ( style == HeaderStyle::plain() ) {
02041     if ( strategy == HeaderStrategy::standard() )
02042       actionName = "view_headers_standard";
02043     else if ( strategy == HeaderStrategy::rich() )
02044       actionName = "view_headers_long";
02045     else if ( strategy == HeaderStrategy::all() )
02046       actionName = "view_headers_all";
02047   }
02048   if ( actionName )
02049     return static_cast<KRadioAction*>(actionCollection()->action(actionName));
02050   else
02051     return 0;
02052 }
02053 
02054 KRadioAction * KMMainWidget::actionForAttachmentStrategy( const AttachmentStrategy * as ) {
02055   const char * actionName = 0;
02056   if ( as == AttachmentStrategy::iconic() )
02057     actionName = "view_attachments_as_icons";
02058   else if ( as == AttachmentStrategy::smart() )
02059     actionName = "view_attachments_smart";
02060   else if ( as == AttachmentStrategy::inlined() )
02061     actionName = "view_attachments_inline";
02062   else if ( as == AttachmentStrategy::hidden() )
02063     actionName = "view_attachments_hide";
02064 
02065   if ( actionName )
02066     return static_cast<KRadioAction*>(actionCollection()->action(actionName));
02067   else
02068     return 0;
02069 }
02070 
02071 
02072 //-----------------------------------------------------------------------------
02073 void KMMainWidget::setupActions()
02074 {
02075   //----- File Menu
02076   (void) new KAction( i18n("New &Window"), "window_new", 0,
02077               this, SLOT(slotNewMailReader()),
02078               actionCollection(), "new_mail_client" );
02079 
02080   mSaveAsAction = new KAction( i18n("Save &As..."), "filesave",
02081     KStdAccel::shortcut(KStdAccel::Save),
02082     this, SLOT(slotSaveMsg()), actionCollection(), "file_save_as" );
02083 
02084   (void) new KAction( i18n("&Compact All Folders"), 0,
02085               this, SLOT(slotCompactAll()),
02086               actionCollection(), "compact_all_folders" );
02087 
02088   (void) new KAction( i18n("&Expire All Folders"), 0,
02089               this, SLOT(slotExpireAll()),
02090               actionCollection(), "expire_all_folders" );
02091 
02092   (void) new KAction( i18n("&Refresh Local IMAP Cache"), "refresh",
02093               this, SLOT(slotInvalidateIMAPFolders()),
02094               actionCollection(), "file_invalidate_imap_cache" );
02095 
02096   (void) new KAction( i18n("Empty &Trash"), 0,
02097               KMKernel::self(), SLOT(slotEmptyTrash()),
02098               actionCollection(), "empty_trash" );
02099 
02100   (void) new KAction( i18n("Check &Mail"), "mail_get", CTRL+Key_L,
02101               this, SLOT(slotCheckMail()),
02102               actionCollection(), "check_mail" );
02103 
02104   KActionMenu *actActionMenu = new
02105     KActionMenu( i18n("Check Mail &In"), "mail_get", actionCollection(),
02106                     "check_mail_in" );
02107   actActionMenu->setDelayed(true); //needed for checking "all accounts"
02108 
02109   connect(actActionMenu,SIGNAL(activated()),this,SLOT(slotCheckMail()));
02110 
02111   mActMenu = actActionMenu->popupMenu();
02112   connect(mActMenu,SIGNAL(activated(int)),this,SLOT(slotCheckOneAccount(int)));
02113   connect(mActMenu,SIGNAL(aboutToShow()),this,SLOT(getAccountMenu()));
02114 
02115   (void) new KAction( i18n("&Send Queued Messages"), "mail_send", 0, this,
02116              SLOT(slotSendQueued()), actionCollection(), "send_queued");
02117   KAction *act;
02118   //----- Tools menu
02119   if (parent()->inherits("KMMainWin")) {
02120     act =  new KAction( i18n("&Address Book..."), "contents", 0, this,
02121             SLOT(slotAddrBook()), actionCollection(), "addressbook" );
02122     if (KStandardDirs::findExe("kaddressbook").isEmpty()) act->setEnabled(false);
02123   }
02124 
02125   act = new KAction( i18n("&Import Messages..."), "fileopen", 0, this,
02126              SLOT(slotImport()), actionCollection(), "import" );
02127   if (KStandardDirs::findExe("kmailcvt").isEmpty()) act->setEnabled(false);
02128 
02129 #if 0 // ### (marc) this isn't ready for prime-time yet - reactivate post 3.2
02130   (void) new KAction( i18n("Edit \"Out of Office\" Replies..."),
02131               "configure", 0, this, SLOT(slotEditVacation()),
02132               actionCollection(), "tools_edit_vacation" );
02133 #endif
02134 
02135   //----- Edit Menu
02136   mTrashAction = new KAction( KGuiItem( i18n("&Move to Trash"), "edittrash",
02137                                        i18n("Move message to trashcan") ),
02138                              Key_Delete, this, SLOT(slotTrashMsg()),
02139                              actionCollection(), "move_to_trash" );
02140 
02141   mDeleteAction = new KAction( i18n("&Delete"), "editdelete", SHIFT+Key_Delete, this,
02142                               SLOT(slotDeleteMsg()), actionCollection(), "delete" );
02143 
02144   (void) new KAction( i18n("&Find Messages..."), "mail_find", Key_S, this,
02145               SLOT(slotSearch()), actionCollection(), "search_messages" );
02146 
02147   mFindInMessageAction = new KAction( i18n("&Find in Message..."), "find", KStdAccel::shortcut(KStdAccel::Find), this,
02148               SLOT(slotFind()), actionCollection(), "find_in_messages" );
02149 
02150   (void) new KAction( i18n("Select &All Messages"), KStdAccel::selectAll(), this,
02151               SLOT(slotMarkAll()), actionCollection(), "mark_all_messages" );
02152 
02153   (void) new KAction( i18n("Select Message &Text"),
02154               CTRL+SHIFT+Key_A, mMsgView,
02155               SLOT(selectAll()), actionCollection(), "mark_all_text" );
02156 
02157   //----- Folder Menu
02158   (void) new KAction( i18n("&New Folder..."), "folder_new", 0, this,
02159               SLOT(slotAddFolder()), actionCollection(), "new_folder" );
02160 
02161   mModifyFolderAction = new KAction( i18n("&Properties"), "configure", 0, this,
02162               SLOT(slotModifyFolder()), actionCollection(), "modify" );
02163 
02164   mMarkAllAsReadAction = new KAction( i18n("Mark All Messages as &Read"), "goto", 0, this,
02165               SLOT(slotMarkAllAsRead()), actionCollection(), "mark_all_as_read" );
02166 
02167   mExpireFolderAction = new KAction(i18n("&Expire"), 0, this, SLOT(slotExpireFolder()),
02168                    actionCollection(), "expire");
02169 
02170   mCompactFolderAction = new KAction( i18n("&Compact"), 0, this,
02171               SLOT(slotCompactFolder()), actionCollection(), "compact" );
02172 
02173   mRefreshFolderAction = new KAction( i18n("Check Mail &in this Folder"), "reload", Key_F5 , this,
02174                      SLOT(slotRefreshFolder()), actionCollection(), "refresh_folder" );
02175 
02176   mEmptyFolderAction = new KAction( i18n("&Move All Messages to Trash"),
02177                                    "edittrash", 0, this,
02178               SLOT(slotEmptyFolder()), actionCollection(), "empty" );
02179 
02180   mRemoveFolderAction = new KAction( i18n("&Delete Folder"), "editdelete", 0, this,
02181               SLOT(slotRemoveFolder()), actionCollection(), "delete_folder" );
02182 
02183   mPreferHtmlAction = new KToggleAction( i18n("Prefer &HTML to Plain Text"), 0, this,
02184               SLOT(slotOverrideHtml()), actionCollection(), "prefer_html" );
02185 
02186   mThreadMessagesAction = new KToggleAction( i18n("&Thread Messages"), 0, this,
02187               SLOT(slotOverrideThread()), actionCollection(), "thread_messages" );
02188 
02189   mThreadBySubjectAction = new KToggleAction( i18n("Thread Messages also by &Subject"), 0, this,
02190               SLOT(slotToggleSubjectThreading()), actionCollection(), "thread_messages_by_subject" );
02191 
02192 
02193   //----- Message Menu
02194   (void) new KAction( i18n("&New Message..."), "mail_new", KStdAccel::shortcut(KStdAccel::New), this,
02195               SLOT(slotCompose()), actionCollection(), "new_message" );
02196 
02197   (void) new KAction( i18n("New Message t&o Mailing-List..."), "mail_post_to", 0, this,
02198               SLOT(slotPostToML()), actionCollection(), "post_message" );
02199 
02200   mForwardActionMenu = new KActionMenu( i18n("Message->","&Forward"),
02201                     "mail_forward", actionCollection(),
02202                     "message_forward" );
02203   connect( mForwardActionMenu, SIGNAL(activated()), this,
02204        SLOT(slotForwardMsg()) );
02205 
02206   mForwardAttachedAction = new KAction( i18n("Message->Forward->","As &Attachment..."),
02207                        "mail_forward", Key_F, this,
02208                     SLOT(slotForwardAttachedMsg()), actionCollection(),
02209                     "message_forward_as_attachment" );
02210   mForwardActionMenu->insert( forwardAttachedAction() );
02211   mForwardAction = new KAction( i18n("&Inline..."), "mail_forward",
02212                 SHIFT+Key_F, this, SLOT(slotForwardMsg()),
02213                 actionCollection(), "message_forward_inline" );
02214 
02215   mForwardActionMenu->insert( forwardAction() );
02216 
02217   mSendAgainAction = new KAction( i18n("Send A&gain..."), 0, this,
02218               SLOT(slotResendMsg()), actionCollection(), "send_again" );
02219 
02220   mReplyActionMenu = new KActionMenu( i18n("Message->","&Reply"),
02221                                       "mail_reply", actionCollection(),
02222                                       "message_reply_menu" );
02223   connect( mReplyActionMenu, SIGNAL(activated()), this,
02224        SLOT(slotReplyToMsg()) );
02225 
02226   mReplyAction = new KAction( i18n("&Reply..."), "mail_reply", Key_R, this,
02227                   SLOT(slotReplyToMsg()), actionCollection(), "reply" );
02228   mReplyActionMenu->insert( mReplyAction );
02229 
02230   mReplyAuthorAction = new KAction( i18n("Reply to A&uthor..."), "mail_reply",
02231                                     SHIFT+Key_A, this,
02232                                     SLOT(slotReplyAuthorToMsg()),
02233                                     actionCollection(), "reply_author" );
02234   mReplyActionMenu->insert( mReplyAuthorAction );
02235 
02236   mReplyAllAction = new KAction( i18n("Reply to &All..."), "mail_replyall",
02237                  Key_A, this, SLOT(slotReplyAllToMsg()),
02238                  actionCollection(), "reply_all" );
02239   mReplyActionMenu->insert( mReplyAllAction );
02240 
02241   mReplyListAction = new KAction( i18n("Reply to Mailing-&List..."),
02242                   "mail_replylist", Key_L, this,
02243                   SLOT(slotReplyListToMsg()), actionCollection(),
02244                   "reply_list" );
02245   mReplyActionMenu->insert( mReplyListAction );
02246 
02247   mRedirectAction = new KAction( i18n("Message->Forward->","&Redirect..."),
02248                  Key_E, this, SLOT(slotRedirectMsg()),
02249                  actionCollection(), "message_forward_redirect" );
02250   mForwardActionMenu->insert( redirectAction() );
02251 
02252   mNoQuoteReplyAction = new KAction( i18n("Reply Without &Quote..."), SHIFT+Key_R,
02253     this, SLOT(slotNoQuoteReplyToMsg()), actionCollection(), "noquotereply" );
02254 
02255   //---- Bounce action
02256   mBounceAction = new KAction( i18n("&Bounce..."), 0, this,
02257                   SLOT(slotBounceMsg()), actionCollection(), "bounce" );
02258 
02259   //----- Create filter actions
02260   mFilterMenu = new KActionMenu( i18n("&Create Filter"), actionCollection(), "create_filter" );
02261 
02262   mSubjectFilterAction = new KAction( i18n("Filter on &Subject..."), 0, this,
02263                       SLOT(slotSubjectFilter()),
02264                       actionCollection(), "subject_filter");
02265   mFilterMenu->insert( mSubjectFilterAction );
02266 
02267   mFromFilterAction = new KAction( i18n("Filter on &From..."), 0, this,
02268                    SLOT(slotFromFilter()),
02269                    actionCollection(), "from_filter");
02270   mFilterMenu->insert( mFromFilterAction );
02271 
02272   mToFilterAction = new KAction( i18n("Filter on &To..."), 0, this,
02273                  SLOT(slotToFilter()),
02274                  actionCollection(), "to_filter");
02275   mFilterMenu->insert( mToFilterAction );
02276 
02277   mListFilterAction = new KAction( i18n("Filter on Mailing-&List..."), 0, this,
02278                                    SLOT(slotMailingListFilter()), actionCollection(),
02279                                    "mlist_filter");
02280   mFilterMenu->insert( mListFilterAction );
02281 
02282   mPrintAction = KStdAction::print (this, SLOT(slotPrintMsg()), actionCollection());
02283 
02284   //----- Message-Encoding Submenu
02285   mEncoding = new KSelectAction( i18n( "&Set Encoding" ), "charset", 0, this,
02286               SLOT( slotSetEncoding() ), actionCollection(), "encoding" );
02287   QStringList encodings = KMMsgBase::supportedEncodings(FALSE);
02288   encodings.prepend( i18n( "Auto" ) );
02289   mEncoding->setItems( encodings );
02290   mEncoding->setCurrentItem(0);
02291 
02292   QStringList::Iterator it;
02293   int i = 0;
02294   for( it = encodings.begin(); it != encodings.end(); ++it)
02295   {
02296     if ( KGlobal::charsets()->encodingForName(*it ) == QString(mEncodingStr) )
02297     {
02298       mEncoding->setCurrentItem( i );
02299       break;
02300     }
02301     i++;
02302   }
02303 
02304   mEditAction = new KAction( i18n("&Edit Message"), "edit", Key_T, this,
02305                             SLOT(slotEditMsg()), actionCollection(), "edit" );
02306 
02307   //----- "Mark Message" submenu
02308   mStatusMenu = new KActionMenu ( i18n( "Mar&k Message" ),
02309                                  actionCollection(), "set_status" );
02310 
02311   mStatusMenu->insert(new KAction(KGuiItem(i18n("Mark Message as &New"), "kmmsgnew",
02312                                           i18n("Mark selected messages as new")),
02313                                  0, this, SLOT(slotSetMsgStatusNew()),
02314                                  actionCollection(), "status_new" ));
02315 
02316   mStatusMenu->insert(new KAction(KGuiItem(i18n("Mark Message as &Unread"), "kmmsgunseen",
02317                                           i18n("Mark selected messages as unread")),
02318                                  0, this, SLOT(slotSetMsgStatusUnread()),
02319                                  actionCollection(), "status_unread"));
02320 
02321   mStatusMenu->insert(new KAction(KGuiItem(i18n("Mark Message as &Read"), "kmmsgread",
02322                                           i18n("Mark selected messages as read")),
02323                                  0, this, SLOT(slotSetMsgStatusRead()),
02324                                  actionCollection(), "status_read"));
02325 
02326   // -------- Toggle Actions
02327   mToggleRepliedAction = new KToggleAction(i18n("Mark Message as Re&plied"), "kmmsgreplied",
02328                                  0, this, SLOT(slotSetMsgStatusReplied()),
02329                                  actionCollection(), "status_replied");
02330 
02331   mStatusMenu->insert( mToggleRepliedAction );
02332   mToggleForwardedAction = new KToggleAction(i18n("Mark Message as &Forwarded"), "kmmsgforwarded",
02333                                  0, this, SLOT(slotSetMsgStatusForwarded()),
02334                                  actionCollection(), "status_forwarded");
02335   mStatusMenu->insert( mToggleForwardedAction );
02336 
02337   mToggleQueuedAction = new KToggleAction(i18n("Mark Message as &Queued"), "kmmsgqueued",
02338                                  0, this, SLOT(slotSetMsgStatusQueued()),
02339                                  actionCollection(), "status_queued");
02340   mStatusMenu->insert( mToggleQueuedAction );
02341 
02342   mToggleSentAction = new KToggleAction(i18n("Mark Message as &Sent"), "kmmsgsent",
02343                                  0, this, SLOT(slotSetMsgStatusSent()),
02344                                  actionCollection(), "status_sent");
02345   mStatusMenu->insert( mToggleSentAction );
02346 
02347   mToggleFlagAction = new KToggleAction(i18n("Mark Message as &Important"), "kmmsgflag",
02348                                  0, this, SLOT(slotSetMsgStatusFlag()),
02349                                  actionCollection(), "status_flag");
02350   mStatusMenu->insert( mToggleFlagAction );
02351 
02352   mMarkAsSpamAction = new KAction(i18n("Mark Message as Spa&m"), "mark_as_spam",
02353                                  0, this, SLOT(slotSetMsgStatusSpam()),
02354                                  actionCollection(), "status_spam");
02355   mStatusMenu->insert( mMarkAsSpamAction );
02356 
02357   mMarkAsHamAction = new KAction(i18n("Mark Message as &Ham"), "mark_as_ham",
02358                                  0, this, SLOT(slotSetMsgStatusHam()),
02359                                  actionCollection(), "status_ham");
02360   mStatusMenu->insert( mMarkAsHamAction );
02361 
02362   //----- "Mark Thread" submenu
02363   mThreadStatusMenu = new KActionMenu ( i18n( "Mark &Thread" ),
02364                                        actionCollection(), "thread_status" );
02365 
02366   mMarkThreadAsNewAction = new KAction(KGuiItem(i18n("Mark Thread as &New"), "kmmsgnew",
02367                                                i18n("Mark all messages in the selected thread as new")),
02368                                                0, this, SLOT(slotSetThreadStatusNew()),
02369                                                actionCollection(), "thread_new");
02370   mThreadStatusMenu->insert( mMarkThreadAsNewAction );
02371 
02372   mMarkThreadAsUnreadAction = new KAction(KGuiItem(i18n("Mark Thread as &Unread"), "kmmsgunseen",
02373                                                 i18n("Mark all messages in the selected thread as unread")),
02374                                                 0, this, SLOT(slotSetThreadStatusUnread()),
02375                                                 actionCollection(), "thread_unread");
02376   mThreadStatusMenu->insert( mMarkThreadAsUnreadAction );
02377 
02378   mMarkThreadAsReadAction = new KAction(KGuiItem(i18n("Mark Thread as &Read"), "kmmsgread",
02379                                                 i18n("Mark all messages in the selected thread as read")),
02380                                                 0, this, SLOT(slotSetThreadStatusRead()),
02381                                                 actionCollection(), "thread_read");
02382   mThreadStatusMenu->insert( mMarkThreadAsReadAction );
02383 
02384   //----- "Mark Thread" toggle actions
02385   mToggleThreadRepliedAction = new KToggleAction(i18n("Mark Thread as R&eplied"), "kmmsgreplied",
02386                                        0, this, SLOT(slotSetThreadStatusReplied()),
02387                                        actionCollection(), "thread_replied");
02388   mThreadStatusMenu->insert( mToggleThreadRepliedAction );
02389   mToggleThreadForwardedAction = new KToggleAction(i18n("Mark Thread as &Forwarded"), "kmmsgforwarded",
02390                                        0, this, SLOT(slotSetThreadStatusForwarded()),
02391                                        actionCollection(), "thread_forwarded");
02392   mThreadStatusMenu->insert( mToggleThreadForwardedAction );
02393   mToggleThreadQueuedAction = new KToggleAction(i18n("Mark Thread as &Queued"), "kmmsgqueued",
02394                                        0, this, SLOT(slotSetThreadStatusQueued()),
02395                                        actionCollection(), "thread_queued");
02396   mThreadStatusMenu->insert( mToggleThreadQueuedAction );
02397   mToggleThreadSentAction = new KToggleAction(i18n("Mark Thread as &Sent"), "kmmsgsent",
02398                                        0, this, SLOT(slotSetThreadStatusSent()),
02399                                        actionCollection(), "thread_sent");
02400   mThreadStatusMenu->insert( mToggleThreadSentAction );
02401   mToggleThreadFlagAction = new KToggleAction(i18n("Mark Thread as &Important"), "kmmsgflag",
02402                                        0, this, SLOT(slotSetThreadStatusFlag()),
02403                                        actionCollection(), "thread_flag");
02404   mThreadStatusMenu->insert( mToggleThreadFlagAction );
02405   //------- "Watch and ignore thread" actions
02406   mWatchThreadAction = new KToggleAction(i18n("&Watch Thread"), "kmmsgwatched",
02407                                        0, this, SLOT(slotSetThreadStatusWatched()),
02408                                        actionCollection(), "thread_watched");
02409 
02410   mIgnoreThreadAction = new KToggleAction(i18n("&Ignore Thread"), "kmmsgignored",
02411                                        0, this, SLOT(slotSetThreadStatusIgnored()),
02412                                        actionCollection(), "thread_ignored");
02413 
02414   //------- "Ham and spam thread" actions
02415   mMarkThreadAsSpamAction = new KAction(i18n("Mark Thread as S&pam"), "mark_as_spam",
02416                                        0, this, SLOT(slotSetThreadStatusSpam()),
02417                                        actionCollection(), "thread_spam");
02418   mThreadStatusMenu->insert( mMarkThreadAsSpamAction );
02419 
02420   mMarkThreadAsHamAction = new KAction(i18n("Mark Thread as &Ham"), "mark_as_ham",
02421                                        0, this, SLOT(slotSetThreadStatusHam()),
02422                                        actionCollection(), "thread_ham");
02423   mThreadStatusMenu->insert( mMarkThreadAsHamAction );
02424 
02425 
02426   mSaveAttachmentsAction = new KAction( i18n("Save A&ttachments..."), "attach",
02427                                 0, this, SLOT(slotSaveAttachments()),
02428                                 actionCollection(), "file_save_attachments" );
02429 
02430   mMoveActionMenu = new KActionMenu( i18n("&Move To" ),
02431                                     actionCollection(), "move_to" );
02432 
02433   mCopyActionMenu = new KActionMenu( i18n("&Copy To" ),
02434                                     actionCollection(), "copy_to" );
02435 
02436   mApplyFiltersAction = new KAction( i18n("Appl&y Filters"), "filter",
02437                     CTRL+Key_J, this,
02438                     SLOT(slotApplyFilters()),
02439                     actionCollection(), "apply_filters" );
02440 
02441   mApplyFilterActionsMenu = new KActionMenu( i18n("A&pply Filter Actions" ),
02442                         actionCollection(),
02443                         "apply_filter_actions" );
02444 
02445   //----- View Menu
02446   KRadioAction * raction = 0;
02447 
02448   // "Headers" submenu:
02449   KActionMenu * headerMenu =
02450     new KActionMenu( i18n("View->", "&Headers"),
02451              actionCollection(), "view_headers" );
02452   headerMenu->setToolTip( i18n("Choose display style of message headers") );
02453 
02454   if (mMsgView) {
02455     connect( headerMenu, SIGNAL(activated()), SLOT(slotCycleHeaderStyles()) );
02456 
02457     raction = new KRadioAction( i18n("View->headers->", "&Fancy Headers"), 0, this,
02458         SLOT(slotFancyHeaders()),
02459         actionCollection(), "view_headers_fancy" );
02460     raction->setToolTip( i18n("Show the list of headers in a fancy format") );
02461     raction->setExclusiveGroup( "view_headers_group" );
02462     headerMenu->insert( raction );
02463 
02464     raction = new KRadioAction( i18n("View->headers->", "&Brief Headers"), 0, this,
02465         SLOT(slotBriefHeaders()),
02466         actionCollection(), "view_headers_brief" );
02467     raction->setToolTip( i18n("Show brief list of message headers") );
02468     raction->setExclusiveGroup( "view_headers_group" );
02469     headerMenu->insert( raction );
02470 
02471     raction = new KRadioAction( i18n("View->headers->", "&Standard Headers"), 0, this,
02472         SLOT(slotStandardHeaders()),
02473         actionCollection(), "view_headers_standard" );
02474     raction->setToolTip( i18n("Show standard list of message headers") );
02475     raction->setExclusiveGroup( "view_headers_group" );
02476     headerMenu->insert( raction );
02477 
02478     raction = new KRadioAction( i18n("View->headers->", "&Long Headers"), 0, this,
02479         SLOT(slotLongHeaders()),
02480         actionCollection(), "view_headers_long" );
02481     raction->setToolTip( i18n("Show long list of message headers") );
02482     raction->setExclusiveGroup( "view_headers_group" );
02483     headerMenu->insert( raction );
02484 
02485     raction = new KRadioAction( i18n("View->headers->", "&All Headers"), 0, this,
02486         SLOT(slotAllHeaders()),
02487         actionCollection(), "view_headers_all" );
02488     raction->setToolTip( i18n("Show all message headers") );
02489     raction->setExclusiveGroup( "view_headers_group" );
02490     headerMenu->insert( raction );
02491 
02492     // check the right one:
02493     raction = actionForHeaderStyle( mMsgView->headerStyle(), mMsgView->headerStrategy() );
02494     if ( raction )
02495       raction->setChecked( true );
02496 
02497     // "Attachments" submenu:
02498     KActionMenu * attachmentMenu =
02499       new KActionMenu( i18n("View->", "&Attachments"),
02500           actionCollection(), "view_attachments" );
02501     connect( attachmentMenu, SIGNAL(activated()),
02502         SLOT(slotCycleAttachmentStrategy()) );
02503 
02504     attachmentMenu->setToolTip( i18n("Choose display style of attachments") );
02505 
02506     raction = new KRadioAction( i18n("View->attachments->", "&As Icons"), 0, this,
02507         SLOT(slotIconicAttachments()),
02508         actionCollection(), "view_attachments_as_icons" );
02509     raction->setToolTip( i18n("Show all attachments as icons. Click to see them.") );
02510     raction->setExclusiveGroup( "view_attachments_group" );
02511     attachmentMenu->insert( raction );
02512 
02513     raction = new KRadioAction( i18n("View->attachments->", "&Smart"), 0, this,
02514         SLOT(slotSmartAttachments()),
02515         actionCollection(), "view_attachments_smart" );
02516     raction->setToolTip( i18n("Show attachments as suggested by sender.") );
02517     raction->setExclusiveGroup( "view_attachments_group" );
02518     attachmentMenu->insert( raction );
02519 
02520     raction = new KRadioAction( i18n("View->attachments->", "&Inline"), 0, this,
02521         SLOT(slotInlineAttachments()),
02522         actionCollection(), "view_attachments_inline" );
02523     raction->setToolTip( i18n("Show all attachments inline (if possible)") );
02524     raction->setExclusiveGroup( "view_attachments_group" );
02525     attachmentMenu->insert( raction );
02526 
02527     raction = new KRadioAction( i18n("View->attachments->", "&Hide"), 0, this,
02528         SLOT(slotHideAttachments()),
02529         actionCollection(), "view_attachments_hide" );
02530     raction->setToolTip( i18n("Don't show attachments in the message viewer") );
02531     raction->setExclusiveGroup( "view_attachments_group" );
02532     attachmentMenu->insert( raction );
02533 
02534     // check the right one:
02535     raction = actionForAttachmentStrategy( mMsgView->attachmentStrategy() );
02536     if ( raction )
02537       raction->setChecked( true );
02538   }
02539   // Unread Submenu
02540   KActionMenu * unreadMenu =
02541     new KActionMenu( i18n("View->", "&Unread Count"),
02542              actionCollection(), "view_unread" );
02543   unreadMenu->setToolTip( i18n("Choose how to display the count of unread messages") );
02544 
02545   mUnreadColumnToggle = new KRadioAction( i18n("View->Unread Count", "View in &Separate Column"), 0, this,
02546                    SLOT(slotToggleUnread()),
02547                    actionCollection(), "view_unread_column" );
02548   mUnreadColumnToggle->setExclusiveGroup( "view_unread_group" );
02549   mUnreadColumnToggle->setChecked( mFolderTree->isUnreadActive() );
02550   unreadMenu->insert( mUnreadColumnToggle );
02551 
02552   mUnreadTextToggle = new KRadioAction( i18n("View->Unread Count", "View After &Folder Name"), 0, this,
02553                    SLOT(slotToggleUnread()),
02554                    actionCollection(), "view_unread_text" );
02555   mUnreadTextToggle->setExclusiveGroup( "view_unread_group" );
02556   mUnreadTextToggle->setChecked( !mFolderTree->isUnreadActive() );
02557   unreadMenu->insert( mUnreadTextToggle );
02558 
02559   // toggle for total column
02560   mTotalColumnToggle = new KToggleAction( i18n("View->", "&Total Column"), 0, this,
02561                    SLOT(slotToggleTotalColumn()),
02562                    actionCollection(), "view_columns_total" );
02563   mTotalColumnToggle->setToolTip( i18n("Toggle display of column showing the "
02564                                       "total number of messages in folders.") );
02565   mTotalColumnToggle->setChecked( mFolderTree->isTotalActive() );
02566 
02567   (void)new KAction( KGuiItem( i18n("View->","&Expand Thread"), QString::null,
02568                    i18n("Expand the current thread") ),
02569              Key_Period, this,
02570              SLOT(slotExpandThread()),
02571              actionCollection(), "expand_thread" );
02572 
02573   (void)new KAction( KGuiItem( i18n("View->","&Collapse Thread"), QString::null,
02574                    i18n("Collapse the current thread") ),
02575              Key_Comma, this,
02576              SLOT(slotCollapseThread()),
02577              actionCollection(), "collapse_thread" );
02578 
02579   (void)new KAction( KGuiItem( i18n("View->","Ex&pand All Threads"), QString::null,
02580                    i18n("Expand all threads in the current folder") ),
02581              CTRL+Key_Period, this,
02582              SLOT(slotExpandAllThreads()),
02583              actionCollection(), "expand_all_threads" );
02584 
02585   (void)new KAction( KGuiItem( i18n("View->","C&ollapse All Threads"), QString::null,
02586                    i18n("Collapse all threads in the current folder") ),
02587              CTRL+Key_Comma, this,
02588              SLOT(slotCollapseAllThreads()),
02589              actionCollection(), "collapse_all_threads" );
02590 
02591 
02592   //----- Go Menu
02593   new KAction( KGuiItem( i18n("&Next Message"), QString::null,
02594                          i18n("Go to the next message") ),
02595                          "N;Right", this, SLOT(slotNextMessage()),
02596                          actionCollection(), "go_next_message" );
02597 
02598   new KAction( KGuiItem( i18n("Next &Unread Message"),
02599                          QApplication::reverseLayout() ? "previous" : "next",
02600                          i18n("Go to the next unread message") ),
02601                          Key_Plus, this, SLOT(slotNextUnreadMessage()),
02602                          actionCollection(), "go_next_unread_message" );
02603 
02604   /* ### needs better support from folders:
02605   new KAction( KGuiItem( i18n("Next &Important Message"), QString::null,
02606                          i18n("Go to the next important message") ),
02607                          0, this, SLOT(slotNextImportantMessage()),
02608                          actionCollection(), "go_next_important_message" );
02609   */
02610 
02611   new KAction( KGuiItem( i18n("&Previous Message"), QString::null,
02612                          i18n("Go to the previous message") ),
02613                          "P;Left", this, SLOT(slotPrevMessage()),
02614                          actionCollection(), "go_prev_message" );
02615 
02616   new KAction( KGuiItem( i18n("Previous Unread &Message"),
02617                          QApplication::reverseLayout() ? "next" : "previous",
02618                          i18n("Go to the previous unread message") ),
02619                          Key_Minus, this, SLOT(slotPrevUnreadMessage()),
02620                          actionCollection(), "go_prev_unread_message" );
02621 
02622   /* needs better support from folders:
02623   new KAction( KGuiItem( i18n("Previous I&mportant Message"), QString::null,
02624                          i18n("Go to the previous important message") ),
02625                          0, this, SLOT(slotPrevImportantMessage()),
02626                          actionCollection(), "go_prev_important_message" );
02627   */
02628 
02629   new KAction( KGuiItem( i18n("Next Unread &Folder"), QString::null,
02630                          i18n("Go to the next folder with unread messages") ),
02631                          CTRL+Key_Plus, this, SLOT(slotNextUnreadFolder()),
02632                          actionCollection(), "go_next_unread_folder" );
02633 
02634   new KAction( KGuiItem( i18n("Previous Unread F&older"), QString::null,
02635                          i18n("Go to the previous folder with unread messages") ),
02636                          CTRL+Key_Minus, this, SLOT(slotPrevUnreadFolder()),
02637                          actionCollection(), "go_prev_unread_folder" );
02638 
02639   new KAction( KGuiItem( i18n("Go->","Next Unread &Text"), QString::null,
02640                          i18n("Go to the next unread text"),
02641                          i18n("Scroll down current message. "
02642                               "If at end of current message, "
02643                               "go to next unread message.") ),
02644                          Key_Space, this, SLOT(slotReadOn()),
02645                          actionCollection(), "go_next_unread_text" );
02646 
02647   //----- Settings Menu
02648   (void) new KAction( i18n("Configure &Filters..."), 0, this,
02649               SLOT(slotFilter()), actionCollection(), "filter" );
02650   (void) new KAction( i18n("Configure &POP Filters..."), 0, this,
02651               SLOT(slotPopFilter()), actionCollection(), "popFilter" );
02652 
02653   (void) new KAction( KGuiItem( i18n("KMail &Introduction"), 0,
02654                 i18n("Display KMail's Welcome Page") ),
02655               0, this, SLOT(slotIntro()),
02656               actionCollection(), "help_kmail_welcomepage" );
02657 
02658   // ----- Standard Actions
02659 //  KStdAction::configureNotifications(this, SLOT(slotEditNotifications()), actionCollection());
02660   (void) new KAction( i18n("Configure &Notifications..."),
02661               "knotify", 0, this,
02662               SLOT(slotEditNotifications()), actionCollection(),
02663               "kmail_configure_notifications" );
02664 //  KStdAction::preferences(this, SLOT(slotSettings()), actionCollection());
02665   (void) new KAction( i18n("&Configure KMail..."),
02666               "configure", 0, kmkernel,
02667                       SLOT(slotShowConfigurationDialog()), actionCollection(),
02668                       "kmail_configure_kmail" );
02669 
02670   KStdAction::undo(this, SLOT(slotUndo()), actionCollection(), "kmail_undo");
02671 //  (void) new KAction( i18n("&Undo"), 0, this,
02672 //            SLOT(slotUndo()), actionCollection(),
02673 //            "kmail_undo" );
02674 
02675   KStdAction::copy( messageView(), SLOT(slotCopySelectedText()), actionCollection(), "kmail_copy");
02676 //  (void) new KAction( i18n("&Copy"), CTRL+Key_C, mMsgView,
02677 //            SLOT(slotCopySelectedText()), actionCollection(),
02678 //            "kmail_copy" );
02679 
02680   KStdAction::tipOfDay( this, SLOT( slotShowTip() ), actionCollection() );
02681 
02682   menutimer = new QTimer( this, "menutimer" );
02683   connect( menutimer, SIGNAL( timeout() ), SLOT( updateMessageActions() ) );
02684   connect( kmkernel->undoStack(),
02685            SIGNAL( undoStackChanged() ), this, SLOT( slotUpdateUndo() ));
02686 
02687   initializeFilterActions();
02688   updateMessageActions();
02689 }
02690 
02691 //-----------------------------------------------------------------------------
02692 void KMMainWidget::setupStatusBar()
02693 {
02694   //we setup the progress dialog here, because its the one widget
02695   //we want to export to the part.
02696   KMainWindow *mainWin = dynamic_cast<KMainWindow*>(topLevelWidget());
02697   KStatusBar *bar =  mainWin ? mainWin->statusBar() : 0;
02698   mLittleProgress = new KMLittleProgressDlg( bar );
02699 
02700   //mLittleProgress->show();
02701   connect( KMBroadcastStatus::instance(), SIGNAL(statusProgressEnable( bool )),
02702            mLittleProgress, SLOT(slotEnable( bool )));
02703   connect( KMBroadcastStatus::instance(),
02704            SIGNAL(statusProgressPercent( unsigned long )),
02705            mLittleProgress,
02706            SLOT(slotJustPercent( unsigned long )));
02707   connect( KMBroadcastStatus::instance(),
02708            SIGNAL(signalUsingSSL( bool )),
02709            mLittleProgress,
02710            SLOT(slotSetSSL(bool)) );
02711   connect( KMBroadcastStatus::instance(), SIGNAL(resetRequested()),
02712            mLittleProgress, SLOT(slotClean()));
02713 }
02714 
02715 
02716 //-----------------------------------------------------------------------------
02717 void KMMainWidget::slotEditNotifications()
02718 {
02719   if(kmkernel->xmlGuiInstance())
02720     KNotifyDialog::configure(this, 0, kmkernel->xmlGuiInstance()->aboutData());
02721   else
02722     KNotifyDialog::configure(this);
02723 }
02724 
02725 void KMMainWidget::slotEditKeys()
02726 {
02727   KKeyDialog::configure( actionCollection(),
02728              true /*allow one-letter shortcuts*/
02729              );
02730 }
02731 
02732 //-----------------------------------------------------------------------------
02733 void KMMainWidget::slotReadOn()
02734 {
02735     if ( !mMsgView )
02736         return;
02737 
02738     if ( !mMsgView->atBottom() ) {
02739         mMsgView->slotJumpDown();
02740         return;
02741     }
02742     slotNextUnreadMessage();
02743 }
02744 
02745 void KMMainWidget::slotNextUnreadFolder() {
02746   if ( !mFolderTree ) return;
02747   mFolderTree->nextUnreadFolder();
02748 }
02749 
02750 void KMMainWidget::slotPrevUnreadFolder() {
02751   if ( !mFolderTree ) return;
02752   mFolderTree->prevUnreadFolder();
02753 }
02754 
02755 void KMMainWidget::slotExpandThread()
02756 {
02757   mHeaders->slotExpandOrCollapseThread( true ); // expand
02758 }
02759 
02760 void KMMainWidget::slotCollapseThread()
02761 {
02762   mHeaders->slotExpandOrCollapseThread( false ); // collapse
02763 }
02764 
02765 void KMMainWidget::slotExpandAllThreads()
02766 {
02767   mHeaders->slotExpandOrCollapseAllThreads( true ); // expand
02768 }
02769 
02770 void KMMainWidget::slotCollapseAllThreads()
02771 {
02772   mHeaders->slotExpandOrCollapseAllThreads( false ); // collapse
02773 }
02774 
02775 
02776 //-----------------------------------------------------------------------------
02777 void KMMainWidget::moveSelectedToFolder( int menuId )
02778 {
02779   if (mMenuToFolder[menuId])
02780     mHeaders->moveMsgToFolder( mMenuToFolder[menuId] );
02781 }
02782 
02783 
02784 //-----------------------------------------------------------------------------
02785 void KMMainWidget::copySelectedToFolder(int menuId )
02786 {
02787   if (mMenuToFolder[menuId])
02788     mHeaders->copyMsgToFolder( mMenuToFolder[menuId] );
02789 }
02790 
02791 
02792 //-----------------------------------------------------------------------------
02793 void KMMainWidget::updateMessageMenu()
02794 {
02795     mMenuToFolder.clear();
02796     KMMenuCommand::folderToPopupMenu( true, this, &mMenuToFolder, mMoveActionMenu->popupMenu() );
02797     KMMenuCommand::folderToPopupMenu( false, this, &mMenuToFolder, mCopyActionMenu->popupMenu() );
02798     updateMessageActions();
02799 }
02800 
02801 void KMMainWidget::startUpdateMessageActionsTimer()
02802 {
02803     menutimer->stop();
02804     menutimer->start( 20, true );
02805 }
02806 
02807 void KMMainWidget::updateMessageActions()
02808 {
02809     int count = 0;
02810     QPtrList<QListViewItem> selectedItems;
02811 
02812     if ( mFolder ) {
02813         for (QListViewItem *item = mHeaders->firstChild(); item; item = item->itemBelow())
02814             if (item->isSelected() )
02815             selectedItems.append(item);
02816         if ( selectedItems.isEmpty() && mFolder->count() ) // there will always be one in mMsgView
02817             count = 1;
02818     else count = selectedItems.count();
02819     }
02820 
02821     updateListFilterAction();
02822 
02823     bool allSelectedInCommonThread = true;
02824     if ( count > 1 && mHeaders->isThreaded() ) {
02825       QListViewItem * curItemParent = mHeaders->currentItem();
02826       while ( curItemParent->parent() )
02827     curItemParent = curItemParent->parent();
02828       for ( QPtrListIterator<QListViewItem> it( selectedItems ) ;
02829         it.current() ; ++ it ) {
02830     QListViewItem * item = *it;
02831     while ( item->parent() )
02832       item = item->parent();
02833     if ( item != curItemParent ) {
02834       allSelectedInCommonThread = false;
02835       break;
02836     }
02837       }
02838     }
02839 
02840     bool mass_actions = count >= 1;
02841     bool thread_actions = mass_actions &&
02842            allSelectedInCommonThread &&
02843            mHeaders->isThreaded();
02844     mStatusMenu->setEnabled( mass_actions );
02845     mThreadStatusMenu->setEnabled( thread_actions );
02846     // these need to be handled individually, the user might have them
02847     // in the toolbar
02848     mWatchThreadAction->setEnabled( thread_actions );
02849     mIgnoreThreadAction->setEnabled( thread_actions );
02850     mMarkThreadAsSpamAction->setEnabled( thread_actions );
02851     mMarkThreadAsHamAction->setEnabled( thread_actions );
02852     mMarkThreadAsNewAction->setEnabled( thread_actions );
02853     mMarkThreadAsReadAction->setEnabled( thread_actions );
02854     mMarkThreadAsUnreadAction->setEnabled( thread_actions );
02855     mToggleThreadRepliedAction->setEnabled( thread_actions );
02856     mToggleThreadForwardedAction->setEnabled( thread_actions );
02857     mToggleThreadQueuedAction->setEnabled( thread_actions );
02858     mToggleThreadSentAction->setEnabled( thread_actions );
02859     mToggleThreadFlagAction->setEnabled( thread_actions );
02860 
02861     if (mFolder && mHeaders && mHeaders->currentMsg()) {
02862       mToggleRepliedAction->setChecked(mHeaders->currentMsg()->isReplied());
02863       mToggleForwardedAction->setChecked(mHeaders->currentMsg()->isForwarded());
02864       mToggleQueuedAction->setChecked(mHeaders->currentMsg()->isQueued());
02865       mToggleSentAction->setChecked(mHeaders->currentMsg()->isSent());
02866       mToggleFlagAction->setChecked(mHeaders->currentMsg()->isFlag());
02867       if (thread_actions) {
02868         mToggleThreadRepliedAction->setChecked(mHeaders->currentMsg()->isReplied());
02869         mToggleThreadForwardedAction->setChecked(mHeaders->currentMsg()->isForwarded());
02870         mToggleThreadQueuedAction->setChecked(mHeaders->currentMsg()->isQueued());
02871         mToggleThreadSentAction->setChecked(mHeaders->currentMsg()->isSent());
02872         mToggleThreadFlagAction->setChecked(mHeaders->currentMsg()->isFlag());
02873         mWatchThreadAction->setChecked( mHeaders->currentMsg()->isWatched());
02874         mIgnoreThreadAction->setChecked( mHeaders->currentMsg()->isIgnored());
02875       }
02876     }
02877 
02878     mMoveActionMenu->setEnabled( mass_actions );
02879     mCopyActionMenu->setEnabled( mass_actions );
02880     mTrashAction->setEnabled( mass_actions );
02881     mDeleteAction->setEnabled( mass_actions );
02882     mFindInMessageAction->setEnabled( mass_actions );
02883     mForwardAction->setEnabled( mass_actions );
02884     mForwardAttachedAction->setEnabled( mass_actions );
02885 
02886     forwardMenu()->setEnabled( mass_actions );
02887 
02888     bool single_actions = count == 1;
02889     mEditAction->setEnabled( single_actions &&
02890     kmkernel->folderIsDraftOrOutbox(mFolder));
02891 
02892     filterMenu()->setEnabled( single_actions );
02893     bounceAction()->setEnabled( single_actions );
02894     replyAction()->setEnabled( single_actions );
02895     noQuoteReplyAction()->setEnabled( single_actions );
02896     replyAuthorAction()->setEnabled( single_actions );
02897     replyAllAction()->setEnabled( single_actions );
02898     replyListAction()->setEnabled( single_actions );
02899     redirectAction()->setEnabled( single_actions );
02900     printAction()->setEnabled( single_actions );
02901     if (mMsgView) {
02902       viewSourceAction()->setEnabled( single_actions );
02903     }
02904 
02905     mSendAgainAction->setEnabled( single_actions &&
02906              ( mHeaders->currentMsg() && mHeaders->currentMsg()->isSent() )
02907           || ( mFolder && kmkernel->folderIsDraftOrOutbox( mFolder ) )
02908           || ( mFolder && kmkernel->folderIsSentMailFolder( mFolder ) )
02909              );
02910     mSaveAsAction->setEnabled( mass_actions );
02911     bool mails = mFolder && mFolder->count();
02912     bool enable_goto_unread = mails || (mHeaders->loopOnGotoUnread() == LoopInAllFolders);
02913     actionCollection()->action( "go_next_message" )->setEnabled( mails );
02914     actionCollection()->action( "go_next_unread_message" )->setEnabled( enable_goto_unread );
02915     actionCollection()->action( "go_prev_message" )->setEnabled( mails );
02916     actionCollection()->action( "go_prev_unread_message" )->setEnabled( enable_goto_unread );
02917     actionCollection()->action( "send_queued" )->setEnabled( kmkernel->outboxFolder()->count() > 0 );
02918     if (action( "edit_undo" ))
02919       action( "edit_undo" )->setEnabled( mHeaders->canUndo() );
02920 
02921     if ( count == 1 ) {
02922       KMMessage *msg;
02923       int aIdx;
02924       if((aIdx = mHeaders->currentItemIndex()) <= -1)
02925         return;
02926       if(!(msg = mFolder->getMsg(aIdx)))
02927         return;
02928 
02929       if (mFolder == kmkernel->outboxFolder())
02930         mEditAction->setEnabled( !msg->transferInProgress() );
02931     }
02932 
02933     mApplyFiltersAction->setEnabled(count);
02934     mApplyFilterActionsMenu->setEnabled(count && (mApplyFilterActionsMenu->popupMenu()->count()>0));
02935 }
02936 
02937 
02938 //-----------------------------------------------------------------------------
02939 void KMMainWidget::statusMsg(const QString& message)
02940 {
02941   KMMainWin *mainKMWin = dynamic_cast<KMMainWin*>(topLevelWidget());
02942   if (mainKMWin)
02943     return mainKMWin->statusMsg( message );
02944 
02945   KMainWindow *mainWin = dynamic_cast<KMainWindow*>(topLevelWidget());
02946   if (mainWin && mainWin->statusBar())
02947     mainWin->statusBar()->message( message );
02948 }
02949 
02950 
02951 // This needs to be updated more often, so it is in its method.
02952 void KMMainWidget::updateMarkAsReadAction()
02953 {
02954   mMarkAllAsReadAction->setEnabled( mFolder && (mFolder->countUnread() > 0) );
02955 }
02956 
02957 //-----------------------------------------------------------------------------
02958 void KMMainWidget::updateFolderMenu()
02959 {
02960   mModifyFolderAction->setEnabled( mFolder ? !mFolder->noContent() : false );
02961   mCompactFolderAction->setEnabled( mFolder ? !mFolder->noContent() : false );
02962   mRefreshFolderAction->setEnabled( mFolder ? !mFolder->noContent()
02963                                             && mFolder->folderType()==KMFolderTypeImap
02964                                             : false );
02965   mEmptyFolderAction->setEnabled( mFolder ? ( !mFolder->noContent()
02966                                              && ( mFolder->count() > 0 ) )
02967                                          : false );
02968   mEmptyFolderAction->setText( (mFolder && kmkernel->folderIsTrash(mFolder))
02969     ? i18n("E&mpty Trash") : i18n("&Move All Messages to Trash") );
02970   mRemoveFolderAction->setEnabled( (mFolder && !mFolder->isSystemFolder()) );
02971   mExpireFolderAction->setEnabled( mFolder && mFolder->isAutoExpire() );
02972   updateMarkAsReadAction();
02973   mPreferHtmlAction->setEnabled( mFolder ? true : false );
02974   mThreadMessagesAction->setEnabled( mFolder ? true : false );
02975 
02976   mPreferHtmlAction->setChecked( mHtmlPref ? !mFolderHtmlPref : mFolderHtmlPref );
02977   mThreadMessagesAction->setChecked(
02978       mThreadPref ? !mFolderThreadPref : mFolderThreadPref );
02979   mThreadBySubjectAction->setEnabled(
02980       mFolder ? ( mThreadMessagesAction->isChecked()) : false );
02981   mThreadBySubjectAction->setChecked( mFolderThreadSubjPref );
02982 }
02983 
02984 
02985 #ifdef MALLOC_DEBUG
02986 static QString fmt(long n) {
02987   char buf[32];
02988 
02989   if(n > 1024*1024*1024)
02990     sprintf(buf, "%0.2f GB", ((double)n)/1024.0/1024.0/1024.0);
02991   else if(n > 1024*1024)
02992     sprintf(buf, "%0.2f MB", ((double)n)/1024.0/1024.0);
02993   else if(n > 1024)
02994     sprintf(buf, "%0.2f KB", ((double)n)/1024.0);
02995   else
02996     sprintf(buf, "%ld Byte", n);
02997   return QString(buf);
02998 }
02999 #endif
03000 
03001 void KMMainWidget::slotMemInfo() {
03002 #ifdef MALLOC_DEBUG
03003   struct mallinfo mi;
03004 
03005   mi = mallinfo();
03006   QString s = QString("\nMALLOC - Info\n\n"
03007               "Number of mmapped regions : %1\n"
03008               "Memory allocated in use   : %2\n"
03009               "Memory allocated, not used: %3\n"
03010               "Memory total allocated    : %4\n"
03011               "Max. freeable memory      : %5\n")
03012     .arg(mi.hblks).arg(fmt(mi.uordblks)).arg(fmt(mi.fordblks))
03013     .arg(fmt(mi.arena)).arg(fmt(mi.keepcost));
03014   KMessageBox::information(0, s, "Malloc information", s);
03015 #endif
03016 }
03017 
03018 
03019 //-----------------------------------------------------------------------------
03020 void KMMainWidget::slotIntro()
03021 {
03022   if ( !mMsgView ) return;
03023 
03024   mMsgView->clear( true );
03025   // hide widgets that are in the way:
03026   if ( mHeaders && mLongFolderList )
03027     mHeaders->hide();
03028 
03029   mMsgView->displayAboutPage();
03030 
03031   mFolder = 0;
03032 }
03033 
03034 void KMMainWidget::slotShowStartupFolder()
03035 {
03036   if (mFolderTree) {
03037     // add the folders
03038     mFolderTree->reload();
03039     // read the config
03040     mFolderTree->readConfig();
03041     // get rid of old-folders
03042     mFolderTree->cleanupConfigFile();
03043   }
03044 
03045   connect( kmkernel->filterMgr(), SIGNAL( filterListUpdated() ),
03046        this, SLOT( initializeFilterActions() ));
03047 
03048   if (kmkernel->firstStart() || kmkernel->previousVersion() != KMAIL_VERSION) {
03049     slotIntro();
03050     return;
03051   }
03052 
03053   KMFolder* startup = 0;
03054   if (!mStartupFolder.isEmpty()) {
03055     // find the startup-folder with this ugly folderMgr switch
03056     startup = kmkernel->folderMgr()->findIdString(mStartupFolder);
03057     if (!startup)
03058       startup = kmkernel->imapFolderMgr()->findIdString(mStartupFolder);
03059     if (!startup)
03060       startup = kmkernel->dimapFolderMgr()->findIdString(mStartupFolder);
03061     if (!startup)
03062       startup = kmkernel->inboxFolder();
03063   } else {
03064     startup = kmkernel->inboxFolder();
03065   }
03066   mFolderTree->doFolderSelected(mFolderTree->indexOfFolder(startup));
03067   mFolderTree->ensureItemVisible(mFolderTree->indexOfFolder(startup));
03068 }
03069 
03070 void KMMainWidget::slotShowTipOnStart()
03071 {
03072   KTipDialog::showTip( this );
03073 }
03074 
03075 void KMMainWidget::slotShowTip()
03076 {
03077   KTipDialog::showTip( this, QString::null, true );
03078 }
03079 
03080 //-----------------------------------------------------------------------------
03081 void KMMainWidget::slotChangeCaption(QListViewItem * i)
03082 {
03083   // set the caption to the current full path
03084   QStringList names;
03085   for ( QListViewItem * item = i ; item ; item = item->parent() )
03086     names.prepend( item->text(0) );
03087   emit captionChangeRequest( names.join( "/" ) );
03088 }
03089 
03090 //-----------------------------------------------------------------------------
03091 void KMMainWidget::removeDuplicates()
03092 {
03093   if (!mFolder)
03094     return;
03095   KMFolder *oFolder = mFolder;
03096   mHeaders->setFolder(0);
03097   QMap< QString, QValueList<int> > idMD5s;
03098   QValueList<int> redundantIds;
03099   QValueList<int>::Iterator kt;
03100   mFolder->open();
03101   for (int i = mFolder->count() - 1; i >= 0; --i) {
03102     QString id = (*mFolder)[i]->msgIdMD5();
03103     if ( !id.isEmpty() ) {
03104       QString subjMD5 = (*mFolder)[i]->strippedSubjectMD5();
03105       int other = -1;
03106       if ( idMD5s.contains(id) )
03107         other = idMD5s[id].first();
03108       else
03109         idMD5s[id].append( i );
03110       if ( other != -1 ) {
03111         QString otherSubjMD5 = (*mFolder)[other]->strippedSubjectMD5();
03112         if (otherSubjMD5 == subjMD5)
03113           idMD5s[id].append( i );
03114       }
03115     }
03116   }
03117   QMap< QString, QValueList<int> >::Iterator it;
03118   for ( it = idMD5s.begin(); it != idMD5s.end() ; ++it ) {
03119     QValueList<int>::Iterator jt;
03120     bool finished = false;
03121     for ( jt = (*it).begin(); jt != (*it).end() && !finished; ++jt )
03122       if (!((*mFolder)[*jt]->isUnread())) {
03123         (*it).remove( jt );
03124         (*it).prepend( *jt );
03125         finished = true;
03126       }
03127     for ( jt = (*it).begin(), ++jt; jt != (*it).end(); ++jt )
03128       redundantIds.append( *jt );
03129   }
03130   qHeapSort( redundantIds );
03131   kt = redundantIds.end();
03132   int numDuplicates = 0;
03133   if (kt != redundantIds.begin()) do {
03134     mFolder->removeMsg( *(--kt) );
03135     ++numDuplicates;
03136   }
03137   while (kt != redundantIds.begin());
03138 
03139   mFolder->close();
03140   mHeaders->setFolder(oFolder);
03141   QString msg;
03142   if ( numDuplicates )
03143     msg = i18n("Removed %n duplicate message.",
03144                "Removed %n duplicate messages.", numDuplicates );
03145     else
03146       msg = i18n("No duplicate messages found.");
03147   KMBroadcastStatus::instance()->setStatusMsg( msg );
03148 }
03149 
03150 
03151 //-----------------------------------------------------------------------------
03152 void KMMainWidget::slotUpdateUndo()
03153 {
03154     if (actionCollection()->action( "edit_undo" ))
03155         actionCollection()->action( "edit_undo" )->setEnabled( mHeaders->canUndo() );
03156 }
03157 
03158 
03159 //-----------------------------------------------------------------------------
03160 void KMMainWidget::initializeFilterActions()
03161 {
03162   QString filterName, normalizedName;
03163   KMMetaFilterActionCommand *filterCommand;
03164   KAction *filterAction;
03165   mFilterActions.clear();
03166   mFilterCommands.clear();
03167   for ( QPtrListIterator<KMFilter> it(*kmkernel->filterMgr()) ;
03168         it.current() ; ++it )
03169     if (!(*it)->isEmpty() && (*it)->configureShortcut()) {
03170       filterName = QString("Filter Action %1").arg((*it)->name());
03171       normalizedName = filterName.replace(" ", "_");
03172       if (action(normalizedName.utf8()))
03173         continue;
03174       filterCommand = new KMMetaFilterActionCommand(*it, mHeaders, this);
03175       mFilterCommands.append(filterCommand);
03176       QString as = i18n("Filter Action %1").arg((*it)->name());
03177       QString icon = (*it)->icon();
03178       if ( icon.isEmpty() )
03179         icon = "gear";
03180       filterAction = new KAction(as, icon, 0, filterCommand,
03181                                  SLOT(start()), actionCollection(),
03182                                  normalizedName.local8Bit());
03183       mFilterActions.append(filterAction);
03184     }
03185 
03186   mApplyFilterActionsMenu->popupMenu()->clear();
03187   plugFilterActions(mApplyFilterActionsMenu->popupMenu());
03188 }
03189 
03190 
03191 //-----------------------------------------------------------------------------
03192 void KMMainWidget::plugFilterActions(QPopupMenu *menu)
03193 {
03194   for (QPtrListIterator<KMFilter> it(*kmkernel->filterMgr()); it.current(); ++it)
03195       if (!(*it)->isEmpty() && (*it)->configureShortcut()) {
03196       QString filterName = QString("Filter Action %1").arg((*it)->name());
03197       filterName = filterName.replace(" ","_");
03198       KAction *filterAction = action(filterName.local8Bit());
03199       if (filterAction && menu)
03200           filterAction->plug(menu);
03201       }
03202 }
03203 
03204 void KMMainWidget::slotSubscriptionDialog()
03205 {
03206   if (!mFolder) return;
03207 
03208   ImapAccountBase* account;
03209   if (mFolder->folderType() == KMFolderTypeImap)
03210   {
03211     account = static_cast<KMFolderImap*>(mFolder)->account();
03212   } else if (mFolder->folderType() == KMFolderTypeCachedImap)
03213   {
03214     account = static_cast<KMFolderCachedImap*>(mFolder)->account();
03215   } else
03216     return;
03217 
03218   SubscriptionDialog *dialog = new SubscriptionDialog(this,
03219       i18n("Subscription"),
03220       account);
03221   if ( dialog->exec() )
03222     account->listDirectory();
03223 }
03224 
03225 //-----------------------------------------------------------------------------
03226 void KMMainWidget::slotFolderTreeColumnsChanged()
03227 {
03228   mTotalColumnToggle->setChecked( mFolderTree->isTotalActive() );
03229   mUnreadColumnToggle->setChecked( mFolderTree->isUnreadActive() );
03230 }
03231 
03232 void KMMainWidget::toggleSystray(bool enabled, int mode)
03233 {
03234   kdDebug(5006) << "setupSystray called" << endl;
03235   if (enabled && !mSystemTray)
03236   {
03237     mSystemTray = new KMSystemTray();
03238   }
03239   else if (!enabled && mSystemTray)
03240   {
03242     kdDebug(5006) << "deleting systray" << endl;
03243     delete mSystemTray;
03244     mSystemTray = 0;
03245   }
03246 
03248   if(mSystemTray)
03249   {
03250     kdDebug(5006) << "Setting system tray mode" << endl;
03251     mSystemTray->setMode(mode);
03252   }
03253 }
KDE Logo
This file is part of the documentation for kmail Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:37:32 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003