00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022 #include "kmcommands.h"
00023 #include "searchwindow.h"
00024 #include "kmmainwidget.h"
00025 #include "kmmsgdict.h"
00026 #include "kmmsgpart.h"
00027 #include "kmfolderimap.h"
00028 #include "kmfoldermgr.h"
00029 #include "kmfoldersearch.h"
00030 #include "kmfoldertree.h"
00031 #include "kmheaders.h"
00032 #include "kmsearchpatternedit.h"
00033 #include "kmsearchpattern.h"
00034 #include "folderrequester.h"
00035 #include "messagecopyhelper.h"
00036 #include "textsource.h"
00037
00038 #include <kapplication.h>
00039 #include <kdebug.h>
00040 #include <kstatusbar.h>
00041 #include <kwin.h>
00042 #include <kconfig.h>
00043 #include <kstdaction.h>
00044 #include <kiconloader.h>
00045
00046 #include <qcheckbox.h>
00047 #include <qlayout.h>
00048 #include <klineedit.h>
00049 #include <qpushbutton.h>
00050 #include <qradiobutton.h>
00051 #include <qbuttongroup.h>
00052 #include <qcombobox.h>
00053 #include <qobjectlist.h>
00054 #include <qcursor.h>
00055 #include <qpopupmenu.h>
00056
00057 #include <maillistdrag.h>
00058 using namespace KPIM;
00059
00060 #include <mimelib/enum.h>
00061 #include <mimelib/boyermor.h>
00062
00063 #include <assert.h>
00064 #include <stdlib.h>
00065
00066 namespace KMail {
00067
00068 const int SearchWindow::MSGID_COLUMN = 4;
00069
00070
00071 class MatchListView : public KListView
00072 {
00073 public:
00074 MatchListView( QWidget *parent, SearchWindow* sw, const char* name = 0 ) :
00075 KListView( parent, name ),
00076 mSearchWindow( sw )
00077 {}
00078
00079 protected:
00080 virtual QDragObject* dragObject()
00081 {
00082 KMMessageList list = mSearchWindow->selectedMessages();
00083 MailList mailList;
00084 for ( KMMsgBase* msg = list.first(); msg; msg = list.next() ) {
00085 if ( !msg )
00086 continue;
00087 MailSummary mailSummary( msg->getMsgSerNum(), msg->msgIdMD5(),
00088 msg->subject(), msg->fromStrip(),
00089 msg->toStrip(), msg->date() );
00090 mailList.append( mailSummary );
00091 }
00092 MailListDrag *d = new MailListDrag( mailList, viewport(), new KMTextSource );
00093
00094 QPixmap pixmap;
00095 if( mailList.count() == 1 )
00096 pixmap = QPixmap( DesktopIcon("message", KIcon::SizeSmall) );
00097 else
00098 pixmap = QPixmap( DesktopIcon("kmultiple", KIcon::SizeSmall) );
00099
00100 d->setPixmap( pixmap );
00101 return d;
00102 }
00103
00104 private:
00105 SearchWindow* mSearchWindow;
00106 };
00107
00108
00109 SearchWindow::SearchWindow(KMMainWidget* w, const char* name,
00110 KMFolder *curFolder, bool modal):
00111 KDialogBase(0, name, modal, i18n("Find Messages"),
00112 User1 | User2 | Close, User1, false,
00113 KGuiItem( i18n("&Search"), "find" ),
00114 KStdGuiItem::stop()),
00115 mStopped(false),
00116 mCloseRequested(false),
00117 mSortColumn(0),
00118 mSortOrder(Ascending),
00119 mFolder(0),
00120 mTimer(new QTimer(this, "mTimer")),
00121 mLastFocus(0),
00122 mKMMainWidget(w)
00123 {
00124 #if !KDE_IS_VERSION( 3, 2, 91 )
00125
00126
00127
00128 XDeleteProperty( qt_xdisplay(), winId(), XA_WM_TRANSIENT_FOR );
00129 #endif
00130 KWin::setIcons(winId(), kapp->icon(), kapp->miniIcon());
00131
00132 KConfig* config = KMKernel::config();
00133 config->setGroup("SearchDialog");
00134
00135 QWidget* searchWidget = new QWidget(this);
00136 QVBoxLayout *vbl = new QVBoxLayout( searchWidget, 0, spacingHint(), "kmfs_vbl" );
00137
00138 QButtonGroup * radioGroup = new QButtonGroup( searchWidget );
00139 radioGroup->hide();
00140
00141 mChkbxAllFolders = new QRadioButton(i18n("Search in &all local folders"), searchWidget);
00142 vbl->addWidget( mChkbxAllFolders );
00143 radioGroup->insert( mChkbxAllFolders );
00144
00145 QHBoxLayout *hbl = new QHBoxLayout( vbl, spacingHint(), "kmfs_hbl" );
00146 mChkbxSpecificFolders = new QRadioButton(i18n("Search &only in:"), searchWidget);
00147 hbl->addWidget(mChkbxSpecificFolders);
00148 mChkbxSpecificFolders->setChecked(true);
00149 radioGroup->insert( mChkbxSpecificFolders );
00150
00151 mCbxFolders = new FolderRequester( searchWidget,
00152 kmkernel->getKMMainWidget()->folderTree() );
00153 mCbxFolders->setMustBeReadWrite( false );
00154 mCbxFolders->setFolder(curFolder);
00155 hbl->addWidget(mCbxFolders);
00156
00157 mChkSubFolders = new QCheckBox(i18n("I&nclude sub-folders"), searchWidget);
00158 mChkSubFolders->setChecked(true);
00159 hbl->addWidget(mChkSubFolders);
00160
00161 QWidget *spacer = new QWidget( searchWidget, "spacer" );
00162 spacer->setMinimumHeight( 2 );
00163 vbl->addWidget( spacer );
00164
00165 mPatternEdit = new KMSearchPatternEdit( "", searchWidget , "spe", false, true );
00166 mPatternEdit->setFrameStyle( QFrame::NoFrame | QFrame::Plain );
00167 mPatternEdit->setInsideMargin( 0 );
00168 mSearchPattern = new KMSearchPattern();
00169 KMFolderSearch *searchFolder = 0;
00170 if (curFolder)
00171 searchFolder = dynamic_cast<KMFolderSearch*>(curFolder->storage());
00172 if (searchFolder) {
00173 KConfig config(curFolder->location());
00174 KMFolder *root = searchFolder->search()->root();
00175 config.setGroup("Search Folder");
00176 mSearchPattern->readConfig(&config);
00177 if (root) {
00178 mChkbxSpecificFolders->setChecked(true);
00179 mCbxFolders->setFolder(root);
00180 mChkSubFolders->setChecked(searchFolder->search()->recursive());
00181 } else {
00182 mChkbxAllFolders->setChecked(true);
00183 }
00184 mFolder = searchFolder;
00185 }
00186 mPatternEdit->setSearchPattern( mSearchPattern );
00187 QObjectList *list = mPatternEdit->queryList( 0, "mRuleField" );
00188 QObject *object = 0;
00189 if ( list )
00190 object = list->first();
00191 delete list;
00192 if (!searchFolder && object && ::qt_cast<QComboBox*>(object))
00193 static_cast<QComboBox*>(object)->setCurrentText("Subject");
00194
00195 vbl->addWidget( mPatternEdit );
00196
00197
00198 connect( mChkbxSpecificFolders, SIGNAL(toggled(bool)),
00199 mCbxFolders, SLOT(setEnabled(bool)) );
00200 connect( mChkbxSpecificFolders, SIGNAL(toggled(bool)),
00201 mChkSubFolders, SLOT(setEnabled(bool)) );
00202 connect( mChkbxAllFolders, SIGNAL(toggled(bool)),
00203 this, SLOT(setEnabledSearchButton(bool)) );
00204
00205 mLbxMatches = new MatchListView(searchWidget, this, "Find Messages");
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 mLbxMatches->setSorting(2, false);
00221 mLbxMatches->setShowSortIndicator(true);
00222 mLbxMatches->setAllColumnsShowFocus(true);
00223 mLbxMatches->setSelectionModeExt(KListView::Extended);
00224 mLbxMatches->addColumn(i18n("Subject"),
00225 config->readNumEntry("SubjectWidth", 150));
00226 mLbxMatches->addColumn(i18n("Sender/Receiver"),
00227 config->readNumEntry("SenderWidth", 120));
00228 mLbxMatches->addColumn(i18n("Date"),
00229 config->readNumEntry("DateWidth", 120));
00230 mLbxMatches->addColumn(i18n("Folder"),
00231 config->readNumEntry("FolderWidth", 100));
00232
00233 mLbxMatches->addColumn("");
00234 mLbxMatches->setColumnWidthMode( MSGID_COLUMN, QListView::Manual );
00235 mLbxMatches->setColumnWidth(MSGID_COLUMN, 0);
00236 mLbxMatches->header()->setResizeEnabled(false, MSGID_COLUMN);
00237
00238 mLbxMatches->setDragEnabled( true );
00239
00240 connect(mLbxMatches, SIGNAL(doubleClicked(QListViewItem *)),
00241 this, SLOT(slotShowMsg(QListViewItem *)));
00242 connect(mLbxMatches, SIGNAL(currentChanged(QListViewItem *)),
00243 this, SLOT(slotCurrentChanged(QListViewItem *)));
00244 connect( mLbxMatches, SIGNAL( contextMenuRequested( QListViewItem*, const QPoint &, int )),
00245 this, SLOT( slotContextMenuRequested( QListViewItem*, const QPoint &, int )));
00246 vbl->addWidget(mLbxMatches);
00247
00248 QHBoxLayout *hbl2 = new QHBoxLayout( vbl, spacingHint(), "kmfs_hbl2" );
00249 mSearchFolderLbl = new QLabel(i18n("Search folder &name:"), searchWidget);
00250 hbl2->addWidget(mSearchFolderLbl);
00251 mSearchFolderEdt = new KLineEdit(searchWidget);
00252 if (searchFolder)
00253 mSearchFolderEdt->setText(searchFolder->folder()->name());
00254 else
00255 mSearchFolderEdt->setText(i18n("Last Search"));
00256
00257 mSearchFolderLbl->setBuddy(mSearchFolderEdt);
00258 hbl2->addWidget(mSearchFolderEdt);
00259 mSearchFolderOpenBtn = new QPushButton(i18n("Op&en Search Folder"), searchWidget);
00260 mSearchFolderOpenBtn->setEnabled(false);
00261 hbl2->addWidget(mSearchFolderOpenBtn);
00262 connect( mSearchFolderEdt, SIGNAL( textChanged( const QString &)),
00263 this, SLOT( scheduleRename( const QString & )));
00264 connect( &mRenameTimer, SIGNAL( timeout() ),
00265 this, SLOT( renameSearchFolder() ));
00266 connect( mSearchFolderOpenBtn, SIGNAL( clicked() ),
00267 this, SLOT( openSearchFolder() ));
00268 mSearchResultOpenBtn = new QPushButton(i18n("Open &Message"), searchWidget);
00269 mSearchResultOpenBtn->setEnabled(false);
00270 hbl2->addWidget(mSearchResultOpenBtn);
00271 connect( mSearchResultOpenBtn, SIGNAL( clicked() ),
00272 this, SLOT( slotShowSelectedMsg() ));
00273 mStatusBar = new KStatusBar(searchWidget);
00274 mStatusBar->insertFixedItem(i18n("AMiddleLengthText..."), 0, true);
00275 mStatusBar->changeItem(i18n("Ready."), 0);
00276 mStatusBar->setItemAlignment(0, AlignLeft | AlignVCenter);
00277 mStatusBar->insertItem(QString::null, 1, 1, true);
00278 mStatusBar->setItemAlignment(1, AlignLeft | AlignVCenter);
00279 vbl->addWidget(mStatusBar);
00280
00281 int mainWidth = config->readNumEntry("SearchWidgetWidth", 0);
00282 int mainHeight = config->readNumEntry("SearchWidgetHeight", 0);
00283
00284 if (mainWidth || mainHeight)
00285 resize(mainWidth, mainHeight);
00286
00287 setMainWidget(searchWidget);
00288 setButtonBoxOrientation(QWidget::Vertical);
00289
00290 mBtnSearch = actionButton(KDialogBase::User1);
00291 mBtnStop = actionButton(KDialogBase::User2);
00292 mBtnStop->setEnabled(false);
00293
00294 connect(this, SIGNAL(user1Clicked()), SLOT(slotSearch()));
00295 connect(this, SIGNAL(user2Clicked()), SLOT(slotStop()));
00296 connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));
00297
00298
00299 object = mPatternEdit->child( "regExpLineEdit" );
00300 if ( object && object->isWidgetType() ) {
00301 static_cast<QWidget*>(object)->setFocus();
00302
00303
00304 }
00305 else
00306 kdDebug(5006) << "SearchWindow: regExpLineEdit not found" << endl;
00307
00308
00309 KActionCollection *ac = actionCollection();
00310 ac->setWidget( this );
00311 mReplyAction = new KAction( i18n("&Reply..."), "mail_reply", 0, this,
00312 SLOT(slotReplyToMsg()), ac, "search_reply" );
00313 mReplyAllAction = new KAction( i18n("Reply to &All..."), "mail_replyall",
00314 0, this, SLOT(slotReplyAllToMsg()),
00315 ac, "search_reply_all" );
00316 mReplyListAction = new KAction( i18n("Reply to Mailing-&List..."),
00317 "mail_replylist", 0, this,
00318 SLOT(slotReplyListToMsg()), ac,
00319 "search_reply_list" );
00320 mForwardActionMenu = new KActionMenu( i18n("Message->","&Forward"),
00321 "mail_forward", ac,
00322 "search_message_forward" );
00323 connect( mForwardActionMenu, SIGNAL(activated()), this,
00324 SLOT(slotForwardInlineMsg()) );
00325 mForwardAttachedAction = new KAction( i18n("Message->Forward->","As &Attachment..."),
00326 "mail_forward", 0, this,
00327 SLOT(slotForwardAttachedMsg()), ac,
00328 "search_message_forward_as_attachment" );
00329 mForwardInlineAction = new KAction( i18n("&Inline..."),
00330 "mail_forward", 0, this,
00331 SLOT(slotForwardInlineMsg()), ac,
00332 "search_message_forward_inline" );
00333 if ( GlobalSettings::self()->forwardingInlineByDefault() ) {
00334 mForwardActionMenu->insert( mForwardInlineAction );
00335 mForwardActionMenu->insert( mForwardAttachedAction );
00336 } else {
00337 mForwardActionMenu->insert( mForwardAttachedAction );
00338 mForwardActionMenu->insert( mForwardInlineAction );
00339 }
00340
00341 mForwardDigestAction = new KAction( i18n("Message->Forward->","As Di&gest..."),
00342 "mail_forward", 0, this,
00343 SLOT(slotForwardDigestMsg()), ac,
00344 "search_message_forward_as_digest" );
00345 mForwardActionMenu->insert( mForwardDigestAction );
00346 mRedirectAction = new KAction( i18n("Message->Forward->","&Redirect..."),
00347 "mail_forward", 0, this,
00348 SLOT(slotRedirectMsg()), ac,
00349 "search_message_forward_redirect" );
00350 mForwardActionMenu->insert( mRedirectAction );
00351 mSaveAsAction = KStdAction::saveAs( this, SLOT(slotSaveMsg()), ac, "search_file_save_as" );
00352 mSaveAtchAction = new KAction( i18n("Save Attachments..."), "attach", 0,
00353 this, SLOT(slotSaveAttachments()), ac, "search_save_attachments" );
00354
00355 mPrintAction = KStdAction::print( this, SLOT(slotPrintMsg()), ac, "search_print" );
00356 mClearAction = new KAction( i18n("Clear Selection"), 0, 0, this,
00357 SLOT(slotClearSelection()), ac, "search_clear_selection" );
00358
00359 mCopyAction = KStdAction::copy( this, SLOT(slotCopyMsgs()), ac, "search_copy_messages" );
00360 mCutAction = KStdAction::cut( this, SLOT(slotCutMsgs()), ac, "search_cut_messages" );
00361
00362 connect(mTimer, SIGNAL(timeout()), this, SLOT(updStatus()));
00363 connect(kmkernel->searchFolderMgr(), SIGNAL(folderInvalidated(KMFolder*)),
00364 this, SLOT(folderInvalidated(KMFolder*)));
00365
00366 connect(mCbxFolders, SIGNAL(folderChanged(KMFolder*)),
00367 this, SLOT(slotFolderActivated()));
00368
00369 }
00370
00371
00372 SearchWindow::~SearchWindow()
00373 {
00374 QValueListIterator<QGuardedPtr<KMFolder> > fit;
00375 for ( fit = mFolders.begin(); fit != mFolders.end(); ++fit ) {
00376 if (!(*fit))
00377 continue;
00378 (*fit)->close("searchwindow");
00379 }
00380
00381 KConfig* config = KMKernel::config();
00382 config->setGroup("SearchDialog");
00383 config->writeEntry("SubjectWidth", mLbxMatches->columnWidth(0));
00384 config->writeEntry("SenderWidth", mLbxMatches->columnWidth(1));
00385 config->writeEntry("DateWidth", mLbxMatches->columnWidth(2));
00386 config->writeEntry("FolderWidth", mLbxMatches->columnWidth(3));
00387 config->writeEntry("SearchWidgetWidth", width());
00388 config->writeEntry("SearchWidgetHeight", height());
00389 config->sync();
00390 }
00391
00392 void SearchWindow::setEnabledSearchButton(bool)
00393 {
00394
00395
00396
00397
00398 mBtnSearch->setEnabled( true );
00399 }
00400
00401
00402 void SearchWindow::updStatus(void)
00403 {
00404 QString genMsg, detailMsg, procMsg;
00405 int numMatches = 0, numProcessed = 0;
00406 KMSearch const *search = (mFolder) ? (mFolder->search()) : 0;
00407 QString folderName;
00408 if (search) {
00409 numMatches = search->foundCount();
00410 numProcessed = search->searchCount();
00411 folderName = search->currentFolder();
00412 }
00413
00414 if (search && !search->running()) {
00415 procMsg = i18n("%n message searched", "%n messages searched",
00416 numProcessed);
00417 if(!mStopped) {
00418 genMsg = i18n("Done.");
00419 detailMsg = i18n("%n match in %1", "%n matches in %1",
00420 numMatches).arg(procMsg);
00421 } else {
00422 genMsg = i18n("Search canceled.");
00423 detailMsg = i18n("%n match so far in %1", "%n matches so far in %1",
00424 numMatches).arg(procMsg);
00425 }
00426 } else {
00427 procMsg = i18n("%n message", "%n messages", numProcessed);
00428 genMsg = i18n("%n match", "%n matches", numMatches);
00429 detailMsg = i18n("Searching in %1. %2 searched so far")
00430 .arg(folderName).arg(procMsg);
00431 }
00432
00433 mStatusBar->changeItem(genMsg, 0);
00434 mStatusBar->changeItem(detailMsg, 1);
00435 }
00436
00437
00438
00439 void SearchWindow::keyPressEvent(QKeyEvent *evt)
00440 {
00441 KMSearch const *search = (mFolder) ? mFolder->search() : 0;
00442 bool searching = (search) ? search->running() : false;
00443 if (evt->key() == Key_Escape && searching) {
00444 mFolder->stopSearch();
00445 return;
00446 }
00447
00448 KDialogBase::keyPressEvent(evt);
00449 }
00450
00451
00452
00453 void SearchWindow::slotFolderActivated()
00454 {
00455 mChkbxSpecificFolders->setChecked(true);
00456 }
00457
00458
00459 void SearchWindow::activateFolder(KMFolder *curFolder)
00460 {
00461 mChkbxSpecificFolders->setChecked(true);
00462 mCbxFolders->setFolder(curFolder);
00463 }
00464
00465
00466 void SearchWindow::slotSearch()
00467 {
00468 mLastFocus = focusWidget();
00469 mBtnSearch->setFocus();
00470
00471 mStopped = false;
00472 mFetchingInProgress = 0;
00473
00474 mSearchFolderOpenBtn->setEnabled(true);
00475 if ( mSearchFolderEdt->text().isEmpty() ) {
00476 mSearchFolderEdt->setText( i18n("Last Search") );
00477 }
00478 mBtnSearch->setEnabled(false);
00479 mBtnStop->setEnabled(true);
00480
00481 mLbxMatches->clear();
00482
00483 mSortColumn = mLbxMatches->sortColumn();
00484 mSortOrder = mLbxMatches->sortOrder();
00485 mLbxMatches->setSorting(-1);
00486 mLbxMatches->setShowSortIndicator(false);
00487
00488
00489
00490 if (!mFolder) {
00491 KMFolderMgr *mgr = kmkernel->searchFolderMgr();
00492 QString baseName = mSearchFolderEdt->text();
00493 QString fullName = baseName;
00494 int count = 0;
00495 KMFolder *folder;
00496 while ((folder = mgr->find(fullName))) {
00497 if (folder->storage()->inherits("KMFolderSearch"))
00498 break;
00499 fullName = QString("%1 %2").arg(baseName).arg(++count);
00500 }
00501
00502 if (!folder)
00503 folder = mgr->createFolder(fullName, false, KMFolderTypeSearch,
00504 &mgr->dir());
00505
00506 mFolder = dynamic_cast<KMFolderSearch*>( folder->storage() );
00507 }
00508 mFolder->stopSearch();
00509 disconnect(mFolder, SIGNAL(msgAdded(int)),
00510 this, SLOT(slotAddMsg(int)));
00511 disconnect(mFolder, SIGNAL(msgRemoved(KMFolder*, Q_UINT32)),
00512 this, SLOT(slotRemoveMsg(KMFolder*, Q_UINT32)));
00513 connect(mFolder, SIGNAL(msgAdded(int)),
00514 this, SLOT(slotAddMsg(int)));
00515 connect(mFolder, SIGNAL(msgRemoved(KMFolder*, Q_UINT32)),
00516 this, SLOT(slotRemoveMsg(KMFolder*, Q_UINT32)));
00517 mSearchFolderEdt->setEnabled(false);
00518 KMSearch *search = new KMSearch();
00519 connect(search, SIGNAL(finished(bool)),
00520 this, SLOT(searchDone()));
00521 if (mChkbxAllFolders->isChecked()) {
00522 search->setRecursive(true);
00523 } else {
00524 search->setRoot(mCbxFolders->folder());
00525 search->setRecursive(mChkSubFolders->isChecked());
00526 }
00527
00528 mPatternEdit->updateSearchPattern();
00529 KMSearchPattern *searchPattern = new KMSearchPattern();
00530 *searchPattern = *mSearchPattern;
00531 searchPattern->purify();
00532 search->setSearchPattern(searchPattern);
00533 mFolder->setSearch(search);
00534 enableGUI();
00535
00536 mTimer->start(200);
00537 }
00538
00539
00540 void SearchWindow::searchDone()
00541 {
00542 mTimer->stop();
00543 updStatus();
00544
00545 QTimer::singleShot(0, this, SLOT(enableGUI()));
00546 if(mLastFocus)
00547 mLastFocus->setFocus();
00548 if (mCloseRequested)
00549 close();
00550
00551 mLbxMatches->setSorting(mSortColumn, mSortOrder == Ascending);
00552 mLbxMatches->setShowSortIndicator(true);
00553
00554 mSearchFolderEdt->setEnabled(true);
00555 }
00556
00557 void SearchWindow::slotAddMsg(int idx)
00558 {
00559 if (!mFolder)
00560 return;
00561 bool unget = !mFolder->isMessage(idx);
00562 KMMessage *msg = mFolder->getMsg(idx);
00563 QString from, fName;
00564 KMFolder *pFolder = msg->parent();
00565 if (!mFolders.contains(pFolder)) {
00566 mFolders.append(pFolder);
00567 pFolder->open("searchwindow");
00568 }
00569 if(pFolder->whoField() == "To")
00570 from = msg->to();
00571 else
00572 from = msg->from();
00573 if (pFolder->isSystemFolder())
00574 fName = i18n(pFolder->name().utf8());
00575 else
00576 fName = pFolder->name();
00577
00578 (void)new KListViewItem(mLbxMatches, mLbxMatches->lastItem(),
00579 msg->subject(), from, msg->dateIsoStr(),
00580 fName,
00581 QString::number(mFolder->serNum(idx)));
00582 if (unget)
00583 mFolder->unGetMsg(idx);
00584 }
00585
00586 void SearchWindow::slotRemoveMsg(KMFolder *, Q_UINT32 serNum)
00587 {
00588 if (!mFolder)
00589 return;
00590 QListViewItemIterator it(mLbxMatches);
00591 while (it.current()) {
00592 QListViewItem *item = *it;
00593 if (serNum == (*it)->text(MSGID_COLUMN).toUInt()) {
00594 delete item;
00595 return;
00596 }
00597 ++it;
00598 }
00599 }
00600
00601
00602 void SearchWindow::slotStop()
00603 {
00604 if (mFolder)
00605 mFolder->stopSearch();
00606 mStopped = true;
00607 mBtnStop->setEnabled(false);
00608 }
00609
00610
00611 void SearchWindow::slotClose()
00612 {
00613 accept();
00614 }
00615
00616
00617
00618 void SearchWindow::closeEvent(QCloseEvent *e)
00619 {
00620 if (mFolder && mFolder->search() && mFolder->search()->running()) {
00621 mCloseRequested = true;
00622
00623
00624 mFolder->setSearch(new KMSearch());
00625 QTimer::singleShot(0, this, SLOT(slotClose()));
00626 } else {
00627 KDialogBase::closeEvent(e);
00628 }
00629 }
00630
00631
00632 void SearchWindow::scheduleRename( const QString &s)
00633 {
00634 if (!s.isEmpty() ) {
00635 mRenameTimer.start(250, true);
00636 mSearchFolderOpenBtn->setEnabled(false);
00637 } else {
00638 mRenameTimer.stop();
00639 mSearchFolderOpenBtn->setEnabled(!s.isEmpty());
00640 }
00641 }
00642
00643
00644 void SearchWindow::renameSearchFolder()
00645 {
00646 if (mFolder && (mFolder->folder()->name() != mSearchFolderEdt->text())) {
00647 int i = 1;
00648 QString name = mSearchFolderEdt->text();
00649 while (i < 100) {
00650 if (!kmkernel->searchFolderMgr()->find( name )) {
00651 mFolder->rename( name );
00652 kmkernel->searchFolderMgr()->contentsChanged();
00653 break;
00654 }
00655 name.setNum( i );
00656 name = mSearchFolderEdt->text() + " " + name;
00657 ++i;
00658 }
00659 }
00660 if ( mFolder )
00661 mSearchFolderOpenBtn->setEnabled(true);
00662 }
00663
00664 void SearchWindow::openSearchFolder()
00665 {
00666 Q_ASSERT( mFolder );
00667 renameSearchFolder();
00668 mKMMainWidget->slotSelectFolder( mFolder->folder() );
00669 slotClose();
00670 }
00671
00672
00673 void SearchWindow::folderInvalidated(KMFolder *folder)
00674 {
00675 if (folder->storage() == mFolder) {
00676 mLbxMatches->clear();
00677 if (mFolder->search())
00678 connect(mFolder->search(), SIGNAL(finished(bool)),
00679 this, SLOT(searchDone()));
00680 mTimer->start(200);
00681 enableGUI();
00682 }
00683 }
00684
00685
00686 bool SearchWindow::slotShowMsg(QListViewItem *item)
00687 {
00688 if(!item)
00689 return false;
00690
00691 KMFolder* folder;
00692 int msgIndex;
00693 KMMsgDict::instance()->getLocation(item->text(MSGID_COLUMN).toUInt(),
00694 &folder, &msgIndex);
00695
00696 if (!folder || msgIndex < 0)
00697 return false;
00698
00699 mKMMainWidget->slotSelectFolder(folder);
00700 KMMessage* message = folder->getMsg(msgIndex);
00701 if (!message)
00702 return false;
00703
00704 mKMMainWidget->slotSelectMessage(message);
00705 return true;
00706 }
00707
00708
00709 void SearchWindow::slotShowSelectedMsg()
00710 {
00711 slotShowMsg(mLbxMatches->currentItem());
00712 }
00713
00714
00715 void SearchWindow::slotCurrentChanged(QListViewItem *item)
00716 {
00717 mSearchResultOpenBtn->setEnabled(item!=0);
00718 }
00719
00720
00721 void SearchWindow::enableGUI()
00722 {
00723 KMSearch const *search = (mFolder) ? (mFolder->search()) : 0;
00724 bool searching = (search) ? (search->running()) : false;
00725 actionButton(KDialogBase::Close)->setEnabled(!searching);
00726 mCbxFolders->setEnabled(!searching && !mChkbxAllFolders->isChecked());
00727 mChkSubFolders->setEnabled(!searching && !mChkbxAllFolders->isChecked());
00728 mChkbxAllFolders->setEnabled(!searching);
00729 mChkbxSpecificFolders->setEnabled(!searching);
00730 mPatternEdit->setEnabled(!searching);
00731 mBtnSearch->setEnabled(!searching);
00732 mBtnStop->setEnabled(searching);
00733 }
00734
00735
00736
00737 KMMessageList SearchWindow::selectedMessages()
00738 {
00739 KMMessageList msgList;
00740 KMFolder* folder = 0;
00741 int msgIndex = -1;
00742 for (QListViewItemIterator it(mLbxMatches); it.current(); it++)
00743 if (it.current()->isSelected()) {
00744 KMMsgDict::instance()->getLocation((*it)->text(MSGID_COLUMN).toUInt(),
00745 &folder, &msgIndex);
00746 if (folder && msgIndex >= 0)
00747 msgList.append(folder->getMsgBase(msgIndex));
00748 }
00749 return msgList;
00750 }
00751
00752
00753 KMMessage* SearchWindow::message()
00754 {
00755 QListViewItem *item = mLbxMatches->currentItem();
00756 KMFolder* folder = 0;
00757 int msgIndex = -1;
00758 if (!item)
00759 return 0;
00760 KMMsgDict::instance()->getLocation(item->text(MSGID_COLUMN).toUInt(),
00761 &folder, &msgIndex);
00762 if (!folder || msgIndex < 0)
00763 return 0;
00764
00765 return folder->getMsg(msgIndex);
00766 }
00767
00768
00769 void SearchWindow::moveSelectedToFolder( int menuId )
00770 {
00771 KMFolder *dest = mMenuToFolder[menuId];
00772 if (!dest)
00773 return;
00774
00775 KMMessageList msgList = selectedMessages();
00776 KMCommand *command = new KMMoveCommand( dest, msgList );
00777 command->start();
00778 }
00779
00780
00781 void SearchWindow::copySelectedToFolder( int menuId )
00782 {
00783 KMFolder *dest = mMenuToFolder[menuId];
00784 if (!dest)
00785 return;
00786
00787 KMMessageList msgList = selectedMessages();
00788 KMCommand *command = new KMCopyCommand( dest, msgList );
00789 command->start();
00790 }
00791
00792
00793 void SearchWindow::updateContextMenuActions()
00794 {
00795 int count = selectedMessages().count();
00796 bool single_actions = count == 1;
00797 mReplyAction->setEnabled( single_actions );
00798 mReplyAllAction->setEnabled( single_actions );
00799 mReplyListAction->setEnabled( single_actions );
00800 mPrintAction->setEnabled( single_actions );
00801 mForwardDigestAction->setEnabled( !single_actions );
00802 mRedirectAction->setEnabled( single_actions );
00803 mCopyAction->setEnabled( count > 0 );
00804 mCutAction->setEnabled( count > 0 );
00805 }
00806
00807
00808 void SearchWindow::slotContextMenuRequested( QListViewItem *lvi, const QPoint &, int )
00809 {
00810 if (!lvi)
00811 return;
00812 mLbxMatches->setSelected( lvi, true );
00813 mLbxMatches->setCurrentItem( lvi );
00814
00815 if (!message())
00816 return;
00817 QPopupMenu *menu = new QPopupMenu(this);
00818 updateContextMenuActions();
00819
00820 mMenuToFolder.clear();
00821 QPopupMenu *msgMoveMenu = new QPopupMenu(menu);
00822 mKMMainWidget->folderTree()->folderToPopupMenu( KMFolderTree::MoveMessage,
00823 this, &mMenuToFolder, msgMoveMenu );
00824 QPopupMenu *msgCopyMenu = new QPopupMenu(menu);
00825 mKMMainWidget->folderTree()->folderToPopupMenu( KMFolderTree::CopyMessage,
00826 this, &mMenuToFolder, msgCopyMenu );
00827
00828
00829 mReplyAction->plug(menu);
00830 mReplyAllAction->plug(menu);
00831 mReplyListAction->plug(menu);
00832 mForwardActionMenu->plug(menu);
00833 menu->insertSeparator();
00834 mCopyAction->plug(menu);
00835 mCutAction->plug(menu);
00836 menu->insertItem(i18n("&Copy To"), msgCopyMenu);
00837 menu->insertItem(i18n("&Move To"), msgMoveMenu);
00838 menu->insertSeparator();
00839 mSaveAsAction->plug(menu);
00840 mSaveAtchAction->plug(menu);
00841 mPrintAction->plug(menu);
00842 menu->insertSeparator();
00843 mClearAction->plug(menu);
00844 menu->exec (QCursor::pos(), 0);
00845 delete menu;
00846 }
00847
00848
00849 void SearchWindow::slotClearSelection()
00850 {
00851 mLbxMatches->clearSelection();
00852 }
00853
00854
00855 void SearchWindow::slotReplyToMsg()
00856 {
00857 KMCommand *command = new KMReplyToCommand(this, message());
00858 command->start();
00859 }
00860
00861
00862 void SearchWindow::slotReplyAllToMsg()
00863 {
00864 KMCommand *command = new KMReplyToAllCommand(this, message());
00865 command->start();
00866 }
00867
00868
00869 void SearchWindow::slotReplyListToMsg()
00870 {
00871 KMCommand *command = new KMReplyListCommand(this, message());
00872 command->start();
00873 }
00874
00875
00876 void SearchWindow::slotForwardInlineMsg()
00877 {
00878 KMCommand *command = new KMForwardInlineCommand(this, selectedMessages());
00879 command->start();
00880 }
00881
00882
00883 void SearchWindow::slotForwardAttachedMsg()
00884 {
00885 KMCommand *command = new KMForwardAttachedCommand(this, selectedMessages());
00886 command->start();
00887 }
00888
00889
00890 void SearchWindow::slotForwardDigestMsg()
00891 {
00892 KMCommand *command = new KMForwardDigestCommand(this, selectedMessages());
00893 command->start();
00894 }
00895
00896
00897 void SearchWindow::slotRedirectMsg()
00898 {
00899 KMCommand *command = new KMRedirectCommand(this, message());
00900 command->start();
00901 }
00902
00903
00904 void SearchWindow::slotSaveMsg()
00905 {
00906 KMSaveMsgCommand *saveCommand = new KMSaveMsgCommand(this,
00907 selectedMessages());
00908 if (saveCommand->url().isEmpty())
00909 delete saveCommand;
00910 else
00911 saveCommand->start();
00912 }
00913
00914 void SearchWindow::slotSaveAttachments()
00915 {
00916 KMSaveAttachmentsCommand *saveCommand = new KMSaveAttachmentsCommand(this,
00917 selectedMessages());
00918 saveCommand->start();
00919 }
00920
00921
00922
00923 void SearchWindow::slotPrintMsg()
00924 {
00925 KMCommand *command = new KMPrintCommand(this, message());
00926 command->start();
00927 }
00928
00929 void SearchWindow::slotCopyMsgs()
00930 {
00931 QValueList<Q_UINT32> list = MessageCopyHelper::serNumListFromMsgList( selectedMessages() );
00932 mKMMainWidget->headers()->setCopiedMessages( list, false );
00933 }
00934
00935 void SearchWindow::slotCutMsgs()
00936 {
00937 QValueList<Q_UINT32> list = MessageCopyHelper::serNumListFromMsgList( selectedMessages() );
00938 mKMMainWidget->headers()->setCopiedMessages( list, true );
00939 }
00940
00941
00942 void SearchWindow::setSearchPattern( const KMSearchPattern& pattern )
00943 {
00944 *mSearchPattern = pattern;
00945 mPatternEdit->setSearchPattern( mSearchPattern );
00946 }
00947
00948 }
00949 #include "searchwindow.moc"