// kmmainwin.cpp //#define MALLOC_DEBUG 1 #define IDENTITY_UOIDs #include #ifdef MALLOC_DEBUG #include #endif #undef Unsorted // X headers... #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if KDE_VERSION >= 306 #include #endif #include "configuredialog.h" #include "kmbroadcaststatus.h" #include "kmfoldermgr.h" #include "kmfolderdia.h" #include "kmacctmgr.h" #include "kbusyptr.h" #include "kmfoldertree.h" #include "kmreaderwin.h" #include "kmfolderimap.h" #include "kmcomposewin.h" #include "kmfolderseldlg.h" #include "kmfiltermgr.h" #include "kmsender.h" #include "kmaddrbook.h" #include "kmversion.h" #include "kmfldsearch.h" #include "mailinglist-magic.h" #include "kmmsgdict.h" #include "kmacctfolder.h" #include "kmmimeparttree.h" #include #include #include #include #include "kmmainwin.moc" //----------------------------------------------------------------------------- KMMainWin::KMMainWin(QWidget *, char *name) : KMMainWinInherited(name) { // must be the first line of the constructor: searchWin = 0; mStartupDone = FALSE; mbNewMBVisible = false; mIntegrated = TRUE; mFolder = NULL; mFolderThreadPref = false; mFolderHtmlPref = false; mCountJobs = 0; mPanner1Sep << 1 << 1; mPanner2Sep << 1 << 1 << 1; mPanner3Sep << 1 << 1; setMinimumSize(400, 300); mConfigureDialog = 0; readPreConfig(); createWidgets(); setupMenuBar(); setupStatusBar(); applyMainWindowSettings(kapp->config(), "Main Window"); toolbarAction->setChecked(!toolBar()->isHidden()); statusbarAction->setChecked(!statusBar()->isHidden()); readConfig(); activatePanners(); if (kernel->firstStart() || kernel->previousVersion() != KMAIL_VERSION) slotIntro(); else { KMFolder* selected = kernel->inboxFolder(); mFolderTree->doFolderSelected(mFolderTree->indexOfFolder(selected)); } connect(kernel->msgSender(), SIGNAL(statusMsg(const QString&)), SLOT(statusMsg(const QString&))); connect(kernel->acctMgr(), SIGNAL( checkedMail(bool, bool)), SLOT( slotMailChecked(bool, bool))); // display the full path to the folder in the caption connect(mFolderTree, SIGNAL(currentChanged(QListViewItem*)), this, SLOT(slotChangeCaption(QListViewItem*))); if ( kernel->firstInstance() ) QTimer::singleShot( 200, this, SLOT(slotShowTipOnStart()) ); // must be the last line of the constructor: mStartupDone = TRUE; } //----------------------------------------------------------------------------- KMMainWin::~KMMainWin() { if (searchWin) searchWin->close(); writeConfig(); writeFolderConfig(); saveMainWindowSettings(kapp->config(), "Main Window"); kapp->config()->sync(); delete mHeaders; delete mFolderTree; } //----------------------------------------------------------------------------- void KMMainWin::readPreConfig(void) { KConfig *config = kapp->config(); { // area for config group "Geometry" KConfigGroupSaver saver(config, "Geometry"); mWindowLayout = config->readNumEntry( "windowLayout", 1 ); mShowMIMETreeMode = config->readNumEntry( "showMIME", 1 ); } KConfigGroupSaver saver(config, "General"); mEncodingStr = config->readEntry("encoding", "").latin1(); } //----------------------------------------------------------------------------- void KMMainWin::readFolderConfig(void) { if (!mFolder) return; KConfig *config = kapp->config(); KConfigGroupSaver saver(config, "Folder-" + mFolder->idString()); mFolderThreadPref = config->readBoolEntry( "threadMessagesOverride", false ); mFolderHtmlPref = config->readBoolEntry( "htmlMailOverride", false ); } //----------------------------------------------------------------------------- void KMMainWin::writeFolderConfig(void) { if (!mFolder) return; KConfig *config = kapp->config(); KConfigGroupSaver saver(config, "Folder-" + mFolder->idString()); config->writeEntry( "threadMessagesOverride", mFolderThreadPref ); config->writeEntry( "htmlMailOverride", mFolderHtmlPref ); } //----------------------------------------------------------------------------- void KMMainWin::readConfig(void) { KConfig *config = kapp->config(); int oldWindowLayout = 1; int oldShowMIMETreeMode = 1; QString str; QSize siz; if (mStartupDone) { writeConfig(); oldWindowLayout = mWindowLayout; oldShowMIMETreeMode = mShowMIMETreeMode; readPreConfig(); mHeaders->refreshNestedState(); if(oldWindowLayout != mWindowLayout || oldShowMIMETreeMode != mShowMIMETreeMode ) { hide(); // delete all panners delete mPanner1; // will always delete the others createWidgets(); } } { // area for config group "Reader" KConfigGroupSaver saver(config, "Reader"); mHtmlPref = config->readBoolEntry( "htmlMail", false ); } { // area for config group "Geometry" KConfigGroupSaver saver(config, "Geometry"); mThreadPref = config->readBoolEntry( "nestedMessages", false ); QSize defaultSize(600,600); siz = config->readSizeEntry("MainWin", &defaultSize); if (!siz.isEmpty()) resize(siz); // the default sizes are dependent on the actual layout switch( mWindowLayout ) { case 0: // the default value for the FolderPaneWidth should be about // 160 but the default is set to 0 to enable the workaround // (see below) mPanner1Sep[0] = config->readNumEntry( "FolderPaneWidth", 0 ); mPanner1Sep[1] = config->readNumEntry( "HeaderPaneWidth", 600-160 ); mPanner2Sep[0] = config->readNumEntry( "HeaderPaneHeight", 200 ); mPanner2Sep[1] = config->readNumEntry( "MimePaneHeight", 100 ); mPanner2Sep[2] = config->readNumEntry( "MessagePaneHeight", 300 ); break; case 1: mPanner1Sep[0] = config->readNumEntry( "FolderPaneWidth", 0 ); mPanner1Sep[1] = config->readNumEntry( "HeaderPaneWidth", 600-160 ); mPanner2Sep[0] = config->readNumEntry( "HeaderPaneHeight", 200 ); mPanner2Sep[1] = config->readNumEntry( "MessagePaneHeight", 300 ); mPanner2Sep[2] = config->readNumEntry( "MimePaneHeight", 100 ); break; case 2: mPanner1Sep[0] = config->readNumEntry( "FolderPaneWidth", 0 ); mPanner1Sep[1] = config->readNumEntry( "HeaderPaneWidth", 600-160 ); mPanner2Sep[0] = config->readNumEntry( "FolderPaneHeight", 400 ); mPanner2Sep[1] = config->readNumEntry( "MimePaneHeight", 200 ); mPanner3Sep[0] = config->readNumEntry( "HeaderPaneHeight", 200 ); mPanner3Sep[1] = config->readNumEntry( "MessagePaneHeight", 400 ); break; case 3: mPanner1Sep[0] = config->readNumEntry( "FolderPaneHeight", 300 ); mPanner1Sep[1] = config->readNumEntry( "MessagePaneHeight", 300 ); mPanner2Sep[0] = config->readNumEntry( "FolderPaneWidth", 160 ); mPanner2Sep[1] = config->readNumEntry( "HeaderPaneWidth", 600-160 ); mPanner3Sep[0] = config->readNumEntry( "HeaderPaneHeight", 150 ); mPanner3Sep[1] = config->readNumEntry( "MimePaneHeight", 150 ); break; case 4: mPanner1Sep[0] = config->readNumEntry( "FolderPaneHeight", 200 ); mPanner1Sep[1] = config->readNumEntry( "MimePaneHeight", 100 ); mPanner1Sep[2] = config->readNumEntry( "MessagePaneHeight", 300 ); mPanner2Sep[0] = config->readNumEntry( "FolderPaneWidth", 160 ); mPanner2Sep[1] = config->readNumEntry( "HeaderPaneWidth", 600-160 ); break; } // workaround to support the old buggy way of saving the dimensions of the panes if (mPanner1Sep[0] == 0) { defaultSize = QSize(300,130); siz = config->readSizeEntry("Panners", &defaultSize); if (siz.isEmpty()) siz = QSize(100,100); // why not defaultSize? mPanner2Sep[0] = siz.width(); mPanner1Sep[0] = siz.height(); mPanner2Sep[1] = height() - siz.width(); mPanner1Sep[1] = width() - siz.height(); } if (!mStartupDone || oldWindowLayout != mWindowLayout || oldShowMIMETreeMode != mShowMIMETreeMode ) { /** unread / total columns * as we have some dependencies in this widget * it's better to manage these here */ // The columns are shown by default. int unreadColumn = config->readNumEntry("UnreadColumn", 1); int totalColumn = config->readNumEntry("TotalColumn", 2); /* we need to _activate_ them in the correct order * this is ugly because we can't use header()->moveSection * but otherwise the restoreLayout from KMFolderTree * doesn't know that to do */ if (unreadColumn != -1 && unreadColumn < totalColumn) mFolderTree->toggleColumn(KMFolderTree::unread); if (totalColumn != -1) mFolderTree->toggleColumn(KMFolderTree::total); if (unreadColumn != -1 && unreadColumn > totalColumn) mFolderTree->toggleColumn(KMFolderTree::unread); } } mMsgView->readConfig(); slotSetEncoding(); mHeaders->readConfig(); mFolderTree->readConfig(); { // area for config group "General" KConfigGroupSaver saver(config, "General"); mSendOnCheck = config->readBoolEntry("sendOnCheck",false); mBeepOnNew = config->readBoolEntry("beep-on-mail", false); mBoxOnNew = config->readBoolEntry("msgbox-on-mail", false); mExecOnNew = config->readBoolEntry("exec-on-mail", false); mNewMailCmd = config->readEntry("exec-on-mail-cmd", ""); mConfirmEmpty = config->readBoolEntry("confirm-before-empty", true); } // Re-activate panners if (mStartupDone) { if (oldWindowLayout != mWindowLayout || oldShowMIMETreeMode != mShowMIMETreeMode ) activatePanners(); // kernel->kbp()->busy(); //Crashes KMail mFolderTree->reload(); QListViewItem *qlvi = mFolderTree->indexOfFolder(mFolder); if (qlvi!=0) { mFolderTree->setCurrentItem(qlvi); mFolderTree->setSelected(qlvi,TRUE); } // sanders - New code mHeaders->setFolder(mFolder, true); int aIdx = mHeaders->currentItemIndex(); if (aIdx != -1) mMsgView->setMsg( mFolder->getMsg(aIdx), true ); else mMsgView->clear( true ); updateMessageActions(); show(); // sanders - Maybe this fixes a bug? /* Old code mMsgView->setMsg( mMsgView->msg(), TRUE ); mHeaders->setFolder(mFolder); // kernel->kbp()->idle(); //For symmetry show(); */ } } //----------------------------------------------------------------------------- void KMMainWin::writeConfig(void) { QString s; KConfig *config = kapp->config(); QRect r = geometry(); mMsgView->writeConfig(); mFolderTree->writeConfig(); { // area for config group "Geometry" KConfigGroupSaver saver(config, "Geometry"); config->writeEntry("MainWin", r.size()); // Save the dimensions of the folder, header and message pane; // this is dependent on the layout style. switch( mWindowLayout ) { case 0: config->writeEntry( "FolderPaneWidth", mPanner1->sizes()[0] ); config->writeEntry( "HeaderPaneWidth", mPanner1->sizes()[1] ); config->writeEntry( "HeaderPaneHeight", mPanner2->sizes()[0] ); config->writeEntry( "MimePaneHeight", mPanner2->sizes()[1] ); config->writeEntry( "MessagePaneHeight", mPanner2->sizes()[2] ); break; case 1: config->writeEntry( "FolderPaneWidth", mPanner1->sizes()[0] ); config->writeEntry( "HeaderPaneWidth", mPanner1->sizes()[1] ); config->writeEntry( "HeaderPaneHeight", mPanner2->sizes()[0] ); config->writeEntry( "MessagePaneHeight", mPanner2->sizes()[1] ); config->writeEntry( "MimePaneHeight", mPanner2->sizes()[2] ); break; case 2: config->writeEntry( "FolderPaneWidth", mPanner1->sizes()[0] ); config->writeEntry( "HeaderPaneWidth", mPanner1->sizes()[1] ); config->writeEntry( "FolderPaneHeight", mPanner2->sizes()[0] ); config->writeEntry( "MimePaneHeight", mPanner2->sizes()[1] ); config->writeEntry( "HeaderPaneHeight", mPanner3->sizes()[0] ); config->writeEntry( "MessagePaneHeight", mPanner3->sizes()[1] ); break; case 3: config->writeEntry( "FolderPaneHeight", mPanner1->sizes()[0] ); config->writeEntry( "MessagePaneHeight", mPanner1->sizes()[1] ); config->writeEntry( "FolderPaneWidth", mPanner2->sizes()[0] ); config->writeEntry( "HeaderPaneWidth", mPanner2->sizes()[1] ); config->writeEntry( "HeaderPaneHeight", mPanner3->sizes()[0] ); config->writeEntry( "MimePaneHeight", mPanner3->sizes()[1] ); break; case 4: config->writeEntry( "FolderPaneHeight", mPanner1->sizes()[0] ); config->writeEntry( "MimePaneHeight", mPanner1->sizes()[1] ); config->writeEntry( "MessagePaneHeight", mPanner1->sizes()[2] ); config->writeEntry( "FolderPaneWidth", mPanner2->sizes()[0] ); config->writeEntry( "HeaderPaneWidth", mPanner2->sizes()[1] ); break; } // save the state of the unread/total-columns config->writeEntry("UnreadColumn", mFolderTree->unreadIndex()); config->writeEntry("TotalColumn", mFolderTree->totalIndex()); } KConfigGroupSaver saver(config, "General"); config->writeEntry("encoding", QString(mEncodingStr)); } //----------------------------------------------------------------------------- void KMMainWin::createWidgets(void) { QAccel *accel = new QAccel(this, "createWidgets()"); KConfig *config = kapp->config(); KConfigGroupSaver saver(config, "Geometry"); // Create the splitters according to the layout settings QWidget *headerParent = 0, *folderParent = 0, *mimeParent = 0, *messageParent = 0; switch( mWindowLayout ) { case 0: case 1: mPanner1 = new QSplitter( Qt::Horizontal, this, "panner 1" ); mPanner1->setOpaqueResize( true ); mPanner2 = new QSplitter( Qt::Vertical, mPanner1, "panner 2" ); mPanner2->setOpaqueResize( true ); mPanner3 = 0; headerParent = mPanner2; folderParent = mPanner1; mimeParent = mPanner2; messageParent = mPanner2; break; case 2: mPanner1 = new QSplitter( Qt::Horizontal, this, "panner 1" ); mPanner1->setOpaqueResize( true ); mPanner2 = new QSplitter( Qt::Vertical, mPanner1, "panner 2" ); mPanner2->setOpaqueResize( true ); mPanner3 = new QSplitter( Qt::Vertical, mPanner1, "panner 3" ); mPanner3->setOpaqueResize( true ); headerParent = mPanner3; folderParent = mPanner2; mimeParent = mPanner2; messageParent = mPanner3; break; case 3: mPanner1 = new QSplitter( Qt::Vertical, this, "panner 1" ); mPanner1->setOpaqueResize( true ); mPanner2 = new QSplitter( Qt::Horizontal, mPanner1, "panner 2" ); mPanner2->setOpaqueResize( true ); mPanner3 = new QSplitter( Qt::Vertical, mPanner2, "panner 3" ); mPanner3->setOpaqueResize( true ); headerParent = mPanner3; folderParent = mPanner2; mimeParent = mPanner3; messageParent = mPanner1; break; case 4: mPanner1 = new QSplitter( Qt::Vertical, this, "panner 1" ); mPanner1->setOpaqueResize( true ); mPanner2 = new QSplitter( Qt::Horizontal, mPanner1, "panner 2" ); mPanner2->setOpaqueResize( true ); mPanner3 = 0; headerParent = mPanner2; folderParent = mPanner2; mimeParent = mPanner1; messageParent = mPanner1; break; } if( mPanner1 ) mPanner1->dumpObjectTree(); if( mPanner2 ) mPanner2->dumpObjectTree(); if( mPanner3 ) mPanner3->dumpObjectTree(); // BUG -sanders these accelerators stop working after switching // between long/short folder layout // Probably need to disconnect them first. // create list of messages headerParent->dumpObjectTree(); mHeaders = new KMHeaders(this, headerParent, "headers"); connect(mHeaders, SIGNAL(selected(KMMessage*)), this, SLOT(slotMsgSelected(KMMessage*))); connect(mHeaders, SIGNAL(activated(KMMessage*)), this, SLOT(slotMsgActivated(KMMessage*))); connect( mHeaders, SIGNAL( selectionChanged() ), SLOT( startUpdateMessageActionsTimer() ) ); accel->connectItem(accel->insertItem(SHIFT+Key_Left), mHeaders, SLOT(selectPrevMessage())); accel->connectItem(accel->insertItem(SHIFT+Key_Right), mHeaders, SLOT(selectNextMessage())); if (!mEncodingStr.isEmpty()) mCodec = KMMsgBase::codecForName(mEncodingStr); else mCodec = 0; mMsgView = new KMReaderWin(0, &mShowMIMETreeMode, messageParent); connect(mMsgView, SIGNAL(replaceMsgByUnencryptedVersion()), this, SLOT(slotReplaceMsgByUnencryptedVersion())); connect(mMsgView, SIGNAL(statusMsg(const QString&)), this, SLOT(htmlStatusMsg(const QString&))); connect(mMsgView, SIGNAL(popupMenu(KMMessage&,const KURL&,const QPoint&)), this, SLOT(slotMsgPopup(KMMessage&,const KURL&,const QPoint&))); connect(mMsgView, SIGNAL(urlClicked(const KURL&,int)), this, SLOT(slotUrlClicked(const KURL&,int))); connect(mMsgView, SIGNAL(showAtmMsg(KMMessage *)), this, SLOT(slotAtmMsg(KMMessage *))); connect(mHeaders, SIGNAL(maybeDeleting()), mMsgView, SLOT(clearCache())); connect(mMsgView, SIGNAL(noDrag()), mHeaders, SLOT(slotNoDrag())); accel->connectItem(accel->insertItem(Key_Up), mMsgView, SLOT(slotScrollUp())); accel->connectItem(accel->insertItem(Key_Down), mMsgView, SLOT(slotScrollDown())); accel->connectItem(accel->insertItem(Key_Prior), mMsgView, SLOT(slotScrollPrior())); accel->connectItem(accel->insertItem(Key_Next), mMsgView, SLOT(slotScrollNext())); new KAction( i18n("Move Message to Folder"), Key_M, this, SLOT(slotMoveMsg()), actionCollection(), "move_message_to_folder" ); new KAction( i18n("Copy Message to Folder"), Key_C, this, SLOT(slotCopyMsg()), actionCollection(), "copy_message_to_folder" ); // create list of folders mFolderTree = new KMFolderTree(folderParent, "folderTree"); connect(mFolderTree, SIGNAL(folderSelected(KMFolder*)), this, SLOT(folderSelected(KMFolder*))); connect(mFolderTree, SIGNAL(folderSelectedUnread(KMFolder*)), this, SLOT(folderSelectedUnread(KMFolder*))); connect(mFolderTree, SIGNAL(folderDrop(KMFolder*)), this, SLOT(slotMoveMsgToFolder(KMFolder*))); connect(mFolderTree, SIGNAL(folderDropCopy(KMFolder*)), this, SLOT(slotCopyMsgToFolder(KMFolder*))); // create a mime part tree and store it's pointer in the reader win mMimePartTree = new KMMimePartTree( mMsgView, mimeParent, "mMimePartTree" ); mMsgView->setMimePartTree( mMimePartTree ); //Commands not worthy of menu items, but that deserve configurable keybindings new KAction( i18n("Focus on Next Folder"), CTRL+Key_Right, mFolderTree, SLOT(incCurrentFolder()), actionCollection(), "inc_current_folder"); new KAction( i18n("Focus on Previous Folder"), CTRL+Key_Left, mFolderTree, SLOT(decCurrentFolder()), actionCollection(), "dec_current_folder"); new KAction( i18n("Select Folder with Focus"), CTRL+Key_Space, mFolderTree, SLOT(selectCurrentFolder()), actionCollection(), "select_current_folder"); connect( kernel->outboxFolder(), SIGNAL( msgRemoved(int, QString) ), SLOT( startUpdateMessageActionsTimer() ) ); connect( kernel->outboxFolder(), SIGNAL( msgAdded(int) ), SLOT( startUpdateMessageActionsTimer() ) ); } //----------------------------------------------------------------------------- void KMMainWin::activatePanners(void) { // glue everything together switch( mWindowLayout ) { case 0: case 1: mHeaders->reparent( mPanner2, 0, QPoint( 0, 0 ) ); mMimePartTree->reparent( mPanner2, 0, QPoint( 0, 0 ) ); mMsgView->reparent( mPanner2, 0, QPoint( 0, 0 ) ); if( mWindowLayout ) mPanner2->moveToLast( mMimePartTree ); else mPanner2->moveToLast( mMsgView ); mFolderTree->reparent( mPanner1, 0, QPoint( 0, 0 ) ); mPanner1->moveToLast( mPanner2 ); mPanner1->setSizes( mPanner1Sep ); mPanner1->setResizeMode( mFolderTree, QSplitter::KeepSize ); mPanner2->setSizes( mPanner2Sep ); mPanner2->setResizeMode( mHeaders, QSplitter::KeepSize ); mPanner2->setResizeMode( mMimePartTree, QSplitter::KeepSize ); break; case 2: mHeaders->reparent( mPanner3, 0, QPoint( 0, 0 ) ); mMsgView->reparent( mPanner3, 0, QPoint( 0, 0 ) ); mPanner3->moveToLast( mMsgView ); mFolderTree->reparent( mPanner2, 0, QPoint( 0, 0 ) ); mMimePartTree->reparent( mPanner2, 0, QPoint( 0, 0 ) ); mPanner2->moveToLast( mMimePartTree ); mPanner1->setSizes( mPanner1Sep ); mPanner2->setSizes( mPanner2Sep ); mPanner3->setSizes( mPanner2Sep ); mPanner2->setResizeMode( mMimePartTree, QSplitter::KeepSize ); mPanner3->setResizeMode( mHeaders, QSplitter::KeepSize ); break; case 3: mFolderTree->reparent( mPanner2, 0, QPoint( 0, 0 ) ); mPanner2->moveToFirst( mFolderTree ); mHeaders->reparent( mPanner3, 0, QPoint( 0, 0 ) ); mMimePartTree->reparent( mPanner3, 0, QPoint( 0, 0 ) ); mPanner3->moveToLast( mMimePartTree ); mMsgView->reparent( mPanner1, 0, QPoint( 0, 0 ) ); mPanner1->moveToLast( mMsgView ); mPanner1->setSizes( mPanner1Sep ); mPanner2->setSizes( mPanner2Sep ); mPanner3->setSizes( mPanner2Sep ); mPanner1->setResizeMode( mPanner2, QSplitter::KeepSize ); mPanner2->setResizeMode( mFolderTree, QSplitter::KeepSize ); mPanner3->setResizeMode( mMimePartTree, QSplitter::KeepSize ); break; case 4: mFolderTree->reparent( mPanner2, 0, QPoint( 0, 0 ) ); mHeaders->reparent( mPanner2, 0, QPoint( 0, 0 ) ); mPanner2->moveToLast( mHeaders ); mMimePartTree->reparent( mPanner1, 0, QPoint( 0, 0 ) ); mPanner1->moveToFirst( mPanner2 ); mMsgView->reparent( mPanner1, 0, QPoint( 0, 0 ) ); mPanner1->moveToLast( mMsgView ); mPanner1->setSizes( mPanner1Sep ); mPanner2->setSizes( mPanner2Sep ); mPanner1->setResizeMode( mPanner2, QSplitter::KeepSize ); mPanner1->setResizeMode( mMimePartTree, QSplitter::KeepSize ); mPanner2->setResizeMode( mFolderTree, QSplitter::KeepSize ); break; } if( 1 < mShowMIMETreeMode ) mMimePartTree->show(); else mMimePartTree->hide(); setCentralWidget( mPanner1 ); } //----------------------------------------------------------------------------- void KMMainWin::slotSetEncoding() { mEncodingStr = KGlobal::charsets()->encodingForName(mEncoding->currentText()).latin1(); if (mEncoding->currentItem() == 0) // Auto { mCodec = 0; mEncodingStr = ""; } else mCodec = KMMsgBase::codecForName( mEncodingStr ); mMsgView->setCodec(mCodec); return; } //----------------------------------------------------------------------------- void KMMainWin::htmlStatusMsg(const QString &aText) { if (aText.isEmpty()) displayStatusMsg(mLastStatusMsg); else displayStatusMsg(aText); } //----------------------------------------------------------------------------- void KMMainWin::statusMsg(const QString& aText) { mLastStatusMsg = aText; displayStatusMsg(aText); } //----------------------------------------------------------------------------- void KMMainWin::displayStatusMsg(const QString& aText) { QString text = " " + aText + " "; int statusWidth = statusBar()->width() - littleProgress->width() - fontMetrics().maxWidth(); while (!text.isEmpty() && fontMetrics().width( text ) >= statusWidth) text.truncate( text.length() - 1); // ### FIXME: We should disable richtext/HTML (to avoid possible denial of service attacks), // but this code would double the size of the satus bar if the user hovers // over an -style email address :-( // text.replace(QRegExp("&"), "&"); // text.replace(QRegExp("<"), "<"); // text.replace(QRegExp(">"), ">"); statusBar()->changeItem(text, mMessageStatusId); } //----------------------------------------------------------------------------- void KMMainWin::hide() { KMMainWinInherited::hide(); } //----------------------------------------------------------------------------- void KMMainWin::show() { if( mPanner1 ) mPanner1->setSizes( mPanner1Sep ); if( mPanner2 ) mPanner2->setSizes( mPanner2Sep ); if( mPanner3 ) mPanner3->setSizes( mPanner3Sep ); KMMainWinInherited::show(); } //------------------------------------------------------------------------- void KMMainWin::slotSearch() { if(!searchWin) { searchWin = new KMFldSearch(this, "Search", mFolder, false); connect(searchWin, SIGNAL(destroyed()), this, SLOT(slotSearchClosed())); } else { searchWin->activateFolder(mFolder); } searchWin->show(); KWin::setActiveWindow(searchWin->winId()); } //------------------------------------------------------------------------- void KMMainWin::slotSearchClosed() { searchWin = 0; } //------------------------------------------------------------------------- void KMMainWin::slotFind() { if( mMsgView ) mMsgView->slotFind(); } //----------------------------------------------------------------------------- void KMMainWin::slotHelp() { kapp->invokeHelp(); } //----------------------------------------------------------------------------- void KMMainWin::slotNewMailReader() { KMMainWin *d; d = new KMMainWin(NULL); d->show(); d->resize(d->size()); } //----------------------------------------------------------------------------- void KMMainWin::slotSettings() { if( mConfigureDialog == 0 ) { mConfigureDialog = new ConfigureDialog( this, "configure", false ); } mConfigureDialog->show(); } //----------------------------------------------------------------------------- void KMMainWin::slotFilter() { kernel->filterMgr()->openDialog( this ); } //----------------------------------------------------------------------------- void KMMainWin::slotPopFilter() { kernel->popFilterMgr()->openDialog( this ); } //----------------------------------------------------------------------------- void KMMainWin::slotAddrBook() { KMAddrBookExternal::launch(this); } //----------------------------------------------------------------------------- void KMMainWin::slotImport() { KRun::runCommand("kmailcvt"); } //----------------------------------------------------------------------------- void KMMainWin::slotAddFolder() { KMFolderDialog *d; d = new KMFolderDialog(0, &(kernel->folderMgr()->dir()), this, i18n("Create Folder")); if (d->exec()) { mFolderTree->reload(); QListViewItem *qlvi = mFolderTree->indexOfFolder( mFolder ); if (qlvi) { qlvi->setOpen(TRUE); mFolderTree->setCurrentItem( qlvi ); } if ( mFolder && mFolder->needsRepainting() ) mFolderTree->delayedUpdate(); } delete d; } //----------------------------------------------------------------------------- void KMMainWin::slotCheckMail() { if(kernel->checkingMail()) { KMessageBox::information(this, i18n("Your mail is already being checked.")); return; } kernel->setCheckingMail(true); kernel->acctMgr()->checkMail(true); kernel->setCheckingMail(false); } //----------------------------------------------------------------------------- void KMMainWin::slotCheckOneAccount(int item) { if(kernel->checkingMail()) { KMessageBox::information(this, i18n("Your mail is already being checked.")); return; } kernel->setCheckingMail(true); // kbp->busy(); kernel->acctMgr()->intCheckMail(item); // kbp->idle(); kernel->setCheckingMail(false); } void KMMainWin::slotMailChecked(bool newMail, bool sendOnCheck) { if(mSendOnCheck && sendOnCheck) slotSendQueued(); if (!newMail) return; KNotifyClient::event("new-mail-arrived", i18n("New mail arrived")); if (mBeepOnNew) { KNotifyClient::beep(); } if (mExecOnNew) { if (!mNewMailCmd.isEmpty()) { #if KDE_VERSION >= 305 KProcess p; p.setUseShell(true); #else KShellProcess p; #endif p << mNewMailCmd; p.start(KProcess::DontCare); } } if (mBoxOnNew && !mbNewMBVisible) { mbNewMBVisible = true; KMessageBox::information(this, i18n("You have new mail!"), i18n("New Mail")); mbNewMBVisible = false; } // Todo: // scroll mHeaders to show new items if current item would // still be visible // mHeaders->showNewMail(); } //----------------------------------------------------------------------------- void KMMainWin::slotCompose() { KMComposeWin *win; KMMessage* msg = new KMMessage; if ( mFolder ) { msg->initHeader( mFolder->identity() ); win = new KMComposeWin(msg, mFolder->identity()); } else { msg->initHeader(); win = new KMComposeWin(msg); } win->show(); } //----------------------------------------------------------------------------- void KMMainWin::slotPostToML() { KMComposeWin *win; KMMessage* msg = new KMMessage; if ( mFolder ) { msg->initHeader( mFolder->identity() ); if (mFolder->isMailingList()) { kdDebug(5006)<isMailingList() %1").arg( mFolder->mailingListPostAddress().latin1())<setTo(mFolder->mailingListPostAddress()); } win = new KMComposeWin(msg, mFolder->identity()); } else { msg->initHeader(); win = new KMComposeWin(msg); } win->show(); } //----------------------------------------------------------------------------- void KMMainWin::slotModifyFolder() { KMFolderDialog *d; if (!mFolder) return; d = new KMFolderDialog((KMFolder*)mFolder, mFolder->parent(), this, i18n("Properties of Folder %1").arg( mFolder->label() ) ); if (d->exec() && ((mFolder->protocol() != "imap") || mFolder->needsRepainting() ) ) { mFolderTree->reload(); QListViewItem *qlvi = mFolderTree->indexOfFolder( mFolder ); if (qlvi) { qlvi->setOpen(TRUE); mFolderTree->setCurrentItem( qlvi ); mHeaders->msgChanged(); } if ( mFolder->needsRepainting() ) mFolderTree->delayedUpdate(); } delete d; } //----------------------------------------------------------------------------- void KMMainWin::slotExpireFolder() { QString str; bool canBeExpired = true; if (!mFolder) return; if (!mFolder->isAutoExpire()) { canBeExpired = false; } else if (mFolder->getUnreadExpireUnits()==expireNever && mFolder->getReadExpireUnits()==expireNever) { canBeExpired = false; } if (!canBeExpired) { str = i18n("This folder does not have any expiry options set"); KMessageBox::information(this, str); return; } KConfig *config = kapp->config(); KConfigGroupSaver saver(config, "General"); if (config->readBoolEntry("warn-before-expire")) { str = i18n("Are you sure you want to expire this folder \"%1\"?").arg(mFolder->label()); if (KMessageBox::warningContinueCancel(this, str, i18n("Expire Folder"), i18n("&Expire")) != KMessageBox::Continue) return; } mFolder->expireOldMessages(); } //----------------------------------------------------------------------------- void KMMainWin::slotEmptyFolder() { QString str; KMMessage* msg; if (!mFolder) return; if (mConfirmEmpty) { str = i18n("Are you sure you want to move all messages from " "folder \"%1\" to the trash?").arg(mFolder->label()); if (KMessageBox::warningContinueCancel(this, str, i18n("Move to Trash"), i18n("&Move to Trash")) !=KMessageBox::Continue) return; } if (mFolder->protocol() == "imap") { slotMarkAll(); slotTrashMsg(); return; } mMsgView->clearCache(); kernel->kbp()->busy(); // begin of critical part // from here to "end..." no signal may change to another mFolder, otherwise // the wrong folder will be truncated in expunge (dnaber, 1999-08-29) mFolder->open(); mHeaders->setFolder(NULL); mMsgView->clear(); if (mFolder != kernel->trashFolder()) { // FIXME: If we run out of disk space mail may be lost rather // than moved into the trash -sanders while ((msg = mFolder->take(0)) != NULL) { kernel->trashFolder()->addMsg(msg); kernel->trashFolder()->unGetMsg(kernel->trashFolder()->count()-1); } } mFolder->close(); mFolder->expunge(); // end of critical if (mFolder != kernel->trashFolder()) statusMsg(i18n("Moved all messages to the trash")); mHeaders->setFolder(mFolder); kernel->kbp()->idle(); updateMessageActions(); } //----------------------------------------------------------------------------- void KMMainWin::slotRemoveFolder() { QString str; QDir dir; if (!mFolder) return; if (mFolder->isSystemFolder()) return; str = i18n("Are you sure you want to delete the folder " "\"%1\" and all its subfolders, discarding their contents?") .arg(mFolder->label()); if (KMessageBox::warningContinueCancel(this, str, i18n("Delete Folder"), i18n("&Delete")) == KMessageBox::Continue) { if (mFolder->hasAccounts()) { // this folder has an account, so we need to change that to the inbox KMAccount* acct = NULL; KMAcctFolder* acctFolder = static_cast(mFolder); for ( acct = acctFolder->account(); acct; acct = acctFolder->nextAccount() ) { acct->setFolder(kernel->inboxFolder()); KMessageBox::information(this, i18n("The destination folder of the account '%1' was restored to the inbox.").arg(acct->name())); } } if (mFolder->protocol() == "imap") static_cast(mFolder)->removeOnServer(); else kernel->folderMgr()->remove(mFolder); } } //----------------------------------------------------------------------------- void KMMainWin::slotMarkAllAsRead() { if (!mFolder) return; mFolder->markUnreadAsRead(); } //----------------------------------------------------------------------------- void KMMainWin::slotCompactFolder() { int idx = mHeaders->currentItemIndex(); if (mFolder) { if (mFolder->protocol() == "imap") { KMFolderImap *imap = static_cast(mFolder); imap->expungeFolder(imap, FALSE); } else { kernel->kbp()->busy(); mFolder->compact(); kernel->kbp()->idle(); } } mHeaders->setCurrentItemByIndex(idx); } //----------------------------------------------------------------------------- void KMMainWin::slotExpireAll() { KConfig *config = kapp->config(); int ret = 0; KConfigGroupSaver saver(config, "General"); if (config->readBoolEntry("warn-before-expire")) { ret = KMessageBox::warningContinueCancel(KMainWindow::memberList->first(), i18n("Are you sure you want to expire all old messages?"), i18n("Expire old Messages?"), i18n("Expire")); if (ret != KMessageBox::Continue) { return; } } kernel->folderMgr()->expireAllFolders(); } //----------------------------------------------------------------------------- void KMMainWin::slotCompactAll() { kernel->kbp()->busy(); QStringList strList; QValueList > folders; KMFolder *folder; mFolderTree->createFolderList(&strList, &folders); for (int i = 0; folders.at(i) != folders.end(); i++) { folder = *folders.at(i); if (!folder || folder->isDir()) continue; if (folder->protocol() == "imap") { KMFolderImap *imap = static_cast(folder); imap->expungeFolder(imap, TRUE); } else folder->compact(); } kernel->kbp()->idle(); } //----------------------------------------------------------------------------- void KMMainWin::slotOverrideHtml() { if( mHtmlPref == mFolderHtmlPref ) { int result = KMessageBox::warningContinueCancel( this, // the warning text is taken from configuredialog.cpp: i18n( "Use of HTML in mail will make you more vulnerable to " "\"spam\" and may increase the likelihood that your system will be " "compromised by other present and anticipated security exploits." ), i18n( "Security Warning" ), i18n( "Continue" ), "OverrideHtmlWarning", false); if( result == KMessageBox::Cancel ) { return; } } mFolderHtmlPref = !mFolderHtmlPref; mMsgView->setHtmlOverride(mFolderHtmlPref); mMsgView->update( true ); } //----------------------------------------------------------------------------- void KMMainWin::slotOverrideThread() { mFolderThreadPref = !mFolderThreadPref; mHeaders->setNestedOverride(mFolderThreadPref); } //----------------------------------------------------------------------------- void KMMainWin::slotPrintMsg() { if(mHeaders->currentItemIndex() >= 0) mMsgView->printMsg(); } //----------------------------------------------------------------------------- void KMMainWin::slotReplyToMsg() { if (mFolder->protocol() == "imap") { // disable the reply-action replyAction->setEnabled(false); // transfer the selected messages first connect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyReplyToMsg(bool))); transferSelectedMsgs(); } else { mHeaders->replyToMsg(mMsgView->copyText()); } } void KMMainWin::slotReallyReplyToMsg(bool success) { disconnect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyReplyToMsg(bool))); replyAction->setEnabled(true); if (success) mHeaders->replyToMsg(mMsgView->copyText(), mSelectedMsgs.getFirst()); } //----------------------------------------------------------------------------- void KMMainWin::slotNoQuoteReplyToMsg() { if (mFolder->protocol() == "imap") { // transfer the selected messages first connect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyNoQuoteReplyToMsg(bool))); transferSelectedMsgs(); } else { mHeaders->noQuoteReplyToMsg(); } } void KMMainWin::slotReallyNoQuoteReplyToMsg(bool success) { disconnect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyNoQuoteReplyToMsg(bool))); if (success) mHeaders->noQuoteReplyToMsg(mSelectedMsgs.getFirst()); } //----------------------------------------------------------------------------- void KMMainWin::slotReplyAllToMsg() { if (mFolder->protocol() == "imap") { // disable the action replyAllAction->setEnabled(false); // transfer the selected messages first connect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyReplyAllToMsg(bool))); transferSelectedMsgs(); } else { mHeaders->replyAllToMsg(mMsgView->copyText()); } } void KMMainWin::slotReallyReplyAllToMsg(bool success) { disconnect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyReplyAllToMsg(bool))); replyAllAction->setEnabled(true); if (success) mHeaders->replyAllToMsg(mMsgView->copyText(), mSelectedMsgs.getFirst()); } //----------------------------------------------------------------------------- void KMMainWin::slotReplyListToMsg() { if (mFolder->protocol() == "imap") { // transfer the selected messages first connect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyReplyListToMsg(bool))); transferSelectedMsgs(); } else { mHeaders->replyListToMsg(mMsgView->copyText()); } } void KMMainWin::slotReallyReplyListToMsg(bool success) { disconnect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyReplyListToMsg(bool))); if (success) mHeaders->replyListToMsg(mMsgView->copyText(), mSelectedMsgs.getFirst()); } void KMMainWin::slotForward() { // ### FIXME: remember the last used subaction and use that // currently, we hard-code "as attachment". slotForwardAttachedMsg(); } //----------------------------------------------------------------------------- void KMMainWin::slotForwardMsg() { if (mFolder->protocol() == "imap") { // disable the forward-action forwardAction->setEnabled(false); // transfer the selected messages first connect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyForwardMsg(bool))); transferSelectedMsgs(); } else { mHeaders->forwardMsg(); } } void KMMainWin::slotReallyForwardMsg(bool success) { disconnect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyForwardMsg(bool))); forwardAction->setEnabled(true); if (success) mHeaders->forwardMsg(&mSelectedMsgs); } //----------------------------------------------------------------------------- void KMMainWin::slotForwardAttachedMsg() { if (mFolder->protocol() == "imap") { connect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyForwardAttachedMsg(bool))); transferSelectedMsgs(); } else { mHeaders->forwardAttachedMsg(); } } void KMMainWin::slotReallyForwardAttachedMsg(bool success) { disconnect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyForwardAttachedMsg(bool))); if (success) mHeaders->forwardAttachedMsg(&mSelectedMsgs); } //----------------------------------------------------------------------------- void KMMainWin::slotRedirectMsg() { if (mFolder->protocol() == "imap") { connect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyRedirectMsg(bool))); transferSelectedMsgs(); } else { mHeaders->redirectMsg(); } } void KMMainWin::slotReallyRedirectMsg(bool success) { disconnect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyRedirectMsg(bool))); if (success) mHeaders->redirectMsg(mSelectedMsgs.getFirst()); } //----------------------------------------------------------------------------- void KMMainWin::slotBounceMsg() { if (mFolder->protocol() == "imap") { connect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyBounceMsg(bool))); transferSelectedMsgs(); } else { mHeaders->bounceMsg(); } } void KMMainWin::slotReallyBounceMsg(bool success) { disconnect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallyBounceMsg(bool))); if (success) mHeaders->bounceMsg(mSelectedMsgs.getFirst()); } //----------------------------------------------------------------------------- void KMMainWin::slotMessageQueuedOrDrafted() { if (!kernel->folderIsDraftOrOutbox(mFolder)) return; mMsgView->update(true); } //----------------------------------------------------------------------------- void KMMainWin::slotEditMsg() { KMMessage *msg; int aIdx; if((aIdx = mHeaders->currentItemIndex()) <= -1) return; if(!(msg = mHeaders->getMsg(aIdx))) return; slotEditMsg(msg); } //----------------------------------------------------------------------------- void KMMainWin::slotEditMsg(KMMessage* msg) { if (!kernel->folderIsDraftOrOutbox(mFolder)) return; if (mFolder == kernel->outboxFolder() && kernel->msgSender()->sending()) { KMessageBox::sorry(this, i18n("You can't edit messages that are already in " "progress of being sent.")); return; } if ( !msg->isComplete() && mFolder->protocol() == "imap" ) { // transfer the message first kdDebug(5006) << "slotEditMsg: transfer message" << endl; if (msg->transferInProgress()) return; msg->setTransferInProgress(TRUE); KMImapJob *job = new KMImapJob(msg); connect(job, SIGNAL(messageRetrieved(KMMessage*)), SLOT(slotEditMsg(KMMessage*))); return; } mFolder->removeMsg(msg); mHeaders->setSelected(mHeaders->currentItem(), TRUE); mHeaders->highlightMessage(mHeaders->currentItem(), true); KMComposeWin *win = new KMComposeWin(); QObject::connect( win, SIGNAL( messageQueuedOrDrafted()), this, SLOT( slotMessageQueuedOrDrafted()) ); win->setMsg(msg,FALSE, TRUE); win->setFolder(mFolder); win->show(); } //----------------------------------------------------------------------------- void KMMainWin::slotResendMsg() { mHeaders->resendMsg(); } //----------------------------------------------------------------------------- void KMMainWin::slotTrashMsg() { mHeaders->deleteMsg(); updateMessageActions(); } //----------------------------------------------------------------------------- void KMMainWin::slotDeleteMsg() { mHeaders->moveMsgToFolder(0); updateMessageActions(); } //----------------------------------------------------------------------------- void KMMainWin::slotUndo() { mHeaders->undo(); updateMessageActions(); } //----------------------------------------------------------------------------- void KMMainWin::slotShowMsgSrc() { KMMessage* msg = mHeaders->getMsg(-1); if (msg) { QTextCodec *codec = mCodec; if (!codec) //this is Auto setting { QCString cset = msg->charset(); if (!cset.isEmpty()) codec = KMMsgBase::codecForName(cset); } msg->viewSource(i18n("Message as Plain Text"), codec, mMsgView->isfixedFont()); } } //----------------------------------------------------------------------------- void KMMainWin::slotToggleFixedFont() { mMsgView->slotToggleFixedFont(); } //----------------------------------------------------------------------------- void KMMainWin::slotToggleUnreadColumn() { mFolderTree->toggleColumn(KMFolderTree::unread); } //----------------------------------------------------------------------------- void KMMainWin::slotToggleTotalColumn() { mFolderTree->toggleColumn(KMFolderTree::total, true); } //----------------------------------------------------------------------------- void KMMainWin::slotMoveMsg() { KMFolderSelDlg dlg(this,i18n("Move Message to Folder")); KMFolder* dest; if (!dlg.exec()) return; if (!(dest = dlg.folder())) return; mHeaders->moveMsgToFolder(dest); } //----------------------------------------------------------------------------- void KMMainWin::slotMoveMsgToFolder( KMFolder *dest) { mHeaders->moveMsgToFolder(dest); } //----------------------------------------------------------------------------- void KMMainWin::slotCopyMsgToFolder( KMFolder *dest) { mHeaders->copyMsgToFolder(dest); } //----------------------------------------------------------------------------- void KMMainWin::slotApplyFilters() { mHeaders->applyFiltersOnMsg(); } //----------------------------------------------------------------------------- void KMMainWin::slotCopyMsg() { KMFolderSelDlg dlg(this,i18n("Copy Message to Folder")); KMFolder* dest; if (!dlg.exec()) return; if (!(dest = dlg.folder())) return; mHeaders->copyMsgToFolder(dest); } //----------------------------------------------------------------------------- void KMMainWin::slotSaveMsg() { if(mHeaders->currentItemIndex() == -1) return; if (mFolder->protocol() == "imap") { connect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallySaveMsg(bool))); transferSelectedMsgs(); } else { mHeaders->saveMsg(-1); } } void KMMainWin::slotReallySaveMsg(bool success) { disconnect(this, SIGNAL(messagesTransfered(bool)), this, SLOT(slotReallySaveMsg(bool))); if (success) mHeaders->saveMsg(-1, &mSelectedMsgs); } //----------------------------------------------------------------------------- void KMMainWin::slotSendQueued() { kernel->msgSender()->sendQueued(); } //----------------------------------------------------------------------------- void KMMainWin::slotViewChange() { if(mBodyPartsMenu->isItemChecked(mBodyPartsMenu->idAt(0))) { mBodyPartsMenu->setItemChecked(mBodyPartsMenu->idAt(0),FALSE); mBodyPartsMenu->setItemChecked(mBodyPartsMenu->idAt(1),TRUE); } else if(mBodyPartsMenu->isItemChecked(mBodyPartsMenu->idAt(1))) { mBodyPartsMenu->setItemChecked(mBodyPartsMenu->idAt(1),FALSE); mBodyPartsMenu->setItemChecked(mBodyPartsMenu->idAt(0),TRUE); } //mMsgView->setInline(!mMsgView->isInline()); } void KMMainWin::slotBriefHeaders() { mMsgView->setHeaderStyle( KMReaderWin::HdrBrief ); } void KMMainWin::slotFancyHeaders() { mMsgView->setHeaderStyle( KMReaderWin::HdrFancy ); } void KMMainWin::slotStandardHeaders() { mMsgView->setHeaderStyle( KMReaderWin::HdrStandard ); } void KMMainWin::slotLongHeaders() { mMsgView->setHeaderStyle( KMReaderWin::HdrLong ); } void KMMainWin::slotAllHeaders() { mMsgView->setHeaderStyle( KMReaderWin::HdrAll ); } void KMMainWin::slotCycleHeaderStyles() { KMReaderWin::HeaderStyle style = mMsgView->headerStyle(); if ( style == KMReaderWin::HdrAll ) // last, go to top again: mMsgView->setHeaderStyle( KMReaderWin::HdrFancy ); else { style = KMReaderWin::HeaderStyle((int)style+1); mMsgView->setHeaderStyle( KMReaderWin::HeaderStyle(style) ); } KRadioAction * action = actionForHeaderStyle( mMsgView->headerStyle() ); assert( action ); action->setChecked( true ); } void KMMainWin::slotIconicAttachments() { mMsgView->setAttachmentStyle( KMReaderWin::IconicAttmnt ); } void KMMainWin::slotSmartAttachments() { mMsgView->setAttachmentStyle( KMReaderWin::SmartAttmnt ); } void KMMainWin::slotInlineAttachments() { mMsgView->setAttachmentStyle( KMReaderWin::InlineAttmnt ); } void KMMainWin::slotHideAttachments() { mMsgView->setAttachmentStyle( KMReaderWin::HideAttmnt ); } void KMMainWin::slotCycleAttachmentStyles() { KMReaderWin::AttachmentStyle style = mMsgView->attachmentStyle(); if ( style == KMReaderWin::HideAttmnt ) // last, go to top again: mMsgView->setAttachmentStyle( KMReaderWin::IconicAttmnt ); else { style = KMReaderWin::AttachmentStyle((int)style+1); mMsgView->setAttachmentStyle( KMReaderWin::AttachmentStyle(style) ); } KRadioAction * action = actionForAttachmentStyle( mMsgView->attachmentStyle() ); assert( action ); action->setChecked( true ); } void KMMainWin::folderSelected(KMFolder* aFolder) { folderSelected( aFolder, false ); } void KMMainWin::folderSelectedUnread(KMFolder* aFolder) { mHeaders->blockSignals( true ); folderSelected( aFolder, true ); QListViewItem *item = mHeaders->firstChild(); while (item && item->itemAbove()) item = item->itemAbove(); mHeaders->setCurrentItem( item ); mHeaders->nextUnreadMessage(true); mHeaders->blockSignals( false ); mHeaders->highlightMessage( mHeaders->currentItem() ); } //----------------------------------------------------------------------------- void KMMainWin::folderSelected(KMFolder* aFolder, bool jumpToUnread) { if( aFolder && mFolder == aFolder ) return; kernel->kbp()->busy(); mMsgView->clear(true); if( !aFolder || aFolder->noContent() || aFolder->count() == 0 ) { if( mMimePartTree ) mMimePartTree->hide(); } else { if( mMimePartTree && (1 < mShowMIMETreeMode) ) mMimePartTree->show(); } if( !mFolder ) { mMsgView->enableMsgDisplay(); mMsgView->clear(true); if( mHeaders ) mHeaders->show(); } if (mFolder && mFolder->needsCompacting() && (mFolder->protocol() == "imap")) { KMFolderImap *imap = static_cast(mFolder); if (imap->autoExpunge()) imap->expungeFolder(imap, TRUE); } writeFolderConfig(); mFolder = (KMFolder*)aFolder; readFolderConfig(); mMsgView->setHtmlOverride(mFolderHtmlPref); mHeaders->setFolder( mFolder, jumpToUnread ); updateMessageActions(); kernel->kbp()->idle(); } //----------------------------------------------------------------------------- KMMessage *KMMainWin::jumpToMessage(KMMessage *aMsg) { KMFolder *folder; int index; kernel->msgDict()->getLocation(aMsg, &folder, &index); if (!folder) return 0; // setting current folder only if we actually have to if (folder != mFolder) { folderSelected(folder, false); slotSelectFolder(folder); } KMMsgBase *msgBase = folder->getMsg(index); KMMessage *msg = static_cast(msgBase); // setting current message only if we actually have to unsigned long curMsgSerNum = 0; if (mHeaders->currentMsg()) curMsgSerNum = mHeaders->currentMsg()->getMsgSerNum(); if (curMsgSerNum != msg->getMsgSerNum()) mHeaders->setCurrentMsg(index); return msg; } //----------------------------------------------------------------------------- void KMMainWin::slotMsgSelected(KMMessage *msg) { if (msg && msg->parent() && (msg->parent()->protocol() == "imap") && !msg->isComplete()) { mMsgView->clear(); KMImapJob *job = new KMImapJob(msg); connect(job, SIGNAL(messageRetrieved(KMMessage*)), SLOT(slotUpdateImapMessage(KMMessage*))); } else { mMsgView->setMsg(msg); } // reset HTML override to the folder setting mMsgView->setHtmlOverride(mFolderHtmlPref); } //----------------------------------------------------------------------------- void KMMainWin::slotSelectFolder(KMFolder* folder) { QListViewItem* item = mFolderTree->indexOfFolder(folder); if (item) mFolderTree->setCurrentItem( item ); } //----------------------------------------------------------------------------- void KMMainWin::slotSelectMessage(KMMessage* msg) { int idx = mFolder->find(msg); if (idx != -1) { mHeaders->setCurrentMsg(idx); mMsgView->setMsg(msg); } } //----------------------------------------------------------------------------- void KMMainWin::slotReplaceMsgByUnencryptedVersion() { kdDebug(5006) << "KMMainWin::slotReplaceMsgByUnencryptedVersion()" << endl; KMMessage* oldMsg = mHeaders->getMsg(-1); if( oldMsg ) { kdDebug(5006) << "KMMainWin - old message found" << endl; if( oldMsg->hasUnencryptedMsg() ) { kdDebug(5006) << "KMMainWin - extra unencrypted message found" << endl; KMMessage* newMsg = oldMsg->unencryptedMsg(); // adjust the message id { QString msgId( oldMsg->msgId() ); QString prefix("DecryptedMsg."); int oldIdx = msgId.find(prefix, 0, false); if( -1 == oldIdx ) { int leftAngle = msgId.findRev( '<' ); msgId = msgId.insert( (-1 == leftAngle) ? 0 : ++leftAngle, prefix ); } else { // toggle between "DecryptedMsg." and "DeCryptedMsg." // to avoid same message id QCharRef c = msgId[ oldIdx+2 ]; if( 'C' == c ) c = 'c'; else c = 'C'; } newMsg->setMsgId( msgId ); mMsgView->setIdOfLastViewedMessage( msgId ); } const QString newMsgIdMD5( newMsg->msgIdMD5() ); // insert the unencrypted message kdDebug(5006) << "KMMainWin - copying unencrypted message to same folder" << endl; mHeaders->copyMsgToFolder(mFolder, -1, newMsg); // delete the encrypted message - this will also delete newMsg kdDebug(5006) << "KMMainWin - deleting encrypted message" << endl; mHeaders->deleteMsg(); kdDebug(5006) << "KMMainWin - updating message actions" << endl; updateMessageActions(); // find and select and show the new message int idx = mFolder->find( newMsgIdMD5 ); if( -1 != idx ) { mHeaders->setCurrentMsg( idx ); mMsgView->setMsg( mHeaders->currentMsg() ); } else { kdDebug(5006) << "KMMainWin - SORRY, could not store unencrypted message!" << endl; } kdDebug(5006) << "KMMainWin - done." << endl; } else kdDebug(5006) << "KMMainWin - NO EXTRA UNENCRYPTED MESSAGE FOUND" << endl; } else kdDebug(5006) << "KMMainWin - PANIC: NO OLD MESSAGE FOUND" << endl; } //----------------------------------------------------------------------------- void KMMainWin::slotUpdateImapMessage(KMMessage *msg) { if (msg && ((KMMsgBase*)msg)->isMessage()) mMsgView->setMsg(msg, TRUE); else // force an update of the folder static_cast(mFolder)->getFolder(true); } //----------------------------------------------------------------------------- void KMMainWin::slotSubjectFilter() { KMMessage* msg = mHeaders->getMsg(-1); if (msg) kernel->filterMgr()->createFilter( "Subject", msg->subject()); } void KMMainWin::slotMailingListFilter() { KMMessage* msg = mHeaders->getMsg(-1); if (msg) { QCString name; QString value; if ( !KMMLInfo::name( msg, name, value ).isNull() ) kernel->filterMgr()->createFilter( name, value ); } } //----------------------------------------------------------------------------- void KMMainWin::slotFromFilter() { KMMessage* msg = mHeaders->getMsg(-1); if (msg) kernel->filterMgr()->createFilter( "From", msg->from()); } //----------------------------------------------------------------------------- void KMMainWin::slotToFilter() { KMMessage* msg = mHeaders->getMsg(-1); if (msg) kernel->filterMgr()->createFilter( "To", msg->to()); } //----------------------------------------------------------------------------- void KMMainWin::slotSetMsgStatusNew() { mHeaders->setMsgStatus(KMMsgStatusNew); } //----------------------------------------------------------------------------- void KMMainWin::slotSetMsgStatusUnread() { mHeaders->setMsgStatus(KMMsgStatusUnread); } //----------------------------------------------------------------------------- void KMMainWin::slotSetMsgStatusFlag() { mHeaders->setMsgStatus(KMMsgStatusFlag); } //----------------------------------------------------------------------------- void KMMainWin::slotSetMsgStatusRead() { mHeaders->setMsgStatus(KMMsgStatusRead); } //----------------------------------------------------------------------------- void KMMainWin::slotSetMsgStatusReplied() { mHeaders->setMsgStatus(KMMsgStatusReplied); } //----------------------------------------------------------------------------- void KMMainWin::slotSetMsgStatusForwarded() { mHeaders->setMsgStatus(KMMsgStatusForwarded); } //----------------------------------------------------------------------------- void KMMainWin::slotSetMsgStatusQueued() { mHeaders->setMsgStatus(KMMsgStatusQueued); } //----------------------------------------------------------------------------- void KMMainWin::slotSetMsgStatusSent() { mHeaders->setMsgStatus(KMMsgStatusSent); } //----------------------------------------------------------------------------- void KMMainWin::slotSetThreadStatusNew() { mHeaders->setThreadStatus(KMMsgStatusNew); } //----------------------------------------------------------------------------- void KMMainWin::slotSetThreadStatusUnread() { mHeaders->setThreadStatus(KMMsgStatusUnread); } //----------------------------------------------------------------------------- void KMMainWin::slotSetThreadStatusFlag() { mHeaders->setThreadStatus(KMMsgStatusFlag); } //----------------------------------------------------------------------------- void KMMainWin::slotSetThreadStatusRead() { mHeaders->setThreadStatus(KMMsgStatusRead); } //----------------------------------------------------------------------------- void KMMainWin::slotSetThreadStatusReplied() { mHeaders->setThreadStatus(KMMsgStatusReplied); } //----------------------------------------------------------------------------- void KMMainWin::slotSetThreadStatusForwarded() { mHeaders->setThreadStatus(KMMsgStatusForwarded); } //----------------------------------------------------------------------------- void KMMainWin::slotSetThreadStatusQueued() { mHeaders->setThreadStatus(KMMsgStatusQueued); } //----------------------------------------------------------------------------- void KMMainWin::slotSetThreadStatusSent() { mHeaders->setThreadStatus(KMMsgStatusSent); } //----------------------------------------------------------------------------- void KMMainWin::slotNextMessage() { mHeaders->nextMessage(); } void KMMainWin::slotNextUnreadMessage() { mHeaders->nextUnreadMessage(); } void KMMainWin::slotNextImportantMessage() { //mHeaders->nextImportantMessage(); } void KMMainWin::slotPrevMessage() { mHeaders->prevMessage(); } void KMMainWin::slotPrevUnreadMessage() { mHeaders->prevUnreadMessage(); } void KMMainWin::slotPrevImportantMessage() { //mHeaders->prevImportantMessage(); } //----------------------------------------------------------------------------- //called from headers. Message must not be deleted on close void KMMainWin::slotMsgActivated(KMMessage *msg) { if (!msg->isComplete() && mFolder->protocol() == "imap") { KMImapJob *job = new KMImapJob(msg); connect(job, SIGNAL(messageRetrieved(KMMessage*)), SLOT(slotMsgActivated(KMMessage*))); return; } if (kernel->folderIsDraftOrOutbox(mFolder)) { slotEditMsg(); return; } assert(msg != NULL); KMReaderWin *win; win = new KMReaderWin; win->setShowCompleteMessage(true); win->setAutoDelete(true); win->setHtmlOverride(mFolderHtmlPref); KMMessage *newMessage = new KMMessage(); newMessage->fromString(msg->asString()); newMessage->setStatus(msg->status()); showMsg(win, newMessage); } //called from reader win. message must be deleted on close void KMMainWin::slotAtmMsg(KMMessage *msg) { KMReaderWin *win; assert(msg != NULL); win = new KMReaderWin; win->setAutoDelete(true); //delete on end showMsg(win, msg); } void KMMainWin::showMsg(KMReaderWin *win, KMMessage *msg) { KWin::setIcons(win->winId(), kapp->icon(), kapp->miniIcon()); win->setCodec(mCodec); win->setMsg(msg, true); // hack to work around strange QTimer bug win->resize(550,600); connect(win, SIGNAL(statusMsg(const QString&)), this, SLOT(statusMsg(const QString&))); connect(win, SIGNAL(popupMenu(KMMessage&,const KURL&,const QPoint&)), this, SLOT(slotMsgPopup(KMMessage&,const KURL&,const QPoint&))); connect(win, SIGNAL(urlClicked(const KURL&,int)), this, SLOT(slotUrlClicked(const KURL&,int))); connect(win, SIGNAL(showAtmMsg(KMMessage *)), this, SLOT(slotAtmMsg(KMMessage *))); QAccel *accel = new QAccel(win, "showMsg()"); accel->connectItem(accel->insertItem(Key_Up), win, SLOT(slotScrollUp())); accel->connectItem(accel->insertItem(Key_Down), win, SLOT(slotScrollDown())); accel->connectItem(accel->insertItem(Key_Prior), win, SLOT(slotScrollPrior())); accel->connectItem(accel->insertItem(Key_Next), win, SLOT(slotScrollNext())); //accel->connectItem(accel->insertItem(Key_S), // win, SLOT(slotCopyMsg())); win->show(); } //----------------------------------------------------------------------------- void KMMainWin::slotCopyText() { QString temp; temp = mMsgView->copyText(); kapp->clipboard()->setText(temp); } //----------------------------------------------------------------------------- void KMMainWin::slotMarkAll() { for (QListViewItemIterator it(mHeaders); it.current(); it++) mHeaders->setSelected( it.current(), TRUE ); } //----------------------------------------------------------------------------- void KMMainWin::slotSelectText() { mMsgView->selectAll(); } //----------------------------------------------------------------------------- void KMMainWin::slotUrlClicked(const KURL &aUrl, int) { KMComposeWin *win; KMMessage* msg; if (aUrl.protocol() == "mailto") { #ifdef IDENTITY_UOIDs uint id = 0; #else QString id = ""; #endif if ( mFolder ) id = mFolder->identity(); msg = new KMMessage; msg->initHeader(id); msg->setCharset("utf-8"); msg->setTo(aUrl.path()); QString query=aUrl.query(); while (!query.isEmpty()) { QString queryPart; int secondQuery = query.find('?',1); if (secondQuery != -1) queryPart = query.left(secondQuery); else queryPart = query; query = query.mid(queryPart.length()); if (queryPart.left(9) == "?subject=") msg->setSubject( KURL::decode_string(queryPart.mid(9)) ); else if (queryPart.left(6) == "?body=") // It is correct to convert to latin1() as URL should not contain // anything except ascii. msg->setBody( KURL::decode_string(queryPart.mid(6)).latin1() ); else if (queryPart.left(4) == "?cc=") msg->setCc( KURL::decode_string(queryPart.mid(4)) ); } win = new KMComposeWin(msg, id); win->setCharset("", TRUE); win->show(); } else if ((aUrl.protocol() == "http") || (aUrl.protocol() == "https") || (aUrl.protocol() == "ftp") || (aUrl.protocol() == "file") || (aUrl.protocol() == "ftps") || (aUrl.protocol() == "sftp" ) || (aUrl.protocol() == "help") || (aUrl.protocol() == "vnc") || (aUrl.protocol() == "smb")) { statusMsg(i18n("Opening URL...")); KMimeType::Ptr mime = KMimeType::findByURL( aUrl ); if (mime->name() == "application/x-desktop" || mime->name() == "application/x-executable" || mime->name() == "application/x-shellscript" ) { if (KMessageBox::warningYesNo( 0, i18n( "Do you really want to execute" " '%1'? " ).arg( aUrl.prettyURL() ) ) != KMessageBox::Yes) return; } (void) new KRun( aUrl ); } // handle own links else if( aUrl.protocol() == "kmail" ) { if( aUrl.path() == "showHTML" ) { mMsgView->setHtmlOverride(!mFolderHtmlPref); mMsgView->update( true ); } } } //----------------------------------------------------------------------------- void KMMainWin::slotMailtoCompose() { KMComposeWin *win; KMMessage *msg = new KMMessage; #ifdef IDENTITY_UOIDs uint id = 0; #else QString id = ""; #endif if ( mMsgCurrent ) id = mMsgCurrent->parent()->identity(); else if ( mFolder ) id = mFolder->identity(); msg->initHeader(id); msg->setCharset("utf-8"); msg->setTo(mUrlCurrent.path()); win = new KMComposeWin(msg, id); win->setCharset("", TRUE); win->show(); } //----------------------------------------------------------------------------- void KMMainWin::slotMailtoReply() { KMComposeWin *win; KMMessage *msg, *rmsg; /* if (!(msg = mHeaders->getMsg(-1))) return; */ msg = mMsgCurrent; rmsg = msg->createReply(FALSE, FALSE, mMsgView->copyText()); rmsg->setTo(mUrlCurrent.path()); #ifdef IDENTITY_UOIDs win = new KMComposeWin(rmsg, 0); #else win = new KMComposeWin(rmsg, QString::null); #endif win->setCharset(msg->codec()->mimeName(), TRUE); win->setReplyFocus(); win->show(); } //----------------------------------------------------------------------------- void KMMainWin::slotMailtoForward() { KMComposeWin *win; KMMessage *msg, *fmsg; /* if (!(msg = mHeaders->getMsg(-1))) return; */ msg = mMsgCurrent; fmsg = msg->createForward(); fmsg->setTo(mUrlCurrent.path()); win = new KMComposeWin(fmsg); win->setCharset(msg->codec()->mimeName(), TRUE); win->show(); } //----------------------------------------------------------------------------- void KMMainWin::slotMailtoAddAddrBook() { KMAddrBookExternal::addEmail(mUrlCurrent.path(), this); } //----------------------------------------------------------------------------- void KMMainWin::slotMailtoOpenAddrBook() { KMAddrBookExternal::openEmail(mUrlCurrent.path(), this); } //----------------------------------------------------------------------------- void KMMainWin::slotUrlCopy() { QClipboard* clip = QApplication::clipboard(); if (mUrlCurrent.protocol() == "mailto") { // put the url into the mouse selection and the clipboard clip->setSelectionMode(true); clip->setText(mUrlCurrent.path()); clip->setSelectionMode(false); clip->setText(mUrlCurrent.path()); statusMsg(i18n("Address copied to clipboard.")); } else { // put the url into the mouse selection and the clipboard clip->setSelectionMode(true); clip->setText(mUrlCurrent.url()); clip->setSelectionMode(false); clip->setText(mUrlCurrent.url()); statusMsg(i18n("URL copied to clipboard.")); } } //----------------------------------------------------------------------------- void KMMainWin::slotUrlOpen() { if (mUrlCurrent.isEmpty()) return; // mMsgView->slotUrlOpen(mUrlCurrent, QString::null, 0); mMsgView->slotUrlOpen( mUrlCurrent, KParts::URLArgs() ); } //----------------------------------------------------------------------------- void KMMainWin::slotUrlSave() { if (mUrlCurrent.isEmpty()) return; KURL saveUrl = KFileDialog::getSaveURL(mUrlCurrent.fileName(), QString::null, this); if (saveUrl.isEmpty()) return; if (KIO::NetAccess::exists(saveUrl)) { if (KMessageBox::warningContinueCancel(0, i18n("File %1 exists.\nDo you want to replace it?") .arg(saveUrl.prettyURL()), i18n("Save to File"), i18n("&Replace")) != KMessageBox::Continue) return; } KIO::Job *job = KIO::file_copy(mUrlCurrent, saveUrl, -1, true); connect(job, SIGNAL(result(KIO::Job*)), SLOT(slotUrlSaveResult(KIO::Job*))); } //----------------------------------------------------------------------------- void KMMainWin::slotUrlSaveResult(KIO::Job *job) { if (job->error()) job->showErrorDialog(); } //----------------------------------------------------------------------------- void KMMainWin::slotMsgPopup(KMMessage &aMsg, const KURL &aUrl, const QPoint& aPoint) { KPopupMenu * menu = new KPopupMenu; updateMessageMenu(); mMsgCurrent = jumpToMessage(&aMsg); mUrlCurrent = aUrl; if (!aUrl.isEmpty()) { if (aUrl.protocol() == "mailto") { // popup on a mailto URL menu->insertItem(i18n("Send To..."), this, SLOT(slotMailtoCompose())); if ( mMsgCurrent ) { menu->insertItem(i18n("Send Reply To..."), this, SLOT(slotMailtoReply())); menu->insertItem(i18n("Forward To..."), this, SLOT(slotMailtoForward())); menu->insertSeparator(); } menu->insertItem(i18n("Add to Addressbook"), this, SLOT(slotMailtoAddAddrBook())); menu->insertItem(i18n("Open in Addressbook..."), this, SLOT(slotMailtoOpenAddrBook())); menu->insertItem(i18n("Copy to Clipboard"), this, SLOT(slotUrlCopy())); } else { // popup on a not-mailto URL menu->insertItem(i18n("Open URL..."), this, SLOT(slotUrlOpen())); menu->insertItem(i18n("Save Link As..."), this, SLOT(slotUrlSave())); menu->insertItem(i18n("Copy to Clipboard"), this, SLOT(slotUrlCopy())); } } else { // popup somewhere else (i.e., not a URL) on the message if (!mMsgCurrent) // no messages { delete menu; return; } bool out_folder = kernel->folderIsDraftOrOutbox(mFolder); if ( out_folder ) editAction->plug(menu); else { replyAction->plug(menu); replyAllAction->plug(menu); action("message_forward")->plug(menu); bounceAction->plug(menu); } menu->insertSeparator(); if ( !out_folder ) { filterMenu->plug( menu ); statusMenu->plug( menu ); threadStatusMenu->plug( menu ); } copyActionMenu->plug( menu ); moveActionMenu->plug( menu ); menu->insertSeparator(); toggleFixFontAction->plug(menu); viewSourceAction->plug(menu); menu->insertSeparator(); printAction->plug(menu); saveAsAction->plug(menu); menu->insertSeparator(); trashAction->plug(menu); deleteAction->plug(menu); } menu->exec(aPoint, 0); delete menu; } //----------------------------------------------------------------------------- void KMMainWin::getAccountMenu() { QStringList actList; actMenu->clear(); actList = kernel->acctMgr()->getAccounts(false); QStringList::Iterator it; int id = 0; for(it = actList.begin(); it != actList.end() ; ++it, id++) actMenu->insertItem((*it).replace(QRegExp("&"),"&&"), id); } // little helper function KRadioAction * KMMainWin::actionForHeaderStyle( int style ) { const char * actionName = 0; switch( style ) { case KMReaderWin::HdrFancy: actionName = "view_headers_fancy"; break; case KMReaderWin::HdrBrief: actionName = "view_headers_brief"; break; case KMReaderWin::HdrStandard: actionName = "view_headers_standard"; break; case KMReaderWin::HdrLong: actionName = "view_headers_long"; break; case KMReaderWin::HdrAll: actionName = "view_headers_all"; break; } if ( actionName ) return static_cast(actionCollection()->action(actionName)); else return 0; } KRadioAction * KMMainWin::actionForAttachmentStyle( int style ) { const char * actionName = 0; switch ( style ) { case KMReaderWin::IconicAttmnt: actionName = "view_attachments_as_icons"; break; case KMReaderWin::SmartAttmnt: actionName = "view_attachments_smart"; break; case KMReaderWin::InlineAttmnt: actionName = "view_attachments_inline"; break; case KMReaderWin::HideAttmnt: actionName = "view_attachments_hide"; break; } if ( actionName ) return static_cast(actionCollection()->action(actionName)); else return 0; } //----------------------------------------------------------------------------- void KMMainWin::setupMenuBar() { //----- File Menu (void) new KAction( i18n("New &Window..."), "window_new", 0, this, SLOT(slotNewMailReader()), actionCollection(), "new_mail_client" ); saveAsAction = new KAction( i18n("Save &As..."), "filesave", KStdAccel::shortcut(KStdAccel::Save), this, SLOT(slotSaveMsg()), actionCollection(), "file_save_as" ); printAction = KStdAction::print (this, SLOT(slotPrintMsg()), actionCollection()); (void) new KAction( i18n("&Compact All Folders"), 0, this, SLOT(slotCompactAll()), actionCollection(), "compact_all_folders" ); (void) new KAction( i18n("&Expire All Folders"), 0, this, SLOT(slotExpireAll()), actionCollection(), "expire_all_folders" ); (void) new KAction( i18n("Check &Mail"), "mail_get", CTRL+Key_L, this, SLOT(slotCheckMail()), actionCollection(), "check_mail" ); KActionMenu *actActionMenu = new KActionMenu( i18n("Check Mail &In"), "mail_get", actionCollection(), "check_mail_in" ); actActionMenu->setDelayed(true); //needed for checking "all accounts" connect(actActionMenu,SIGNAL(activated()),this,SLOT(slotCheckMail())); actMenu = actActionMenu->popupMenu(); connect(actMenu,SIGNAL(activated(int)),this,SLOT(slotCheckOneAccount(int))); connect(actMenu,SIGNAL(aboutToShow()),this,SLOT(getAccountMenu())); (void) new KAction( i18n("&Send Queued Messages"), "mail_send", 0, this, SLOT(slotSendQueued()), actionCollection(), "send_queued"); KStdAction::quit( this, SLOT(slotQuit()), actionCollection()); //----- Tools menu (void) new KAction( i18n("&Address Book..."), "contents", 0, this, SLOT(slotAddrBook()), actionCollection(), "addressbook" ); (void) new KAction( i18n("&Import..."), "fileopen", 0, this, SLOT(slotImport()), actionCollection(), "import" ); //----- Edit Menu KStdAction::undo( this, SLOT(slotUndo()), actionCollection(), "edit_undo"); KStdAction::copy( this, SLOT(slotCopyText()), actionCollection(), "copy"); trashAction = new KAction( KGuiItem( i18n("&Move to Trash"), "edittrash", i18n("Move message to trashcan") ), "D;Delete", this, SLOT(slotTrashMsg()), actionCollection(), "move_to_trash" ); deleteAction = new KAction( i18n("&Delete"), "editdelete", SHIFT+Key_Delete, this, SLOT(slotDeleteMsg()), actionCollection(), "delete" ); (void) new KAction( i18n("&Find Messages..."), "mail_find", Key_S, this, SLOT(slotSearch()), actionCollection(), "search_messages" ); (void) new KAction( i18n("&Find in Message..."), "find", KStdAccel::shortcut(KStdAccel::Find), this, SLOT(slotFind()), actionCollection(), "find_in_messages" ); (void) new KAction( i18n("Select &All Messages"), Key_K, this, SLOT(slotMarkAll()), actionCollection(), "mark_all_messages" ); (void) new KAction( i18n("Select Message &Text"), KStdAccel::shortcut(KStdAccel::SelectAll), this, SLOT(slotSelectText()), actionCollection(), "mark_all_text" ); //----- Folder Menu (void) new KAction( i18n("&New Folder..."), "folder_new", 0, this, SLOT(slotAddFolder()), actionCollection(), "new_folder" ); modifyFolderAction = new KAction( i18n("&Properties..."), "configure", 0, this, SLOT(slotModifyFolder()), actionCollection(), "modify" ); markAllAsReadAction = new KAction( i18n("Mark All Messages as &Read"), "goto", 0, this, SLOT(slotMarkAllAsRead()), actionCollection(), "mark_all_as_read" ); expireFolderAction = new KAction(i18n("&Expire"), 0, this, SLOT(slotExpireFolder()), actionCollection(), "expire"); compactFolderAction = new KAction( i18n("&Compact"), 0, this, SLOT(slotCompactFolder()), actionCollection(), "compact" ); emptyFolderAction = new KAction( i18n("&Move All Messages to Trash"), "edittrash", 0, this, SLOT(slotEmptyFolder()), actionCollection(), "empty" ); removeFolderAction = new KAction( i18n("&Delete Folder"), "editdelete", 0, this, SLOT(slotRemoveFolder()), actionCollection(), "delete_folder" ); preferHtmlAction = new KToggleAction( i18n("Prefer &HTML to Plain Text"), 0, this, SLOT(slotOverrideHtml()), actionCollection(), "prefer_html" ); threadMessagesAction = new KToggleAction( i18n("&Thread Messages"), 0, this, SLOT(slotOverrideThread()), actionCollection(), "thread_messages" ); //----- Message Menu (void) new KAction( i18n("&New Message..."), "mail_new", KStdAccel::shortcut(KStdAccel::New), this, SLOT(slotCompose()), actionCollection(), "new_message" ); (void) new KAction( i18n("New Message t&o Mailing-List..."), "mail_post_to", 0, this, SLOT(slotPostToML()), actionCollection(), "post_message" ); replyAction = new KAction( i18n("&Reply..."), "mail_reply", Key_R, this, SLOT(slotReplyToMsg()), actionCollection(), "reply" ); noQuoteReplyAction = new KAction( i18n("Reply Without &Quote..."), SHIFT+Key_R, this, SLOT(slotNoQuoteReplyToMsg()), actionCollection(), "noquotereply" ); replyAllAction = new KAction( i18n("Reply to &All..."), "mail_replyall", Key_A, this, SLOT(slotReplyAllToMsg()), actionCollection(), "reply_all" ); replyListAction = new KAction( i18n("Reply to Mailing-&List..."), "mail_replylist", Key_L, this, SLOT(slotReplyListToMsg()), actionCollection(), "reply_list" ); KActionMenu * forwardMenu = new KActionMenu( i18n("Message->","&Forward"), "mail_forward", actionCollection(), "message_forward" ); connect( forwardMenu, SIGNAL(activated()), this, SLOT(slotForward()) ); forwardAction = new KAction( i18n("&Inline..."), "mail_forward", SHIFT+Key_F, this, SLOT(slotForwardMsg()), actionCollection(), "message_forward_inline" ); forwardMenu->insert( forwardAction ); forwardAttachedAction = new KAction( i18n("Message->Forward->","As &Attachment..."), "mail_forward", Key_F, this, SLOT(slotForwardAttachedMsg()), actionCollection(), "message_forward_as_attachment" ); forwardMenu->insert( forwardAttachedAction ); redirectAction = new KAction( i18n("Message->Forward->","&Redirect..."), Key_E, this, SLOT(slotRedirectMsg()), actionCollection(), "message_forward_redirect" ); forwardMenu->insert( redirectAction ); bounceAction = new KAction( i18n("&Bounce..."), 0, this, SLOT(slotBounceMsg()), actionCollection(), "bounce" ); sendAgainAction = new KAction( i18n("Send A&gain..."), 0, this, SLOT(slotResendMsg()), actionCollection(), "send_again" ); //----- Message-Encoding Submenu mEncoding = new KSelectAction( i18n( "&Set Encoding" ), "charset", 0, this, SLOT( slotSetEncoding() ), actionCollection(), "encoding" ); QStringList encodings = KMMsgBase::supportedEncodings(FALSE); encodings.prepend( i18n( "Auto" ) ); mEncoding->setItems( encodings ); mEncoding->setCurrentItem(0); QStringList::Iterator it; int i = 0; for( it = encodings.begin(); it != encodings.end(); ++it) { if ( KGlobal::charsets()->encodingForName(*it ) == QString(mEncodingStr) ) { mEncoding->setCurrentItem( i ); break; } i++; } editAction = new KAction( i18n("&Edit Message"), "edit", Key_T, this, SLOT(slotEditMsg()), actionCollection(), "edit" ); //----- Create filter submenu filterMenu = new KActionMenu( i18n("&Create Filter"), actionCollection(), "create_filter" ); KAction *subjectFilterAction = new KAction( i18n("Filter on &Subject..."), 0, this, SLOT(slotSubjectFilter()), actionCollection(), "subject_filter"); filterMenu->insert( subjectFilterAction ); KAction *fromFilterAction = new KAction( i18n("Filter on &From..."), 0, this, SLOT(slotFromFilter()), actionCollection(), "from_filter"); filterMenu->insert( fromFilterAction ); KAction *toFilterAction = new KAction( i18n("Filter on &To..."), 0, this, SLOT(slotToFilter()), actionCollection(), "to_filter"); filterMenu->insert( toFilterAction ); mlistFilterAction = new KAction( i18n("Filter on Mailing-&List..."), 0, this, SLOT(slotMailingListFilter()), actionCollection(), "mlist_filter"); filterMenu->insert( mlistFilterAction ); //----- "Mark Message" submenu statusMenu = new KActionMenu ( i18n( "Mar&k Message" ), actionCollection(), "set_status" ); statusMenu->insert(new KAction(KGuiItem(i18n("Mark Message as &New"), "kmmsgnew", i18n("Mark selected messages as new")), 0, this, SLOT(slotSetMsgStatusNew()), actionCollection(), "status_new" )); statusMenu->insert(new KAction(KGuiItem(i18n("Mark Message as &Unread"), "kmmsgunseen", i18n("Mark selected messages as unread")), 0, this, SLOT(slotSetMsgStatusUnread()), actionCollection(), "status_unread")); statusMenu->insert(new KAction(KGuiItem(i18n("Mark Message as &Read"), "kmmsgold", i18n("Mark selected messages as read")), 0, this, SLOT(slotSetMsgStatusRead()), actionCollection(), "status_read")); statusMenu->insert(new KAction(KGuiItem(i18n("Mark Message as R&eplied"), "kmmsgreplied", i18n("Mark selected messages as replied")), 0, this, SLOT(slotSetMsgStatusReplied()), actionCollection(), "status_replied")); statusMenu->insert(new KAction(KGuiItem(i18n("Mark Message as &Forwarded"), "kmmsgforwarded", i18n("Mark selected messages as forwarded")), 0, this, SLOT(slotSetMsgStatusForwarded()), actionCollection(), "status_forwarded")); statusMenu->insert(new KAction(KGuiItem(i18n("Mark Message as &Queued"), "kmmsgqueued", i18n("Mark selected messages as queued")), 0, this, SLOT(slotSetMsgStatusQueued()), actionCollection(), "status_queued")); statusMenu->insert(new KAction(KGuiItem(i18n("Mark Message as &Sent"), "kmmsgsent", i18n("Mark selected messages as sent")), 0, this, SLOT(slotSetMsgStatusSent()), actionCollection(), "status_sent")); statusMenu->insert(new KAction(KGuiItem(i18n("Mark Message as &Important"), "kmmsgflag", i18n("Mark selected messages as important")), 0, this, SLOT(slotSetMsgStatusFlag()), actionCollection(), "status_flag")); //----- "Mark Thread" submenu threadStatusMenu = new KActionMenu ( i18n( "Mark &Thread" ), actionCollection(), "thread_status" ); threadStatusMenu->insert(new KAction(KGuiItem(i18n("Mark Thread as &New"), "kmmsgnew", i18n("Mark all messages in the selected thread as new")), 0, this, SLOT(slotSetThreadStatusNew()), actionCollection(), "thread_new")); threadStatusMenu->insert(new KAction(KGuiItem(i18n("Mark Thread as &Unread"), "kmmsgunseen", i18n("Mark all messages in the selected thread as unread")), 0, this, SLOT(slotSetThreadStatusUnread()), actionCollection(), "thread_unread")); threadStatusMenu->insert(new KAction(KGuiItem(i18n("Mark Thread as &Read"), "kmmsgold", i18n("Mark all messages in the selected thread as read")), 0, this, SLOT(slotSetThreadStatusRead()), actionCollection(), "thread_read")); threadStatusMenu->insert(new KAction(KGuiItem(i18n("Mark Thread as R&eplied"), "kmmsgreplied", i18n("Mark all messages in the selected thread as replied")), 0, this, SLOT(slotSetThreadStatusReplied()), actionCollection(), "thread_replied")); threadStatusMenu->insert(new KAction(KGuiItem(i18n("Mark Thread as &Forwarded"), "kmmsgforwarded", i18n("Mark all messages in the selected thread as forwarded")), 0, this, SLOT(slotSetThreadStatusForwarded()), actionCollection(), "thread_forwarded")); threadStatusMenu->insert(new KAction(KGuiItem(i18n("Mark Thread as &Queued"), "kmmsgqueued", i18n("Mark all messages in the selected thread as queued")), 0, this, SLOT(slotSetThreadStatusQueued()), actionCollection(), "thread_queued")); threadStatusMenu->insert(new KAction(KGuiItem(i18n("Mark Thread as &Sent"), "kmmsgsent", i18n("Mark all messages in the selected thread as sent")), 0, this, SLOT(slotSetThreadStatusSent()), actionCollection(), "thread_sent")); threadStatusMenu->insert(new KAction(KGuiItem(i18n("Mark Thread as &Important"), "kmmsgflag", i18n("Mark all messages in the selected thread as important")), 0, this, SLOT(slotSetThreadStatusFlag()), actionCollection(), "thread_flag")); moveActionMenu = new KActionMenu( i18n("&Move To" ), actionCollection(), "move_to" ); copyActionMenu = new KActionMenu( i18n("&Copy To" ), actionCollection(), "copy_to" ); (void) new KAction( i18n("Appl&y Filters"), "filter", CTRL+Key_J, this, SLOT(slotApplyFilters()), actionCollection(), "apply_filters" ); //----- View Menu KRadioAction * raction = 0; // "Headers" submenu: KActionMenu * headerMenu = new KActionMenu( i18n("View->", "&Headers"), actionCollection(), "view_headers" ); headerMenu->setToolTip( i18n("Choose display style of message headers") ); connect( headerMenu, SIGNAL(activated()), SLOT(slotCycleHeaderStyles()) ); raction = new KRadioAction( i18n("View->headers->", "&Fancy Headers"), 0, this, SLOT(slotFancyHeaders()), actionCollection(), "view_headers_fancy" ); raction->setToolTip( i18n("Show the list of headers in a fancy format") ); raction->setExclusiveGroup( "view_headers_group" ); headerMenu->insert( raction ); raction = new KRadioAction( i18n("View->headers->", "&Brief Headers"), 0, this, SLOT(slotBriefHeaders()), actionCollection(), "view_headers_brief" ); raction->setToolTip( i18n("Show brief list of message headers") ); raction->setExclusiveGroup( "view_headers_group" ); headerMenu->insert( raction ); raction = new KRadioAction( i18n("View->headers->", "&Standard Headers"), 0, this, SLOT(slotStandardHeaders()), actionCollection(), "view_headers_standard" ); raction->setToolTip( i18n("Show standard list of message headers") ); raction->setExclusiveGroup( "view_headers_group" ); headerMenu->insert( raction ); raction = new KRadioAction( i18n("View->headers->", "&Long Headers"), 0, this, SLOT(slotLongHeaders()), actionCollection(), "view_headers_long" ); raction->setToolTip( i18n("Show long list of message headers") ); raction->setExclusiveGroup( "view_headers_group" ); headerMenu->insert( raction ); raction = new KRadioAction( i18n("View->headers->", "&All Headers"), 0, this, SLOT(slotAllHeaders()), actionCollection(), "view_headers_all" ); raction->setToolTip( i18n("Show all message headers") ); raction->setExclusiveGroup( "view_headers_group" ); headerMenu->insert( raction ); // check the right one: raction = actionForHeaderStyle( mMsgView->headerStyle() ); if ( raction ) raction->setChecked( true ); // "Attachments" submenu: KActionMenu * attachmentMenu = new KActionMenu( i18n("View->", "&Attachments"), actionCollection(), "view_attachments" ); connect( attachmentMenu, SIGNAL(activated()), SLOT(slotCycleAttachmentStyles()) ); attachmentMenu->setToolTip( i18n("Choose display style of attachments") ); raction = new KRadioAction( i18n("View->attachments->", "&As Icons"), 0, this, SLOT(slotIconicAttachments()), actionCollection(), "view_attachments_as_icons" ); raction->setToolTip( i18n("Show all attachments as icons. Click to see them.") ); raction->setExclusiveGroup( "view_attachments_group" ); attachmentMenu->insert( raction ); raction = new KRadioAction( i18n("View->attachments->", "&Smart"), 0, this, SLOT(slotSmartAttachments()), actionCollection(), "view_attachments_smart" ); raction->setToolTip( i18n("Show attachments as suggested by sender.") ); raction->setExclusiveGroup( "view_attachments_group" ); attachmentMenu->insert( raction ); raction = new KRadioAction( i18n("View->attachments->", "&Inline"), 0, this, SLOT(slotInlineAttachments()), actionCollection(), "view_attachments_inline" ); raction->setToolTip( i18n("Show all attachments inline (if possible)") ); raction->setExclusiveGroup( "view_attachments_group" ); attachmentMenu->insert( raction ); raction = new KRadioAction( i18n("View->attachments->", "&Hide"), 0, this, SLOT(slotHideAttachments()), actionCollection(), "view_attachments_hide" ); raction->setToolTip( i18n("Don't show attachments in the message viewer") ); raction->setExclusiveGroup( "view_attachments_group" ); attachmentMenu->insert( raction ); // check the right one: raction = actionForAttachmentStyle( mMsgView->attachmentStyle() ); if ( raction ) raction->setChecked( true ); unreadColumnToggle = new KToggleAction( i18n("View->", "&Unread Column"), 0, this, SLOT(slotToggleUnreadColumn()), actionCollection(), "view_columns_unread" ); unreadColumnToggle->setToolTip( i18n("Toggle display of column showing the " "number of unread messages in folders.") ); unreadColumnToggle->setChecked( mFolderTree->isUnreadActive() ); totalColumnToggle = new KToggleAction( i18n("View->", "&Total Column"), 0, this, SLOT(slotToggleTotalColumn()), actionCollection(), "view_columns_total" ); totalColumnToggle->setToolTip( i18n("Toggle display of column showing the " "total number of messages in folders.") ); totalColumnToggle->setChecked( mFolderTree->isTotalActive() ); (void)new KAction( KGuiItem( i18n("View->","&Expand Thread"), QString::null, i18n("Expand the current thread") ), Key_Period, this, SLOT(slotExpandThread()), actionCollection(), "expand_thread" ); (void)new KAction( KGuiItem( i18n("View->","&Collapse Thread"), QString::null, i18n("Collapse the current thread") ), Key_Comma, this, SLOT(slotCollapseThread()), actionCollection(), "collapse_thread" ); (void)new KAction( KGuiItem( i18n("View->","Ex&pand All Threads"), QString::null, i18n("Expand all threads in the current folder") ), CTRL+Key_Period, this, SLOT(slotExpandAllThreads()), actionCollection(), "expand_all_threads" ); (void)new KAction( KGuiItem( i18n("View->","C&ollapse All Threads"), QString::null, i18n("Collapse all threads in the current folder") ), CTRL+Key_Comma, this, SLOT(slotCollapseAllThreads()), actionCollection(), "collapse_all_threads" ); toggleFixFontAction = new KToggleAction( i18n("Use Fi&xed Font"), Key_X, this, SLOT(slotToggleFixedFont()), actionCollection(), "toggle_fixedfont" ); viewSourceAction = new KAction( i18n("&View Source"), Key_V, this, SLOT(slotShowMsgSrc()), actionCollection(), "view_source" ); //----- Go Menu new KAction( KGuiItem( i18n("&Next Message"), QString::null, i18n("Go to the next message") ), "N;Right", this, SLOT(slotNextMessage()), actionCollection(), "go_next_message" ); new KAction( KGuiItem( i18n("Next &Unread Message"), "next", i18n("Go to the next unread message") ), Key_Plus, this, SLOT(slotNextUnreadMessage()), actionCollection(), "go_next_unread_message" ); /* ### needs better support from folders: new KAction( KGuiItem( i18n("Next &Important Message"), QString::null, i18n("Go to the next important message") ), 0, this, SLOT(slotNextImportantMessage()), actionCollection(), "go_next_important_message" ); */ new KAction( KGuiItem( i18n("&Previous Message"), QString::null, i18n("Go to the previous message") ), "P;Left", this, SLOT(slotPrevMessage()), actionCollection(), "go_prev_message" ); new KAction( KGuiItem( i18n("Previous Unread &Message"), "previous", i18n("Go to the previous unread message") ), Key_Minus, this, SLOT(slotPrevUnreadMessage()), actionCollection(), "go_prev_unread_message" ); /* needs better support from folders: new KAction( KGuiItem( i18n("Previous I&mportant Message"), QString::null, i18n("Go to the previous important message") ), 0, this, SLOT(slotPrevImportantMessage()), actionCollection(), "go_prev_important_message" ); */ new KAction( KGuiItem( i18n("Next Unread &Folder"), QString::null, i18n("Go to the next folder with unread messages") ), CTRL+Key_Plus, this, SLOT(slotNextUnreadFolder()), actionCollection(), "go_next_unread_folder" ); new KAction( KGuiItem( i18n("Previous Unread F&older"), QString::null, i18n("Go to the previous folder with unread messages") ), CTRL+Key_Minus, this, SLOT(slotPrevUnreadFolder()), actionCollection(), "go_prev_unread_folder" ); new KAction( KGuiItem( i18n("Go->","Next Unread &Text"), QString::null, i18n("Go to the next unread text"), i18n("Scroll down current message. " "If at end of current message, " "go to next unread message.") ), Key_Space, this, SLOT(slotReadOn()), actionCollection(), "go_next_unread_text" ); //----- Settings Menu toolbarAction = KStdAction::showToolbar(this, SLOT(slotToggleToolBar()), actionCollection()); statusbarAction = KStdAction::showStatusbar(this, SLOT(slotToggleStatusBar()), actionCollection()); KStdAction::keyBindings(this, SLOT(slotEditKeys()), actionCollection()); KStdAction::configureToolbars(this, SLOT(slotEditToolbars()), actionCollection()); #if KDE_VERSION >= 306 KStdAction::configureNotifications(this, SLOT(slotEditNotifications()), actionCollection()); #endif KStdAction::preferences(this, SLOT(slotSettings()), actionCollection()); #if KDE_VERSION >= 305 // KDE 3.1 KStdAction::tipOfDay( this, SLOT( slotShowTip() ), actionCollection() ); #else (void) new KAction( KGuiItem( i18n("Tip of the &Day..."), "idea", i18n("Show \"Tip of the Day\"") ), 0, this, SLOT(slotShowTip()), actionCollection(), "help_show_tip" ); #endif (void) new KAction( i18n("Configure &Filters..."), 0, this, SLOT(slotFilter()), actionCollection(), "filter" ); (void) new KAction( i18n("Configure &POP Filters..."), 0, this, SLOT(slotPopFilter()), actionCollection(), "popFilter" ); (void) new KAction( KGuiItem( i18n("KMail &Introduction"), 0, i18n("Display KMail's Welcome Page") ), 0, this, SLOT(slotIntro()), actionCollection(), "help_kmail_welcomepage" ); createGUI( "kmmainwin.rc", false ); connect( guiFactory()->container("folder", this), SIGNAL( aboutToShow() ), this, SLOT( updateFolderMenu() )); connect( guiFactory()->container("message", this), SIGNAL( aboutToShow() ), this, SLOT( updateMessageMenu() )); // contains "Create Filter" actions. connect( guiFactory()->container("tools", this), SIGNAL( aboutToShow() ), this, SLOT( updateMessageMenu() )); // contains "View source" action. connect( guiFactory()->container("view", this), SIGNAL( aboutToShow() ), this, SLOT( updateMessageMenu() )); conserveMemory(); menutimer = new QTimer( this, "menutimer" ); connect( menutimer, SIGNAL( timeout() ), SLOT( updateMessageActions() ) ); updateMessageActions(); } //----------------------------------------------------------------------------- void KMMainWin::slotToggleToolBar() { if(toolBar("mainToolBar")->isVisible()) toolBar("mainToolBar")->hide(); else toolBar("mainToolBar")->show(); } void KMMainWin::slotToggleStatusBar() { if (statusBar()->isVisible()) statusBar()->hide(); else statusBar()->show(); } void KMMainWin::slotEditToolbars() { saveMainWindowSettings(kapp->config(), "MainWindow"); KEditToolbar dlg(actionCollection(), "kmmainwin.rc"); connect( &dlg, SIGNAL(newToolbarConfig()), SLOT(slotUpdateToolbars()) ); dlg.exec(); } void KMMainWin::slotEditNotifications() { #if KDE_VERSION >= 306 KNotifyDialog::configure(this); #endif } void KMMainWin::slotUpdateToolbars() { createGUI("kmmainwin.rc"); applyMainWindowSettings(kapp->config(), "MainWindow"); toolbarAction->setChecked(!toolBar()->isHidden()); } void KMMainWin::slotEditKeys() { KKeyDialog::configure( actionCollection() #if KDE_VERSION >= 306 , true /*allow on-letter shortcuts*/ #endif ); } //----------------------------------------------------------------------------- void KMMainWin::setupStatusBar() { littleProgress = new KMLittleProgressDlg( statusBar() ); statusBar()->addWidget( littleProgress, 0 , true ); mMessageStatusId = 1; statusBar()->insertItem(i18n(" Initializing..."), 1, 1 ); statusBar()->setItemAlignment( 1, AlignLeft | AlignVCenter ); littleProgress->show(); connect( KMBroadcastStatus::instance(), SIGNAL(statusProgressEnable( bool )), littleProgress, SLOT(slotEnable( bool ))); connect( KMBroadcastStatus::instance(), SIGNAL(statusProgressPercent( unsigned long )), littleProgress, SLOT(slotJustPercent( unsigned long ))); connect( KMBroadcastStatus::instance(), SIGNAL(resetRequested()), littleProgress, SLOT(slotClean())); connect( KMBroadcastStatus::instance(), SIGNAL(statusMsg( const QString& )), this, SLOT(statusMsg( const QString& ))); } void KMMainWin::slotQuit() { close(); } void KMMainWin::slotReadOn() { if ( !mMsgView ) return; if ( !mMsgView->atBottom() ) { mMsgView->slotJumpDown(); return; } int i = mHeaders->findUnread(true, -1, false, false); if ( i < 0 ) // let's try from start, what gives? i = mHeaders->findUnread(true, 0, false, true); if ( i >= 0 ) { mHeaders->setCurrentMsg(i); QTimer::singleShot( 100, mHeaders, SLOT( ensureCurrentItemVisible() ) ); return; } mFolderTree->nextUnreadFolder( true ); } void KMMainWin::slotNextUnreadFolder() { if ( !mFolderTree ) return; mFolderTree->nextUnreadFolder(); } void KMMainWin::slotPrevUnreadFolder() { if ( !mFolderTree ) return; mFolderTree->prevUnreadFolder(); } void KMMainWin::slotExpandThread() { mHeaders->slotExpandOrCollapseThread( true ); // expand } void KMMainWin::slotCollapseThread() { mHeaders->slotExpandOrCollapseThread( false ); // collapse } void KMMainWin::slotExpandAllThreads() { mHeaders->slotExpandOrCollapseAllThreads( true ); // expand } void KMMainWin::slotCollapseAllThreads() { mHeaders->slotExpandOrCollapseAllThreads( false ); // collapse } //----------------------------------------------------------------------------- void KMMainWin::moveSelectedToFolder( int menuId ) { if (mMenuToFolder[menuId]) mHeaders->moveMsgToFolder( mMenuToFolder[menuId] ); } //----------------------------------------------------------------------------- void KMMainWin::copySelectedToFolder(int menuId ) { if (mMenuToFolder[menuId]) mHeaders->copyMsgToFolder( mMenuToFolder[menuId] ); } //----------------------------------------------------------------------------- QPopupMenu* KMMainWin::folderToPopupMenu(bool move, QObject *receiver, KMMenuToFolder *aMenuToFolder, QPopupMenu *menu ) { while ( menu->count() ) { QPopupMenu *popup = menu->findItem( menu->idAt( 0 ) )->popup(); if (popup) delete popup; else menu->removeItemAt( 0 ); } QListViewItem *startItem = mFolderTree->firstChild(); if (!startItem->nextSibling()) { makeFolderMenu(dynamic_cast(startItem), move, receiver, aMenuToFolder, menu); return menu; } for (QListViewItem *item = startItem; item; item = item->nextSibling()) { // operate on top-level items QString label = item->text(0); // make a new Submenu QPopupMenu* subMenu = new QPopupMenu(menu); subMenu = makeFolderMenu(dynamic_cast(item), move, receiver, aMenuToFolder, subMenu); menu->insertItem( label, subMenu ); } return menu; } //----------------------------------------------------------------------------- QPopupMenu* KMMainWin::makeFolderMenu(KMFolderTreeItem* item, bool move, QObject *receiver, KMMenuToFolder *aMenuToFolder, QPopupMenu *menu ) { // connect the signals if (move) { disconnect(menu, SIGNAL(activated(int)), receiver, SLOT(moveSelectedToFolder(int))); connect(menu, SIGNAL(activated(int)), receiver, SLOT(moveSelectedToFolder(int))); } else { disconnect(menu, SIGNAL(activated(int)), receiver, SLOT(copySelectedToFolder(int))); connect(menu, SIGNAL(activated(int)), receiver, SLOT(copySelectedToFolder(int))); } if (item->folder() && !item->folder()->isDir() && !item->folder()->noContent()) { int menuId; if (move) menuId = menu->insertItem(i18n("Move to this Folder")); else menuId = menu->insertItem(i18n("Copy to this Folder")); aMenuToFolder->insert( menuId, item->folder() ); menu->insertSeparator(); } for (QListViewItem *it = item->firstChild(); it; it = it->nextSibling()) { KMFolderTreeItem* fti = dynamic_cast(it); if (fti->folder()) { QString label = fti->text(0); label.replace(QRegExp("&"),QString("&&")); if (fti->firstChild()) { // descend QPopupMenu *subMenu = makeFolderMenu(fti, move, receiver, aMenuToFolder, new QPopupMenu(menu, "subMenu")); menu->insertItem(label, subMenu); } else { // insert an item if (!fti->folder()->isDir()) { int menuId = menu->insertItem(label); aMenuToFolder->insert( menuId, fti->folder() ); } } } } return menu; } //----------------------------------------------------------------------------- void KMMainWin::updateMessageMenu() { mMenuToFolder.clear(); folderToPopupMenu( true, this, &mMenuToFolder, moveActionMenu->popupMenu() ); folderToPopupMenu( false, this, &mMenuToFolder, copyActionMenu->popupMenu() ); updateMessageActions(); } void KMMainWin::startUpdateMessageActionsTimer() { menutimer->stop(); menutimer->start( 20, true ); } void KMMainWin::updateMessageActions() { int count = 0; QPtrList selectedItems; if ( mFolder ) { for (QListViewItem *item = mHeaders->firstChild(); item; item = item->itemBelow()) if (item->isSelected() ) selectedItems.append(item); if ( selectedItems.isEmpty() && mFolder->count() ) // there will always be one in mMsgView count = 1; else count = selectedItems.count(); } mlistFilterAction->setText( i18n("Filter on Mailing-List...") ); bool allSelectedInCommonThread = true; if ( count > 1 && mHeaders->isThreaded() ) { QListViewItem * curItemParent = mHeaders->currentItem(); while ( curItemParent->parent() ) curItemParent = curItemParent->parent(); for ( QPtrListIterator it( selectedItems ) ; it.current() ; ++ it ) { QListViewItem * item = *it; while ( item->parent() ) item = item->parent(); if ( item != curItemParent ) { allSelectedInCommonThread = false; break; } } } bool mass_actions = count >= 1; statusMenu->setEnabled( mass_actions ); threadStatusMenu->setEnabled( mass_actions && allSelectedInCommonThread && mHeaders->isThreaded() ); moveActionMenu->setEnabled( mass_actions ); copyActionMenu->setEnabled( mass_actions ); trashAction->setEnabled( mass_actions ); deleteAction->setEnabled( mass_actions ); action( "message_forward" )->setEnabled( mass_actions ); forwardAction->setEnabled( mass_actions ); forwardAttachedAction->setEnabled( mass_actions ); action( "apply_filters" )->setEnabled( mass_actions ); bool single_actions = count == 1; filterMenu->setEnabled( single_actions ); editAction->setEnabled( single_actions && kernel->folderIsDraftOrOutbox(mFolder)); bounceAction->setEnabled( single_actions ); replyAction->setEnabled( single_actions ); noQuoteReplyAction->setEnabled( single_actions ); replyAllAction->setEnabled( single_actions ); replyListAction->setEnabled( single_actions ); redirectAction->setEnabled( single_actions ); sendAgainAction->setEnabled( single_actions ); printAction->setEnabled( single_actions ); saveAsAction->setEnabled( mass_actions ); viewSourceAction->setEnabled( single_actions ); if ( count == 1 ) { KMMessage *msg; int aIdx; if((aIdx = mHeaders->currentItemIndex()) <= -1) return; if(!(msg = mHeaders->getMsg(aIdx))) return; QCString name; QString value; QString lname = KMMLInfo::name( msg, name, value ); if ( lname.isNull() ) mlistFilterAction->setEnabled( false ); else { mlistFilterAction->setEnabled( true ); mlistFilterAction->setText( i18n( "Filter on Mailing-List %1..." ).arg( lname ) ); } } bool mails = mFolder && mFolder->count(); action( "go_next_message" )->setEnabled( mails ); action( "go_next_unread_message" )->setEnabled( mails ); action( "go_prev_message" )->setEnabled( mails ); action( "go_prev_unread_message" )->setEnabled( mails ); action( "send_queued" )->setEnabled( kernel->outboxFolder()->count() > 0 ); action( "edit_undo" )->setEnabled( mHeaders->canUndo() ); } //----------------------------------------------------------------------------- void KMMainWin::updateFolderMenu() { modifyFolderAction->setEnabled( mFolder ? !mFolder->noContent() : false ); compactFolderAction->setEnabled( mFolder ? !mFolder->noContent() : false ); emptyFolderAction->setEnabled( mFolder ? !mFolder->noContent() : false ); removeFolderAction->setEnabled( (mFolder && !mFolder->isSystemFolder()) ); expireFolderAction->setEnabled( mFolder && mFolder->protocol() != "imap" && mFolder->isAutoExpire() ); markAllAsReadAction->setEnabled( mFolder && (mFolder->countUnread() > 0) ); preferHtmlAction->setEnabled( mFolder ? true : false ); threadMessagesAction->setEnabled( mFolder ? true : false ); preferHtmlAction->setChecked( mHtmlPref ? !mFolderHtmlPref : mFolderHtmlPref ); threadMessagesAction->setChecked( mThreadPref ? !mFolderThreadPref : mFolderThreadPref ); } #ifdef MALLOC_DEBUG QString fmt(long n) { char buf[32]; if(n > 1024*1024*1024) sprintf(buf, "%0.2f GB", ((double)n)/1024.0/1024.0/1024.0); else if(n > 1024*1024) sprintf(buf, "%0.2f MB", ((double)n)/1024.0/1024.0); else if(n > 1024) sprintf(buf, "%0.2f KB", ((double)n)/1024.0); else sprintf(buf, "%ld Byte", n); return QString(buf); } #endif void KMMainWin::slotMemInfo() { #ifdef MALLOC_DEBUG struct mallinfo mi; mi = mallinfo(); QString s = QString("\nMALLOC - Info\n\n" "Number of mmapped regions : %1\n" "Memory allocated in use : %2\n" "Memory allocated, not used: %3\n" "Memory total allocated : %4\n" "Max. freeable memory : %5\n") .arg(mi.hblks).arg(fmt(mi.uordblks)).arg(fmt(mi.fordblks)) .arg(fmt(mi.arena)).arg(fmt(mi.keepcost)); KMessageBox::information(0, s, "Malloc information", s); #endif } //----------------------------------------------------------------------------- bool KMMainWin::queryClose() { int ret = 0; QString str = i18n("Expire old messages from all folders? " "Expired messages are permanently deleted."); KConfig *config = kapp->config(); // Make sure this is the last window. KMainWindow *kmWin = NULL; int num = 0; kernel->setCanExpire(false); for (kmWin = KMainWindow::memberList->first(); kmWin; kmWin = KMainWindow::memberList->next()) { if (kmWin->isA("KMMainWin")) { num++; } } // If this isn't the last open window, don't do anything. if (num > 1) { return true; } KConfigGroupSaver saver(config, "General"); if (config->readNumEntry("when-to-expire", 0) != expireAtExit) { return true; } if (config->readBoolEntry("warn-before-expire")) { ret = KMessageBox::warningContinueCancel(KMainWindow::memberList->first(), str, i18n("Expire old Messages?"), i18n("Expire")); if (ret == KMessageBox::Continue) { kernel->setCanExpire(true); } } return true; } //----------------------------------------------------------------------------- void KMMainWin::transferSelectedMsgs() { // make sure no other transfer is active if (mCountJobs > 0) return; bool complete = true; mCountJobs = 0; mCountMsgs = 0; mSelectedMsgs.clear(); // get the selected messages QPtrList* msgList = mHeaders->selectedMsgs(); mCountMsgs = msgList->count(); // the KProgressDialog for the user-feedback mProgressDialog = new KProgressDialog(this, "transferProgress", i18n("Please wait"), i18n("Please wait while the message is transferred", "Please wait while the %n messages are transferred", msgList->count()), true); mProgressDialog->setMinimumDuration(1000); for (KMMsgBase *mb = msgList->first(); mb; mb = msgList->next()) { // check if all messages are complete int idx = mFolder->find(mb); if (idx < 0) continue; KMMessage *thisMsg = mFolder->getMsg(idx); if (!thisMsg) continue; if (thisMsg->parent() && thisMsg->parent()->protocol() == "imap" && !thisMsg->isComplete() && !mProgressDialog->wasCancelled()) { // the message needs to be transferred first complete = false; mCountJobs++; KMImapJob *imapJob = new KMImapJob(thisMsg); // emitted when the message was transferred successfully connect(imapJob, SIGNAL(messageRetrieved(KMMessage*)), this, SLOT(slotMsgTransfered(KMMessage*))); // emitted when the job is destroyed connect(imapJob, SIGNAL(finished()), this, SLOT(slotJobFinished())); // msg musn't be deleted thisMsg->setTransferInProgress(true); } else { mSelectedMsgs.append(thisMsg); } } if (complete) { delete mProgressDialog; emit messagesTransfered(true); } else { // wait for the transfer and tell the progressBar the necessary steps connect(mProgressDialog, SIGNAL(cancelClicked()), this, SLOT(slotTransferCancelled())); mProgressDialog->progressBar()->setTotalSteps(mCountJobs); } } //----------------------------------------------------------------------------- void KMMainWin::slotMsgTransfered(KMMessage* msg) { msg->setTransferInProgress(false); if (mProgressDialog->wasCancelled()) return; // save the complete messages mSelectedMsgs.append(msg); } //----------------------------------------------------------------------------- void KMMainWin::slotJobFinished() { // the job is finished (with / without error) mCountJobs--; if (mProgressDialog->wasCancelled()) return; if ( (mCountMsgs - static_cast(mSelectedMsgs.count())) > mCountJobs ) { // the message wasn't retrieved before => error mProgressDialog->hide(); slotTransferCancelled(); return; } // update the progressbar mProgressDialog->progressBar()->advance(1); mProgressDialog->setLabel(i18n("Please wait while the message is transferred", "Please wait while the %n messages are transferred", mCountJobs)); if (mCountJobs == 0) { // all done delete mProgressDialog; emit messagesTransfered(true); } } //----------------------------------------------------------------------------- void KMMainWin::slotTransferCancelled() { if (mFolder->protocol() != "imap") return; emit messagesTransfered(false); // kill the pending jobs KMAcctImap* acct = static_cast(mFolder)->account(); if (acct) { acct->killAllJobs(); acct->setIdle(true); } mCountJobs = 0; mCountMsgs = 0; // unget the transfered messages QPtrListIterator it( mSelectedMsgs ); KMMessage* msg; while ( (msg = it.current()) != 0 ) { ++it; int idx = mFolder->find(msg); if (idx > 0) mFolder->unGetMsg(idx); } mSelectedMsgs.clear(); // unget the selected messages QPtrList* msgList = mHeaders->selectedMsgs(); for (KMMsgBase *mb = msgList->first(); mb; mb = msgList->next()) { if (mb->isMessage()) { int idx = mFolder->find(mb); if (idx > 0) mFolder->unGetMsg(idx); } } } //----------------------------------------------------------------------------- void KMMainWin::slotIntro() { if ( !mFolderTree || !mMsgView ) return; if ( !mFolderTree->firstChild() ) return; if ( mFolderTree->currentItem() != mFolderTree->firstChild() ) // don't loop mFolderTree->doFolderSelected( mFolderTree->firstChild() ); mMsgView->clear( true ); // hide widgets that are in the way: if ( mHeaders && mWindowLayout < 3 ) mHeaders->hide(); if ( mMimePartTree && mShowMIMETreeMode > 0 && mWindowLayout != 2 && mWindowLayout != 3 ) mMimePartTree->hide(); mMsgView->displayAboutPage(); } void KMMainWin::slotShowTipOnStart() { KTipDialog::showTip( this ); } void KMMainWin::slotShowTip() { KTipDialog::showTip( this, QString::null, true ); } //----------------------------------------------------------------------------- void KMMainWin::slotChangeCaption(QListViewItem * i) { // set the caption to the current full path QStringList names; for ( QListViewItem * item = i ; item ; item = item->parent() ) names.prepend( item->text(0) ); setCaption( names.join("/") ); }