kmail Library API Documentation

kmfldsearch.cpp

00001 /* kmfldsearch
00002  * (c) 1999 Stefan Taferner, (c) 2001 Aaron J. Seigo
00003  * This code is under GPL
00004  */
00005 // kmfldsearch.cpp
00006 
00007 #include <config.h>
00008 #include "kmcommands.h"
00009 #include "kmfldsearch.h"
00010 #include "kmmainwidget.h"
00011 #include "kmmsgdict.h"
00012 #include "kmmsgpart.h"
00013 #include "kmfoldercombobox.h"
00014 #include "kmfolderdia.h"
00015 #include "kmfolderimap.h"
00016 #include "kmfoldermgr.h"
00017 #include "kmfoldersearch.h"
00018 #include "kmfoldertree.h"
00019 #include "kmsearchpatternedit.h"
00020 #include "kmsearchpattern.h"
00021 
00022 #include <kapplication.h>
00023 #include <kdebug.h>
00024 #include <kstatusbar.h>
00025 #include <kwin.h>
00026 #include <kconfig.h>
00027 #include <kstdaction.h>
00028 
00029 #include <qcheckbox.h>
00030 #include <qlayout.h>
00031 #include <klineedit.h>
00032 #include <qpushbutton.h>
00033 #include <qradiobutton.h>
00034 #include <qbuttongroup.h>
00035 #include <qobjectlist.h> //for mPatternEdit->queryList( 0, "mRuleField" )->first();
00036 #include <qcursor.h>
00037 
00038 #include <mimelib/enum.h>
00039 #include <mimelib/boyermor.h>
00040 
00041 #include <assert.h>
00042 #include <stdlib.h>
00043 
00044 #include <X11/Xlib.h>
00045 #include <X11/Xatom.h>
00046 
00047 const int KMFldSearch::MSGID_COLUMN = 4;
00048 
00049 //-----------------------------------------------------------------------------
00050 KMFldSearch::KMFldSearch(KMMainWidget* w, const char* name,
00051                          KMFolder *curFolder, bool modal):
00052   KDialogBase(0, name, modal, i18n("Search in Folders"),
00053               User1 | User2 | Close, User1, false,
00054               KGuiItem( i18n("&Search"), "find" ),
00055               KGuiItem( i18n("S&top"), "cancel" )),
00056   mStopped(false),
00057   mCloseRequested(false),
00058   mSortColumn(0),
00059   mSortOrder(Ascending),
00060   mFolder(0),
00061   mTimer(new QTimer(this)),
00062   mLastFocus(0),
00063   mKMMainWidget(w)
00064 {
00065 #if !KDE_IS_VERSION( 3, 2, 91 )
00066   // HACK - KWin keeps all dialogs on top of their mainwindows, but that's probably
00067   // wrong (#76026), and should be done only for modals. CVS HEAD should get
00068   // proper fix in KWin (l.lunak@kde.org)
00069   XDeleteProperty( qt_xdisplay(), winId(), XA_WM_TRANSIENT_FOR );
00070 #endif
00071   KWin::setIcons(winId(), kapp->icon(), kapp->miniIcon());
00072 
00073   KConfig* config = KMKernel::config();
00074   config->setGroup("SearchDialog");
00075 
00076   QWidget* searchWidget = new QWidget(this);
00077   QVBoxLayout *vbl = new QVBoxLayout( searchWidget, 0, spacingHint(), "kmfs_vbl" );
00078 
00079   QButtonGroup * radioGroup = new QButtonGroup( searchWidget );
00080   radioGroup->hide();
00081 
00082   mChkbxAllFolders = new QRadioButton(i18n("Search in &all local folders"), searchWidget);
00083   vbl->addWidget( mChkbxAllFolders );
00084   radioGroup->insert( mChkbxAllFolders );
00085 
00086   QHBoxLayout *hbl = new QHBoxLayout( vbl, spacingHint(), "kmfs_hbl" );
00087   mChkbxSpecificFolders = new QRadioButton(i18n("Search &only in:"), searchWidget);
00088   hbl->addWidget(mChkbxSpecificFolders);
00089   mChkbxSpecificFolders->setChecked(true);
00090   radioGroup->insert( mChkbxSpecificFolders );
00091 
00092   mCbxFolders = new KMFolderComboBox(false, searchWidget);
00093   mCbxFolders->setFolder(curFolder);
00094   hbl->addWidget(mCbxFolders);
00095 
00096   connect(mCbxFolders, SIGNAL(activated(int)),
00097           this, SLOT(slotFolderActivated(int)));
00098   connect(mCbxFolders, SIGNAL(activated(int)),
00099           this, SLOT(slotFilterAvailableRules()));
00100     
00101   mChkSubFolders = new QCheckBox(i18n("I&nclude sub-folders"), searchWidget);
00102   mChkSubFolders->setChecked(true);
00103   hbl->addWidget(mChkSubFolders);
00104 
00105   QWidget *spacer = new QWidget( searchWidget, "spacer" );
00106   spacer->setMinimumHeight( 2 );
00107   vbl->addWidget( spacer );
00108 
00109   mPatternEdit = new KMSearchPatternEdit( "", searchWidget , "spe", false, true );
00110   mPatternEdit->setFrameStyle( QFrame::NoFrame | QFrame::Plain );
00111   mPatternEdit->setInsideMargin( 0 );
00112   mSearchPattern = new KMSearchPattern();
00113   KMFolderSearch *searchFolder = 0;
00114   if (curFolder)
00115       searchFolder = dynamic_cast<KMFolderSearch*>(curFolder->storage());
00116   if (searchFolder) {
00117       KConfig config(curFolder->location());
00118       KMFolder *root = searchFolder->search()->root();
00119       config.setGroup("Search Folder");
00120       mSearchPattern->readConfig(&config);
00121       if (root) {
00122       mChkbxSpecificFolders->setChecked(true);
00123       mCbxFolders->setFolder(root);
00124       mChkSubFolders->setChecked(searchFolder->search()->recursive());
00125       } else {
00126       mChkbxAllFolders->setChecked(true);
00127       }
00128       mFolder = searchFolder;
00129   }
00130   mPatternEdit->setSearchPattern( mSearchPattern );
00131   QObjectList *list = mPatternEdit->queryList( 0, "mRuleField" );
00132   QObject *object = 0;
00133   if ( list )
00134       object = list->first();
00135   delete list;
00136   if (!searchFolder && object && ::qt_cast<QComboBox*>(object))
00137       static_cast<QComboBox*>(object)->setCurrentText("Subject");
00138 
00139   vbl->addWidget( mPatternEdit );
00140 
00141   // enable/disable widgets depending on radio buttons:
00142   connect( mChkbxSpecificFolders, SIGNAL(toggled(bool)),
00143        mCbxFolders, SLOT(setEnabled(bool)) );
00144   connect( mChkbxSpecificFolders, SIGNAL(toggled(bool)),
00145        mChkSubFolders, SLOT(setEnabled(bool)) );
00146 
00147   mLbxMatches = new KListView(searchWidget, "Search in Folders");
00148 
00149   /*
00150      Default is to sort by date. TODO: Unfortunately this sorts *while*
00151      inserting, which looks rather strange - the user cannot read
00152      the results so far as they are constantly re-sorted --dnaber
00153 
00154      Sorting is now disabled when a search is started and reenabled
00155      when it stops. Items are appended to the list. This not only
00156      solves the above problem, but speeds searches with many hits
00157      up considerably. - till
00158 
00159      TODO: subclass KListViewItem and do proper (and performant)
00160      comapare functions
00161   */
00162   mLbxMatches->setSorting(2, false);
00163   mLbxMatches->setShowSortIndicator(true);
00164   mLbxMatches->setAllColumnsShowFocus(true);
00165   mLbxMatches->setSelectionModeExt(KListView::Extended);
00166   mLbxMatches->addColumn(i18n("Subject"),
00167                          config->readNumEntry("SubjectWidth", 150));
00168   mLbxMatches->addColumn(i18n("Sender/Receiver"),
00169                          config->readNumEntry("SenderWidth", 120));
00170   mLbxMatches->addColumn(i18n("Date"),
00171                          config->readNumEntry("DateWidth", 120));
00172   mLbxMatches->addColumn(i18n("Folder"),
00173                          config->readNumEntry("FolderWidth", 100));
00174 
00175   mLbxMatches->addColumn(""); // should be hidden
00176   mLbxMatches->setColumnWidthMode( MSGID_COLUMN, QListView::Manual );
00177   mLbxMatches->setColumnWidth(MSGID_COLUMN, 0);
00178   mLbxMatches->header()->setResizeEnabled(false, MSGID_COLUMN);
00179 
00180   connect(mLbxMatches, SIGNAL(doubleClicked(QListViewItem *)),
00181           this, SLOT(slotShowMsg(QListViewItem *)));
00182   connect( mLbxMatches, SIGNAL( contextMenuRequested( QListViewItem*, const QPoint &, int )),
00183        this, SLOT( slotContextMenuRequested( QListViewItem*, const QPoint &, int )));
00184   vbl->addWidget(mLbxMatches);
00185 
00186   QHBoxLayout *hbl2 = new QHBoxLayout( vbl, spacingHint(), "kmfs_hbl2" );
00187   mSearchFolderLbl = new QLabel(i18n("Search folder &name:"), searchWidget);
00188   hbl2->addWidget(mSearchFolderLbl);
00189   mSearchFolderEdt = new KLineEdit(searchWidget);
00190   if (searchFolder)
00191     mSearchFolderEdt->setText(searchFolder->folder()->name());
00192   else
00193     mSearchFolderEdt->setText(i18n("Last Search"));
00194 
00195   mSearchFolderLbl->setBuddy(mSearchFolderEdt);
00196   hbl2->addWidget(mSearchFolderEdt);
00197   mSearchFolderBtn = new QPushButton(i18n("&Rename"), searchWidget);
00198   mSearchFolderBtn->setEnabled(false);
00199   hbl2->addWidget(mSearchFolderBtn);
00200   mSearchFolderOpenBtn = new QPushButton(i18n("Op&en"), searchWidget);
00201   mSearchFolderOpenBtn->setEnabled(false);
00202   hbl2->addWidget(mSearchFolderOpenBtn);
00203   connect( mSearchFolderEdt, SIGNAL( textChanged( const QString &)),
00204        this, SLOT( updateCreateButton( const QString & )));
00205   connect( mSearchFolderBtn, SIGNAL( clicked() ),
00206        this, SLOT( renameSearchFolder() ));
00207   connect( mSearchFolderOpenBtn, SIGNAL( clicked() ),
00208        this, SLOT( openSearchFolder() ));
00209   mStatusBar = new KStatusBar(searchWidget);
00210   mStatusBar->insertFixedItem(i18n("AMiddleLengthText..."), 0, true);
00211   mStatusBar->changeItem(i18n("Ready."), 0);
00212   mStatusBar->setItemAlignment(0, AlignLeft | AlignVCenter);
00213   mStatusBar->insertItem(QString::null, 1, 1, true);
00214   mStatusBar->setItemAlignment(1, AlignLeft | AlignVCenter);
00215   vbl->addWidget(mStatusBar);
00216 
00217   int mainWidth = config->readNumEntry("SearchWidgetWidth", 0);
00218   int mainHeight = config->readNumEntry("SearchWidgetHeight", 0);
00219 
00220   if (mainWidth || mainHeight)
00221     resize(mainWidth, mainHeight);
00222 
00223   setMainWidget(searchWidget);
00224   setButtonBoxOrientation(QWidget::Vertical);
00225 
00226   mBtnSearch = actionButton(KDialogBase::User1);
00227   mBtnStop = actionButton(KDialogBase::User2);
00228   mBtnStop->setEnabled(false);
00229 
00230   connect(this, SIGNAL(user1Clicked()), SLOT(slotSearch()));
00231   connect(this, SIGNAL(user2Clicked()), SLOT(slotStop()));
00232   connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));
00233 
00234   // give focus to the value field of the first search rule
00235   object = mPatternEdit->child( "regExpLineEdit" );
00236   if ( object && object->isWidgetType() ) {
00237       static_cast<QWidget*>(object)->setFocus();
00238       //kdDebug(5006) << "KMFldSearch: focus has been given to widget "
00239       //              << object->name() << endl;
00240   }
00241   else
00242       kdDebug(5006) << "KMFldSearch: regExpLineEdit not found" << endl;
00243 
00244   // Remove the <message> and <body> rule fields when searching imap folders
00245   slotFilterAvailableRules();
00246   connect(mChkbxAllFolders, SIGNAL(toggled(bool)),
00247           this, SLOT(slotFilterAvailableRules()));
00248 
00249   //set up actions
00250   KActionCollection *ac = actionCollection();
00251   mReplyAction = new KAction( i18n("&Reply..."), "mail_reply", 0, this,
00252                   SLOT(slotReplyToMsg()), ac, "search_reply" );
00253   mReplyAllAction = new KAction( i18n("Reply to &All..."), "mail_replyall",
00254                  0, this, SLOT(slotReplyAllToMsg()),
00255                  ac, "search_reply_all" );
00256   mReplyListAction = new KAction( i18n("Reply to Mailing-&List..."),
00257                   "mail_replylist", 0, this,
00258                   SLOT(slotReplyListToMsg()), ac,
00259                   "search_reply_list" );
00260   mForwardActionMenu = new KActionMenu( i18n("Message->","&Forward"),
00261                     "mail_forward", ac,
00262                     "search_message_forward" );
00263   connect( mForwardActionMenu, SIGNAL(activated()), this,
00264        SLOT(slotForwardMsg()) );
00265   mForwardAction = new KAction( i18n("&Inline..."), "mail_forward",
00266                 0, this, SLOT(slotForwardMsg()),
00267                 ac, "search_message_forward_inline" );
00268   mForwardActionMenu->insert( mForwardAction );
00269   mForwardAttachedAction = new KAction( i18n("Message->Forward->","As &Attachment..."),
00270                        "mail_forward", 0, this,
00271                     SLOT(slotForwardAttachedMsg()), ac,
00272                     "search_message_forward_as_attachment" );
00273   mForwardActionMenu->insert( mForwardAttachedAction );
00274   mSaveAsAction = KStdAction::saveAs( this, SLOT(slotSaveMsg()), ac, "search_file_save_as" );
00275   mSaveAtchAction = new KAction( i18n("Save Attachments..."), "attach", 0,
00276                                  this, SLOT(slotSaveAttachments()), ac, "search_save_attachments" );
00277 
00278   mPrintAction = KStdAction::print( this, SLOT(slotPrintMsg()), ac, "search_print" );
00279   mClearAction = new KAction( i18n("Clear Selection"), 0, 0, this,
00280                   SLOT(slotClearSelection()), ac, "search_clear_selection" );
00281   connect(mTimer, SIGNAL(timeout()), this, SLOT(updStatus()));
00282   connect(kmkernel->searchFolderMgr(), SIGNAL(folderInvalidated(KMFolder*)),
00283       this, SLOT(folderInvalidated(KMFolder*)));
00284 }
00285 
00286 //-----------------------------------------------------------------------------
00287 KMFldSearch::~KMFldSearch()
00288 {
00289   QValueListIterator<QGuardedPtr<KMFolder> > fit;
00290   for ( fit = mFolders.begin(); fit != mFolders.end(); ++fit ) {
00291     if (!(*fit))
00292       continue;
00293     (*fit)->close();
00294   }
00295 
00296   KConfig* config = KMKernel::config();
00297   config->setGroup("SearchDialog");
00298   config->writeEntry("SubjectWidth", mLbxMatches->columnWidth(0));
00299   config->writeEntry("SenderWidth", mLbxMatches->columnWidth(1));
00300   config->writeEntry("DateWidth", mLbxMatches->columnWidth(2));
00301   config->writeEntry("FolderWidth", mLbxMatches->columnWidth(3));
00302   config->writeEntry("SearchWidgetWidth", width());
00303   config->writeEntry("SearchWidgetHeight", height());
00304   config->sync();
00305 }
00306 
00307 //-----------------------------------------------------------------------------
00308 void KMFldSearch::updStatus(void)
00309 {
00310     QString genMsg, detailMsg;
00311     int numMatches = 0, count = 0;
00312     KMSearch const *search = (mFolder) ? (mFolder->search()) : 0;
00313     QString folderName;
00314     if (search) {
00315     numMatches = search->foundCount();
00316     count = search->searchedCount();
00317     folderName = search->currentFolder();
00318     }
00319 
00320     if (mFolder && mFolder->search() && !mFolder->search()->running()) {
00321     if(!mStopped) {
00322         genMsg = i18n("Done");
00323         detailMsg = i18n("%n match (%1)", "%n matches (%1)", numMatches)
00324             .arg(i18n("%n message processed",
00325                   "%n messages processed", count));
00326     } else {
00327         genMsg = i18n("Search canceled");
00328         detailMsg = i18n("%n match so far (%1)",
00329                  "%n matches so far (%1)", numMatches)
00330             .arg(i18n("%n message processed",
00331                   "%n messages processed", count));
00332     }
00333     } else {
00334     genMsg = i18n("%n match", "%n matches", numMatches);
00335     detailMsg = i18n("Searching in %1 (message %2)")
00336             .arg(folderName)
00337             .arg(count);
00338     }
00339 
00340     mStatusBar->changeItem(genMsg, 0);
00341     mStatusBar->changeItem(detailMsg, 1);
00342 }
00343 
00344 
00345 //-----------------------------------------------------------------------------
00346 void KMFldSearch::keyPressEvent(QKeyEvent *evt)
00347 {
00348     KMSearch const *search = (mFolder) ? mFolder->search() : 0;
00349     bool searching = (search) ? search->running() : false;
00350     if (evt->key() == Key_Escape && searching) {
00351     mFolder->stopSearch();
00352     return;
00353     }
00354 
00355     KDialogBase::keyPressEvent(evt);
00356 }
00357 
00358 
00359 //-----------------------------------------------------------------------------
00360 void KMFldSearch::slotFolderActivated(int /*nr*/)
00361 {
00362     KMFolder* folder = mCbxFolders->getFolder();
00363 
00364     mChkbxSpecificFolders->setChecked(true);
00365     mBtnSearch->setEnabled(folder);
00366 }
00367 
00368 
00369 //-----------------------------------------------------------------------------
00370 void KMFldSearch::slotFilterAvailableRules()
00371 {
00372     static bool lastHeadersOnly = false;
00373     KMFolder* folder = mCbxFolders->getFolder();
00374     bool headersOnly = folder->folderType() == KMFolderTypeImap;
00375     if (mChkbxAllFolders->isChecked())
00376     headersOnly = false;
00377     if (headersOnly != lastHeadersOnly)
00378     mPatternEdit->setHeadersOnly( headersOnly );
00379     lastHeadersOnly = headersOnly;
00380 }
00381 
00382 
00383 //-----------------------------------------------------------------------------
00384 void KMFldSearch::activateFolder(KMFolder *curFolder)
00385 {
00386     mChkbxSpecificFolders->setChecked(true);
00387     mCbxFolders->setFolder(curFolder);
00388 }
00389 
00390 //-----------------------------------------------------------------------------
00391 void KMFldSearch::slotSearch()
00392 {
00393     mLastFocus = focusWidget();
00394     mBtnSearch->setFocus(); // set focus so we don't miss key event
00395 
00396     mStopped = false;
00397     mFetchingInProgress = 0;
00398 
00399     mSearchFolderOpenBtn->setEnabled(true);
00400     mBtnSearch->setEnabled(false);
00401     mBtnStop->setEnabled(true);
00402 
00403     mLbxMatches->clear();
00404 
00405     mSortColumn = mLbxMatches->sortColumn();
00406     mSortOrder = mLbxMatches->sortOrder();
00407     mLbxMatches->setSorting(-1);
00408     mLbxMatches->setShowSortIndicator(false);
00409 
00410     // If we haven't openend an existing search folder, find or
00411     // create one.
00412     if (!mFolder) {
00413       KMFolderMgr *mgr = kmkernel->searchFolderMgr();
00414       if (mSearchFolderEdt->text().isEmpty())
00415       mSearchFolderEdt->setText(i18n("Last Search"));
00416       QString baseName = mSearchFolderEdt->text();
00417       QString fullName = baseName;
00418       int count = 0;
00419       KMFolder *folder;
00420       while ((folder = mgr->find(fullName))) {
00421         if (folder->storage()->inherits("KMFolderSearch"))
00422           break;
00423         fullName = QString("%1 %2").arg(baseName).arg(++count);
00424       }
00425 
00426       if (!folder)
00427         folder = mgr->createFolder(fullName, FALSE, KMFolderTypeSearch,
00428             &mgr->dir());
00429 
00430       mFolder = dynamic_cast<KMFolderSearch*>( folder->storage() );
00431     }
00432     mFolder->stopSearch();
00433     disconnect(mFolder, SIGNAL(msgAdded(int)),
00434         this, SLOT(slotAddMsg(int)));
00435     disconnect(mFolder, SIGNAL(msgRemoved(KMFolder*, Q_UINT32)),
00436         this, SLOT(slotRemoveMsg(KMFolder*, Q_UINT32)));
00437     connect(mFolder, SIGNAL(msgAdded(int)),
00438         this, SLOT(slotAddMsg(int)));
00439     connect(mFolder, SIGNAL(msgRemoved(KMFolder*, Q_UINT32)),
00440         this, SLOT(slotRemoveMsg(KMFolder*, Q_UINT32)));
00441     KMSearch *search = new KMSearch();
00442     connect(search, SIGNAL(finished(bool)),
00443         this, SLOT(searchDone()));
00444     if (mChkbxAllFolders->isChecked()) {
00445     search->setRecursive(true);
00446     } else {
00447     search->setRoot(mCbxFolders->getFolder());
00448     search->setRecursive(mChkSubFolders->isChecked());
00449     }
00450 
00451     mPatternEdit->updateSearchPattern();
00452     KMSearchPattern *searchPattern = new KMSearchPattern();
00453     *searchPattern = *mSearchPattern; //deep copy
00454     searchPattern->purify();
00455     search->setSearchPattern(searchPattern);
00456     mFolder->setSearch(search);
00457     enableGUI();
00458 
00459     if (mFolder && !mFolders.contains(mFolder.operator->()->folder())) {
00460     mFolder->open();
00461     mFolders.append(mFolder.operator->()->folder());
00462     }
00463     mTimer->start(200);
00464 }
00465 
00466 //-----------------------------------------------------------------------------
00467 void KMFldSearch::searchDone()
00468 {
00469     mTimer->stop();
00470     updStatus();
00471 
00472     QTimer::singleShot(0, this, SLOT(enableGUI()));
00473     if(mLastFocus)
00474     mLastFocus->setFocus();
00475     if (mCloseRequested)
00476     close();
00477 
00478     mLbxMatches->setSorting(mSortColumn, mSortOrder == Ascending);
00479     mLbxMatches->setShowSortIndicator(true);
00480 }
00481 
00482 void KMFldSearch::slotAddMsg(int idx)
00483 {
00484     if (!mFolder)
00485     return;
00486     bool unget = !mFolder->isMessage(idx);
00487     KMMessage *msg = mFolder->getMsg(idx);
00488     QString from, fName;
00489     KMFolder *pFolder = msg->parent();
00490     if (!mFolders.contains(pFolder)) {
00491     mFolders.append(pFolder);
00492     pFolder->open();
00493     }
00494     if(pFolder->whoField() == "To")
00495         from = msg->to();
00496     else
00497         from = msg->from();
00498     if (pFolder->isSystemFolder())
00499     fName = i18n(pFolder->name().utf8());
00500     else
00501         fName = pFolder->name();
00502 
00503     (void)new KListViewItem(mLbxMatches, mLbxMatches->lastItem(),
00504                 msg->subject(), from, msg->dateIsoStr(),
00505                 fName,
00506                 QString::number(mFolder->serNum(idx)));
00507     if (unget)
00508     mFolder->unGetMsg(idx);
00509 }
00510 
00511 void KMFldSearch::slotRemoveMsg(KMFolder *, Q_UINT32 serNum)
00512 {
00513     if (!mFolder)
00514     return;
00515     QListViewItemIterator it(mLbxMatches);
00516     while (it.current()) {
00517     QListViewItem *item = *it;
00518     if (serNum == (*it)->text(MSGID_COLUMN).toUInt()) {
00519         delete item;
00520         return;
00521     }
00522     ++it;
00523     }
00524 }
00525 
00526 //-----------------------------------------------------------------------------
00527 void KMFldSearch::slotStop()
00528 {
00529     if (mFolder)
00530     mFolder->stopSearch();
00531     mStopped = true;
00532     mBtnStop->setEnabled(false);
00533 }
00534 
00535 //-----------------------------------------------------------------------------
00536 void KMFldSearch::slotClose()
00537 {
00538     accept();
00539 }
00540 
00541 
00542 //-----------------------------------------------------------------------------
00543 void KMFldSearch::closeEvent(QCloseEvent *e)
00544 {
00545     if (mFolder && mFolder->search() && mFolder->search()->running()) {
00546     mCloseRequested = true;
00547     //Cancel search in progress by setting the search folder search to
00548     //the null search
00549     mFolder->setSearch(new KMSearch());
00550     QTimer::singleShot(0, this, SLOT(slotClose()));
00551     } else {
00552     KDialogBase::closeEvent(e);
00553     }
00554 }
00555 
00556 //-----------------------------------------------------------------------------
00557 void KMFldSearch::updateCreateButton( const QString &s)
00558 {
00559     mSearchFolderBtn->setEnabled(s != i18n("Last Search") && mSearchFolderOpenBtn->isEnabled());
00560 }
00561 
00562 //-----------------------------------------------------------------------------
00563 void KMFldSearch::renameSearchFolder()
00564 {
00565     if (mFolder && (mFolder->folder()->name() != mSearchFolderEdt->text())) {
00566     int i = 1;
00567     QString name =  mSearchFolderEdt->text();
00568     while (i < 100) {
00569         if (!kmkernel->searchFolderMgr()->find( name )) {
00570         mFolder->rename( name );
00571         kmkernel->searchFolderMgr()->contentsChanged();
00572         break;
00573         }
00574         name.setNum( i );
00575         name = mSearchFolderEdt->text() + " " + name;
00576         ++i;
00577     }
00578     }
00579 }
00580 
00581 void KMFldSearch::openSearchFolder()
00582 {
00583     renameSearchFolder();
00584     KMFolderTree *folderTree = mKMMainWidget->folderTree();
00585     QListViewItem *index = folderTree->indexOfFolder(mFolder->folder());
00586     if (index) {
00587     folderTree->ensureItemVisible(index);
00588     folderTree->doFolderSelected(index);
00589     slotClose();
00590     }
00591 }
00592 
00593 //-----------------------------------------------------------------------------
00594 void KMFldSearch::folderInvalidated(KMFolder *folder)
00595 {
00596     if (folder->storage() == mFolder) {
00597     mLbxMatches->clear();
00598     if (mFolder->search())
00599         connect(mFolder->search(), SIGNAL(finished(bool)),
00600             this, SLOT(searchDone()));
00601     mTimer->start(200);
00602     enableGUI();
00603     }
00604 }
00605 
00606 //-----------------------------------------------------------------------------
00607 bool KMFldSearch::slotShowMsg(QListViewItem *item)
00608 {
00609     if(!item)
00610     return false;
00611 
00612     KMFolder* folder;
00613     int msgIndex;
00614     kmkernel->msgDict()->getLocation(item->text(MSGID_COLUMN).toUInt(),
00615                    &folder, &msgIndex);
00616 
00617     if (!folder || msgIndex < 0)
00618     return false;
00619 
00620     mKMMainWidget->slotSelectFolder(folder);
00621     KMMessage* message = folder->getMsg(msgIndex);
00622     if (!message)
00623     return false;
00624 
00625     mKMMainWidget->slotSelectMessage(message);
00626     return true;
00627 }
00628 
00629 //-----------------------------------------------------------------------------
00630 void KMFldSearch::enableGUI()
00631 {
00632     KMSearch const *search = (mFolder) ? (mFolder->search()) : 0;
00633     bool searching = (search) ? (search->running()) : false;
00634     actionButton(KDialogBase::Close)->setEnabled(!searching);
00635     mCbxFolders->setEnabled(!searching);
00636     mChkSubFolders->setEnabled(!searching);
00637     mChkbxAllFolders->setEnabled(!searching);
00638     mChkbxSpecificFolders->setEnabled(!searching);
00639     mPatternEdit->setEnabled(!searching);
00640     mBtnSearch->setEnabled(!searching);
00641     mBtnStop->setEnabled(searching);
00642 }
00643 
00644 
00645 //-----------------------------------------------------------------------------
00646 KMMessageList KMFldSearch::selectedMessages()
00647 {
00648     KMMessageList msgList;
00649     KMFolder* folder = 0;
00650     int msgIndex = -1;
00651     for (QListViewItemIterator it(mLbxMatches); it.current(); it++)
00652     if (it.current()->isSelected()) {
00653         kmkernel->msgDict()->getLocation((*it)->text(MSGID_COLUMN).toUInt(),
00654                        &folder, &msgIndex);
00655         if (folder && msgIndex >= 0)
00656         msgList.append(folder->getMsgBase(msgIndex));
00657     }
00658     return msgList;
00659 }
00660 
00661 //-----------------------------------------------------------------------------
00662 KMMessage* KMFldSearch::message()
00663 {
00664     QListViewItem *item = mLbxMatches->currentItem();
00665     KMFolder* folder = 0;
00666     int msgIndex = -1;
00667     if (!item)
00668     return 0;
00669     kmkernel->msgDict()->getLocation(item->text(MSGID_COLUMN).toUInt(),
00670                    &folder, &msgIndex);
00671     if (!folder || msgIndex < 0)
00672     return 0;
00673 
00674     return folder->getMsg(msgIndex);
00675 }
00676 
00677 //-----------------------------------------------------------------------------
00678 void KMFldSearch::moveSelectedToFolder( int menuId )
00679 {
00680     KMFolder *dest = mMenuToFolder[menuId];
00681     if (!dest)
00682     return;
00683 
00684     KMMessageList msgList = selectedMessages();
00685     KMCommand *command = new KMMoveCommand( dest, msgList );
00686     command->start();
00687 }
00688 
00689 //-----------------------------------------------------------------------------
00690 void KMFldSearch::copySelectedToFolder( int menuId )
00691 {
00692     KMFolder *dest = mMenuToFolder[menuId];
00693     if (!dest)
00694     return;
00695 
00696     KMMessageList msgList = selectedMessages();
00697     KMCommand *command = new KMCopyCommand( dest, msgList );
00698     command->start();
00699 }
00700 
00701 //-----------------------------------------------------------------------------
00702 void KMFldSearch::updateContextMenuActions()
00703 {
00704     int count = selectedMessages().count();
00705     bool single_actions = count == 1;
00706     mReplyAction->setEnabled( single_actions );
00707     mReplyAllAction->setEnabled( single_actions );
00708     mReplyListAction->setEnabled( single_actions );
00709     mPrintAction->setEnabled( single_actions );
00710 }
00711 
00712 //-----------------------------------------------------------------------------
00713 void KMFldSearch::slotContextMenuRequested( QListViewItem *lvi, const QPoint &, int )
00714 {
00715     if (!lvi)
00716     return;
00717     mLbxMatches->setSelected( lvi, TRUE );
00718     mLbxMatches->setCurrentItem( lvi );
00719     if (!message())
00720     return;
00721     QPopupMenu *menu = new QPopupMenu(this);
00722     updateContextMenuActions();
00723 
00724     mMenuToFolder.clear();
00725     QPopupMenu *msgMoveMenu = new QPopupMenu(menu);
00726     KMMoveCommand::folderToPopupMenu( TRUE, this, &mMenuToFolder, msgMoveMenu );
00727     QPopupMenu *msgCopyMenu = new QPopupMenu(menu);
00728     KMCopyCommand::folderToPopupMenu( FALSE, this, &mMenuToFolder, msgCopyMenu );
00729 
00730     // show most used actions
00731     mReplyAction->plug(menu);
00732     mReplyAllAction->plug(menu);
00733     mReplyListAction->plug(menu);
00734     mForwardActionMenu->plug(menu);
00735     menu->insertSeparator();
00736     menu->insertItem(i18n("&Copy To"), msgCopyMenu);
00737     menu->insertItem(i18n("&Move To"), msgMoveMenu);
00738     mSaveAsAction->plug(menu);
00739     mSaveAtchAction->plug(menu);
00740     mPrintAction->plug(menu);
00741     menu->insertSeparator();
00742     mClearAction->plug(menu);
00743     menu->exec (QCursor::pos(), 0);
00744     delete menu;
00745 }
00746 
00747 //-----------------------------------------------------------------------------
00748 void KMFldSearch::slotClearSelection()
00749 {
00750     mLbxMatches->clearSelection();
00751 }
00752 
00753 //-----------------------------------------------------------------------------
00754 void KMFldSearch::slotReplyToMsg()
00755 {
00756     KMCommand *command = new KMReplyToCommand(this, message());
00757     command->start();
00758 }
00759 
00760 //-----------------------------------------------------------------------------
00761 void KMFldSearch::slotReplyAllToMsg()
00762 {
00763     KMCommand *command = new KMReplyToAllCommand(this, message());
00764     command->start();
00765 }
00766 
00767 //-----------------------------------------------------------------------------
00768 void KMFldSearch::slotReplyListToMsg()
00769 {
00770     KMCommand *command = new KMReplyListCommand(this, message());
00771     command->start();
00772 }
00773 
00774 //-----------------------------------------------------------------------------
00775 void KMFldSearch::slotForwardMsg()
00776 {
00777     KMCommand *command = new KMForwardCommand(this, selectedMessages());
00778     command->start();
00779 }
00780 
00781 //-----------------------------------------------------------------------------
00782 void KMFldSearch::slotForwardAttachedMsg()
00783 {
00784     KMCommand *command = new KMForwardAttachedCommand(this, selectedMessages());
00785     command->start();
00786 }
00787 
00788 //-----------------------------------------------------------------------------
00789 void KMFldSearch::slotSaveMsg()
00790 {
00791     KMSaveMsgCommand *saveCommand = new KMSaveMsgCommand(this,
00792                              selectedMessages());
00793     if (saveCommand->url().isEmpty())
00794     delete saveCommand;
00795     else
00796     saveCommand->start();
00797 }
00798 //-----------------------------------------------------------------------------
00799 void KMFldSearch::slotSaveAttachments()
00800 {
00801     KMSaveAttachmentsCommand *saveCommand = new KMSaveAttachmentsCommand(this,
00802                                                                          selectedMessages());
00803     saveCommand->start();
00804 }
00805 
00806 
00807 //-----------------------------------------------------------------------------
00808 void KMFldSearch::slotPrintMsg()
00809 {
00810     KMCommand *command = new KMPrintCommand(this, message());
00811     command->start();
00812 }
00813 
00814 #include "kmfldsearch.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Dec 21 14:24:51 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003