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 <tqcheckbox.h>
00047 #include <tqlayout.h>
00048 #include <klineedit.h>
00049 #include <tqpushbutton.h>
00050 #include <tqradiobutton.h>
00051 #include <tqbuttongroup.h>
00052 #include <tqcombobox.h>
00053 #include <tqobjectlist.h>
00054 #include <tqcursor.h>
00055 #include <tqpopupmenu.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( TQWidget *parent, SearchWindow* sw, const char* name = 0 ) :
00075 KListView( parent, name ),
00076 mSearchWindow( sw )
00077 {}
00078
00079 protected:
00080 virtual TQDragObject* 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 TQPixmap pixmap;
00095 if( mailList.count() == 1 )
00096 pixmap = TQPixmap( DesktopIcon("message", KIcon::SizeSmall) );
00097 else
00098 pixmap = TQPixmap( 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 TQTimer(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 TQWidget* searchWidget = new TQWidget(this);
00136 TQVBoxLayout *vbl = new TQVBoxLayout( searchWidget, 0, spacingHint(), "kmfs_vbl" );
00137
00138 TQButtonGroup * radioGroup = new TQButtonGroup( searchWidget );
00139 radioGroup->hide();
00140
00141 mChkbxAllFolders = new TQRadioButton(i18n("Search in &all local folders"), searchWidget);
00142 vbl->addWidget( mChkbxAllFolders );
00143 radioGroup->insert( mChkbxAllFolders );
00144
00145 TQHBoxLayout *hbl = new TQHBoxLayout( vbl, spacingHint(), "kmfs_hbl" );
00146 mChkbxSpecificFolders = new TQRadioButton(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 TQCheckBox(i18n("I&nclude sub-folders"), searchWidget);
00158 mChkSubFolders->setChecked(true);
00159 hbl->addWidget(mChkSubFolders);
00160
00161 TQWidget *spacer = new TQWidget( searchWidget, "spacer" );
00162 spacer->setMinimumHeight( 2 );
00163 vbl->addWidget( spacer );
00164
00165 mPatternEdit = new KMSearchPatternEdit( "", searchWidget , "spe", false, true );
00166 mPatternEdit->setFrameStyle( TQFrame::NoFrame | TQFrame::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 }
00185 mPatternEdit->setSearchPattern( mSearchPattern );
00186 TQObjectList *list = mPatternEdit->queryList( 0, "mRuleField" );
00187 TQObject *object = 0;
00188 if ( list )
00189 object = list->first();
00190 delete list;
00191 if (!searchFolder && object && ::qt_cast<TQComboBox*>(object))
00192 static_cast<TQComboBox*>(object)->setCurrentText("Subject");
00193
00194 vbl->addWidget( mPatternEdit );
00195
00196
00197 connect( mChkbxSpecificFolders, TQT_SIGNAL(toggled(bool)),
00198 mCbxFolders, TQT_SLOT(setEnabled(bool)) );
00199 connect( mChkbxSpecificFolders, TQT_SIGNAL(toggled(bool)),
00200 mChkSubFolders, TQT_SLOT(setEnabled(bool)) );
00201 connect( mChkbxAllFolders, TQT_SIGNAL(toggled(bool)),
00202 this, TQT_SLOT(setEnabledSearchButton(bool)) );
00203
00204 mLbxMatches = new MatchListView(searchWidget, this, "Find Messages");
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 mLbxMatches->setSorting(2, false);
00220 mLbxMatches->setShowSortIndicator(true);
00221 mLbxMatches->setAllColumnsShowFocus(true);
00222 mLbxMatches->setSelectionModeExt(KListView::Extended);
00223 mLbxMatches->addColumn(i18n("Subject"),
00224 config->readNumEntry("SubjectWidth", 150));
00225 mLbxMatches->addColumn(i18n("Sender/Receiver"),
00226 config->readNumEntry("SenderWidth", 120));
00227 mLbxMatches->addColumn(i18n("Date"),
00228 config->readNumEntry("DateWidth", 120));
00229 mLbxMatches->addColumn(i18n("Folder"),
00230 config->readNumEntry("FolderWidth", 100));
00231
00232 mLbxMatches->addColumn("");
00233 mLbxMatches->setColumnWidthMode( MSGID_COLUMN, TQListView::Manual );
00234 mLbxMatches->setColumnWidth(MSGID_COLUMN, 0);
00235 mLbxMatches->header()->setResizeEnabled(false, MSGID_COLUMN);
00236
00237 mLbxMatches->setDragEnabled( true );
00238
00239 connect( mLbxMatches, TQT_SIGNAL(clicked(TQListViewItem *)),
00240 this, TQT_SLOT(slotShowMsg(TQListViewItem *)) );
00241 connect( mLbxMatches, TQT_SIGNAL(doubleClicked(TQListViewItem *)),
00242 this, TQT_SLOT(slotViewMsg(TQListViewItem *)) );
00243 connect( mLbxMatches, TQT_SIGNAL(currentChanged(TQListViewItem *)),
00244 this, TQT_SLOT(slotCurrentChanged(TQListViewItem *)) );
00245 connect( mLbxMatches, TQT_SIGNAL(contextMenuRequested(TQListViewItem *,const TQPoint &,int)),
00246 this, TQT_SLOT(slotContextMenuRequested(TQListViewItem *,const TQPoint &,int)) );
00247 vbl->addWidget( mLbxMatches );
00248
00249 TQHBoxLayout *hbl2 = new TQHBoxLayout( vbl, spacingHint(), "kmfs_hbl2" );
00250 mSearchFolderLbl = new TQLabel(i18n("Search folder &name:"), searchWidget);
00251 hbl2->addWidget(mSearchFolderLbl);
00252 mSearchFolderEdt = new KLineEdit(searchWidget);
00253 if (searchFolder)
00254 mSearchFolderEdt->setText(searchFolder->folder()->name());
00255 else
00256 mSearchFolderEdt->setText(i18n("Last Search"));
00257
00258 mSearchFolderLbl->setBuddy(mSearchFolderEdt);
00259 hbl2->addWidget(mSearchFolderEdt);
00260 mSearchFolderOpenBtn = new TQPushButton(i18n("Op&en Search Folder"), searchWidget);
00261 mSearchFolderOpenBtn->setEnabled(false);
00262 hbl2->addWidget(mSearchFolderOpenBtn);
00263 connect( mSearchFolderEdt, TQT_SIGNAL( textChanged( const TQString &)),
00264 this, TQT_SLOT( scheduleRename( const TQString & )));
00265 connect( &mRenameTimer, TQT_SIGNAL( timeout() ),
00266 this, TQT_SLOT( renameSearchFolder() ));
00267 connect( mSearchFolderOpenBtn, TQT_SIGNAL( clicked() ),
00268 this, TQT_SLOT( openSearchFolder() ));
00269 mSearchResultOpenBtn = new TQPushButton(i18n("Open &Message"), searchWidget);
00270 mSearchResultOpenBtn->setEnabled(false);
00271 hbl2->addWidget(mSearchResultOpenBtn);
00272 connect( mSearchResultOpenBtn, TQT_SIGNAL( clicked() ),
00273 this, TQT_SLOT( slotViewSelectedMsg() ));
00274 mStatusBar = new KStatusBar(searchWidget);
00275 mStatusBar->insertFixedItem(i18n("AMiddleLengthText..."), 0, true);
00276 mStatusBar->changeItem(i18n("Ready."), 0);
00277 mStatusBar->setItemAlignment(0, AlignLeft | AlignVCenter);
00278 mStatusBar->insertItem(TQString::null, 1, 1, true);
00279 mStatusBar->setItemAlignment(1, AlignLeft | AlignVCenter);
00280 vbl->addWidget(mStatusBar);
00281
00282 int mainWidth = config->readNumEntry("SearchWidgetWidth", 0);
00283 int mainHeight = config->readNumEntry("SearchWidgetHeight", 0);
00284
00285 if (mainWidth || mainHeight)
00286 resize(mainWidth, mainHeight);
00287
00288 setMainWidget(searchWidget);
00289 setButtonBoxOrientation(TQWidget::Vertical);
00290
00291 mBtnSearch = actionButton(KDialogBase::User1);
00292 mBtnStop = actionButton(KDialogBase::User2);
00293 mBtnStop->setEnabled(false);
00294
00295 connect(this, TQT_SIGNAL(user1Clicked()), TQT_SLOT(slotSearch()));
00296 connect(this, TQT_SIGNAL(user2Clicked()), TQT_SLOT(slotStop()));
00297 connect(this, TQT_SIGNAL(finished()), this, TQT_SLOT(deleteLater()));
00298
00299
00300 object = mPatternEdit->child( "regExpLineEdit" );
00301 if ( object && object->isWidgetType() ) {
00302 static_cast<TQWidget*>(object)->setFocus();
00303
00304
00305 }
00306 else
00307 kdDebug(5006) << "SearchWindow: regExpLineEdit not found" << endl;
00308
00309
00310 KActionCollection *ac = actionCollection();
00311 ac->setWidget( this );
00312 mReplyAction = new KAction( i18n("&Reply..."), "mail_reply", 0, this,
00313 TQT_SLOT(slotReplyToMsg()), ac, "search_reply" );
00314 mReplyAllAction = new KAction( i18n("Reply to &All..."), "mail_replyall",
00315 0, this, TQT_SLOT(slotReplyAllToMsg()),
00316 ac, "search_reply_all" );
00317 mReplyListAction = new KAction( i18n("Reply to Mailing-&List..."),
00318 "mail_replylist", 0, this,
00319 TQT_SLOT(slotReplyListToMsg()), ac,
00320 "search_reply_list" );
00321 mForwardActionMenu = new KActionMenu( i18n("Message->","&Forward"),
00322 "mail_forward", ac,
00323 "search_message_forward" );
00324 connect( mForwardActionMenu, TQT_SIGNAL(activated()), this,
00325 TQT_SLOT(slotForwardInlineMsg()) );
00326 mForwardAttachedAction = new KAction( i18n("Message->Forward->","As &Attachment..."),
00327 "mail_forward", 0, this,
00328 TQT_SLOT(slotForwardAttachedMsg()), ac,
00329 "search_message_forward_as_attachment" );
00330 mForwardInlineAction = new KAction( i18n("&Inline..."),
00331 "mail_forward", 0, this,
00332 TQT_SLOT(slotForwardInlineMsg()), ac,
00333 "search_message_forward_inline" );
00334 if ( GlobalSettings::self()->forwardingInlineByDefault() ) {
00335 mForwardActionMenu->insert( mForwardInlineAction );
00336 mForwardActionMenu->insert( mForwardAttachedAction );
00337 } else {
00338 mForwardActionMenu->insert( mForwardAttachedAction );
00339 mForwardActionMenu->insert( mForwardInlineAction );
00340 }
00341
00342 mForwardDigestAction = new KAction( i18n("Message->Forward->","As Di&gest..."),
00343 "mail_forward", 0, this,
00344 TQT_SLOT(slotForwardDigestMsg()), ac,
00345 "search_message_forward_as_digest" );
00346 mForwardActionMenu->insert( mForwardDigestAction );
00347 mRedirectAction = new KAction( i18n("Message->Forward->","&Redirect..."),
00348 "mail_forward", 0, this,
00349 TQT_SLOT(slotRedirectMsg()), ac,
00350 "search_message_forward_redirect" );
00351 mForwardActionMenu->insert( mRedirectAction );
00352 mSaveAsAction = KStdAction::saveAs( this, TQT_SLOT(slotSaveMsg()), ac, "search_file_save_as" );
00353 mSaveAtchAction = new KAction( i18n("Save Attachments..."), "attach", 0,
00354 this, TQT_SLOT(slotSaveAttachments()), ac, "search_save_attachments" );
00355
00356 mPrintAction = KStdAction::print( this, TQT_SLOT(slotPrintMsg()), ac, "search_print" );
00357 mClearAction = new KAction( i18n("Clear Selection"), 0, 0, this,
00358 TQT_SLOT(slotClearSelection()), ac, "search_clear_selection" );
00359
00360 mCopyAction = KStdAction::copy( this, TQT_SLOT(slotCopyMsgs()), ac, "search_copy_messages" );
00361 mCutAction = KStdAction::cut( this, TQT_SLOT(slotCutMsgs()), ac, "search_cut_messages" );
00362
00363 connect(mTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(updStatus()));
00364 connect(kmkernel->searchFolderMgr(), TQT_SIGNAL(folderInvalidated(KMFolder*)),
00365 this, TQT_SLOT(folderInvalidated(KMFolder*)));
00366
00367 connect(mCbxFolders, TQT_SIGNAL(folderChanged(KMFolder*)),
00368 this, TQT_SLOT(slotFolderActivated()));
00369
00370 }
00371
00372
00373 SearchWindow::~SearchWindow()
00374 {
00375 TQValueListIterator<TQGuardedPtr<KMFolder> > fit;
00376 for ( fit = mFolders.begin(); fit != mFolders.end(); ++fit ) {
00377 if (!(*fit))
00378 continue;
00379 (*fit)->close("searchwindow");
00380 }
00381
00382 KConfig* config = KMKernel::config();
00383 config->setGroup("SearchDialog");
00384 config->writeEntry("SubjectWidth", mLbxMatches->columnWidth(0));
00385 config->writeEntry("SenderWidth", mLbxMatches->columnWidth(1));
00386 config->writeEntry("DateWidth", mLbxMatches->columnWidth(2));
00387 config->writeEntry("FolderWidth", mLbxMatches->columnWidth(3));
00388 config->writeEntry("SearchWidgetWidth", width());
00389 config->writeEntry("SearchWidgetHeight", height());
00390 config->sync();
00391 }
00392
00393 void SearchWindow::setEnabledSearchButton(bool)
00394 {
00395
00396
00397
00398
00399 mBtnSearch->setEnabled( true );
00400 }
00401
00402
00403 void SearchWindow::updStatus(void)
00404 {
00405 TQString genMsg, detailMsg, procMsg;
00406 int numMatches = 0, numProcessed = 0;
00407 KMSearch const *search = (mFolder) ? (mFolder->search()) : 0;
00408 TQString folderName;
00409 if (search) {
00410 numMatches = search->foundCount();
00411 numProcessed = search->searchCount();
00412 folderName = search->currentFolder();
00413 }
00414
00415 if (search && !search->running()) {
00416 procMsg = i18n("%n message searched", "%n messages searched",
00417 numProcessed);
00418 if(!mStopped) {
00419 genMsg = i18n("Done.");
00420 detailMsg = i18n("%n match in %1", "%n matches in %1",
00421 numMatches).arg(procMsg);
00422 } else {
00423 genMsg = i18n("Search canceled.");
00424 detailMsg = i18n("%n match so far in %1", "%n matches so far in %1",
00425 numMatches).arg(procMsg);
00426 }
00427 } else {
00428 procMsg = i18n("%n message", "%n messages", numProcessed);
00429 genMsg = i18n("%n match", "%n matches", numMatches);
00430 detailMsg = i18n("Searching in %1. %2 searched so far")
00431 .arg(folderName).arg(procMsg);
00432 }
00433
00434 mStatusBar->changeItem(genMsg, 0);
00435 mStatusBar->changeItem(detailMsg, 1);
00436 }
00437
00438
00439
00440 void SearchWindow::keyPressEvent(TQKeyEvent *evt)
00441 {
00442 KMSearch const *search = (mFolder) ? mFolder->search() : 0;
00443 bool searching = (search) ? search->running() : false;
00444 if (evt->key() == Key_Escape && searching) {
00445 mFolder->stopSearch();
00446 return;
00447 }
00448
00449 KDialogBase::keyPressEvent(evt);
00450 }
00451
00452
00453
00454 void SearchWindow::slotFolderActivated()
00455 {
00456 mChkbxSpecificFolders->setChecked(true);
00457 }
00458
00459
00460 void SearchWindow::activateFolder(KMFolder *curFolder)
00461 {
00462 mChkbxSpecificFolders->setChecked(true);
00463 mCbxFolders->setFolder(curFolder);
00464 }
00465
00466
00467 void SearchWindow::slotSearch()
00468 {
00469 mLastFocus = focusWidget();
00470 mBtnSearch->setFocus();
00471
00472 mStopped = false;
00473 mFetchingInProgress = 0;
00474
00475 mSearchFolderOpenBtn->setEnabled(true);
00476 if ( mSearchFolderEdt->text().isEmpty() ) {
00477 mSearchFolderEdt->setText( i18n("Last Search") );
00478 }
00479 mBtnSearch->setEnabled(false);
00480 mBtnStop->setEnabled(true);
00481
00482 mLbxMatches->clear();
00483
00484 mSortColumn = mLbxMatches->sortColumn();
00485 mSortOrder = mLbxMatches->sortOrder();
00486 mLbxMatches->setSorting(-1);
00487 mLbxMatches->setShowSortIndicator(false);
00488
00489
00490
00491 if (!mFolder) {
00492 KMFolderMgr *mgr = kmkernel->searchFolderMgr();
00493 TQString baseName = mSearchFolderEdt->text();
00494 TQString fullName = baseName;
00495 int count = 0;
00496 KMFolder *folder;
00497 while ((folder = mgr->find(fullName))) {
00498 if (folder->storage()->inherits("KMFolderSearch"))
00499 break;
00500 fullName = TQString("%1 %2").arg(baseName).arg(++count);
00501 }
00502
00503 if (!folder)
00504 folder = mgr->createFolder(fullName, false, KMFolderTypeSearch,
00505 &mgr->dir());
00506
00507 mFolder = dynamic_cast<KMFolderSearch*>( folder->storage() );
00508 }
00509 mFolder->stopSearch();
00510 disconnect(mFolder, TQT_SIGNAL(msgAdded(int)),
00511 this, TQT_SLOT(slotAddMsg(int)));
00512 disconnect(mFolder, TQT_SIGNAL(msgRemoved(KMFolder*, Q_UINT32)),
00513 this, TQT_SLOT(slotRemoveMsg(KMFolder*, Q_UINT32)));
00514 connect(mFolder, TQT_SIGNAL(msgAdded(int)),
00515 this, TQT_SLOT(slotAddMsg(int)));
00516 connect(mFolder, TQT_SIGNAL(msgRemoved(KMFolder*, Q_UINT32)),
00517 this, TQT_SLOT(slotRemoveMsg(KMFolder*, Q_UINT32)));
00518 mSearchFolderEdt->setEnabled(false);
00519 KMSearch *search = new KMSearch();
00520 connect(search, TQT_SIGNAL(finished(bool)),
00521 this, TQT_SLOT(searchDone()));
00522 if (mChkbxAllFolders->isChecked()) {
00523 search->setRecursive(true);
00524 } else {
00525 search->setRoot(mCbxFolders->folder());
00526 search->setRecursive(mChkSubFolders->isChecked());
00527 }
00528
00529 mPatternEdit->updateSearchPattern();
00530 KMSearchPattern *searchPattern = new KMSearchPattern();
00531 *searchPattern = *mSearchPattern;
00532 searchPattern->purify();
00533 search->setSearchPattern(searchPattern);
00534 mFolder->setSearch(search);
00535 enableGUI();
00536
00537 mTimer->start(200);
00538 }
00539
00540
00541 void SearchWindow::searchDone()
00542 {
00543 mTimer->stop();
00544 updStatus();
00545
00546 TQTimer::singleShot(0, this, TQT_SLOT(enableGUI()));
00547 if(mLastFocus)
00548 mLastFocus->setFocus();
00549 if (mCloseRequested)
00550 close();
00551
00552 mLbxMatches->setSorting(mSortColumn, mSortOrder == Ascending);
00553 mLbxMatches->setShowSortIndicator(true);
00554
00555 mSearchFolderEdt->setEnabled(true);
00556 }
00557
00558 void SearchWindow::slotAddMsg(int idx)
00559 {
00560 if (!mFolder)
00561 return;
00562 bool unget = !mFolder->isMessage(idx);
00563 KMMessage *msg = mFolder->getMsg(idx);
00564 TQString from, fName;
00565 KMFolder *pFolder = msg->parent();
00566 if (!mFolders.contains(pFolder)) {
00567 mFolders.append(pFolder);
00568 pFolder->open("searchwindow");
00569 }
00570 if(pFolder->whoField() == "To")
00571 from = msg->to();
00572 else
00573 from = msg->from();
00574 if (pFolder->isSystemFolder())
00575 fName = i18n(pFolder->name().utf8());
00576 else
00577 fName = pFolder->name();
00578
00579 (void)new KListViewItem(mLbxMatches, mLbxMatches->lastItem(),
00580 msg->subject(), from, msg->dateIsoStr(),
00581 fName,
00582 TQString::number(mFolder->serNum(idx)));
00583 if (unget)
00584 mFolder->unGetMsg(idx);
00585 }
00586
00587 void SearchWindow::slotRemoveMsg(KMFolder *, Q_UINT32 serNum)
00588 {
00589 if (!mFolder)
00590 return;
00591 TQListViewItemIterator it(mLbxMatches);
00592 while (it.current()) {
00593 TQListViewItem *item = *it;
00594 if (serNum == (*it)->text(MSGID_COLUMN).toUInt()) {
00595 delete item;
00596 return;
00597 }
00598 ++it;
00599 }
00600 }
00601
00602
00603 void SearchWindow::slotStop()
00604 {
00605 if (mFolder)
00606 mFolder->stopSearch();
00607 mStopped = true;
00608 mBtnStop->setEnabled(false);
00609 }
00610
00611
00612 void SearchWindow::slotClose()
00613 {
00614 accept();
00615 }
00616
00617
00618
00619 void SearchWindow::closeEvent(TQCloseEvent *e)
00620 {
00621 if (mFolder && mFolder->search() && mFolder->search()->running()) {
00622 mCloseRequested = true;
00623
00624
00625 mFolder->setSearch(new KMSearch());
00626 TQTimer::singleShot(0, this, TQT_SLOT(slotClose()));
00627 } else {
00628 KDialogBase::closeEvent(e);
00629 }
00630 }
00631
00632
00633 void SearchWindow::scheduleRename( const TQString &s)
00634 {
00635 if (!s.isEmpty() ) {
00636 mRenameTimer.start(250, true);
00637 mSearchFolderOpenBtn->setEnabled(false);
00638 } else {
00639 mRenameTimer.stop();
00640 mSearchFolderOpenBtn->setEnabled(!s.isEmpty());
00641 }
00642 }
00643
00644
00645 void SearchWindow::renameSearchFolder()
00646 {
00647 if (mFolder && (mFolder->folder()->name() != mSearchFolderEdt->text())) {
00648 int i = 1;
00649 TQString name = mSearchFolderEdt->text();
00650 while (i < 100) {
00651 if (!kmkernel->searchFolderMgr()->find( name )) {
00652 mFolder->rename( name );
00653 kmkernel->searchFolderMgr()->contentsChanged();
00654 break;
00655 }
00656 name.setNum( i );
00657 name = mSearchFolderEdt->text() + " " + name;
00658 ++i;
00659 }
00660 }
00661 if ( mFolder )
00662 mSearchFolderOpenBtn->setEnabled(true);
00663 }
00664
00665 void SearchWindow::openSearchFolder()
00666 {
00667 Q_ASSERT( mFolder );
00668 renameSearchFolder();
00669 mKMMainWidget->slotSelectFolder( mFolder->folder() );
00670 slotClose();
00671 }
00672
00673
00674 void SearchWindow::folderInvalidated(KMFolder *folder)
00675 {
00676 if (folder->storage() == mFolder) {
00677 mLbxMatches->clear();
00678 if (mFolder->search())
00679 connect(mFolder->search(), TQT_SIGNAL(finished(bool)),
00680 this, TQT_SLOT(searchDone()));
00681 mTimer->start(200);
00682 enableGUI();
00683 }
00684 }
00685
00686
00687 KMMessage *SearchWindow::indexToMessage( TQListViewItem *item )
00688 {
00689 if( !item ) {
00690 return 0;
00691 }
00692
00693 KMFolder *folder;
00694 int msgIndex;
00695 KMMsgDict::instance()->getLocation( item->text( MSGID_COLUMN ).toUInt(),
00696 &folder, &msgIndex );
00697
00698 if ( !folder || msgIndex < 0 ) {
00699 return 0;
00700 }
00701
00702 mKMMainWidget->slotSelectFolder( folder );
00703 return folder->getMsg( msgIndex );
00704 }
00705
00706
00707 bool SearchWindow::slotShowMsg( TQListViewItem *item )
00708 {
00709 KMMessage *message = indexToMessage( item );
00710 if ( message ) {
00711 mKMMainWidget->slotSelectMessage( message );
00712 return true;
00713 }
00714 return false;
00715 }
00716
00717
00718 void SearchWindow::slotViewSelectedMsg()
00719 {
00720 slotViewMsg( mLbxMatches->currentItem() );
00721 }
00722
00723
00724 bool SearchWindow::slotViewMsg( TQListViewItem *item )
00725 {
00726 KMMessage *message = indexToMessage( item );
00727 if ( message ) {
00728 mKMMainWidget->slotMsgActivated( message );
00729 return true;
00730 }
00731 return false;
00732 }
00733
00734
00735 void SearchWindow::slotCurrentChanged(TQListViewItem *item)
00736 {
00737 mSearchResultOpenBtn->setEnabled(item!=0);
00738 }
00739
00740
00741 void SearchWindow::enableGUI()
00742 {
00743 KMSearch const *search = (mFolder) ? (mFolder->search()) : 0;
00744 bool searching = (search) ? (search->running()) : false;
00745 actionButton(KDialogBase::Close)->setEnabled(!searching);
00746 mCbxFolders->setEnabled(!searching && !mChkbxAllFolders->isChecked());
00747 mChkSubFolders->setEnabled(!searching && !mChkbxAllFolders->isChecked());
00748 mChkbxAllFolders->setEnabled(!searching);
00749 mChkbxSpecificFolders->setEnabled(!searching);
00750 mPatternEdit->setEnabled(!searching);
00751 mBtnSearch->setEnabled(!searching);
00752 mBtnStop->setEnabled(searching);
00753 }
00754
00755
00756
00757 KMMessageList SearchWindow::selectedMessages()
00758 {
00759 KMMessageList msgList;
00760 KMFolder* folder = 0;
00761 int msgIndex = -1;
00762 for (TQListViewItemIterator it(mLbxMatches); it.current(); it++)
00763 if (it.current()->isSelected()) {
00764 KMMsgDict::instance()->getLocation((*it)->text(MSGID_COLUMN).toUInt(),
00765 &folder, &msgIndex);
00766 if (folder && msgIndex >= 0)
00767 msgList.append(folder->getMsgBase(msgIndex));
00768 }
00769 return msgList;
00770 }
00771
00772
00773 KMMessage* SearchWindow::message()
00774 {
00775 TQListViewItem *item = mLbxMatches->currentItem();
00776 KMFolder* folder = 0;
00777 int msgIndex = -1;
00778 if (!item)
00779 return 0;
00780 KMMsgDict::instance()->getLocation(item->text(MSGID_COLUMN).toUInt(),
00781 &folder, &msgIndex);
00782 if (!folder || msgIndex < 0)
00783 return 0;
00784
00785 return folder->getMsg(msgIndex);
00786 }
00787
00788
00789 void SearchWindow::moveSelectedToFolder( int menuId )
00790 {
00791 KMFolder *dest = mMenuToFolder[menuId];
00792 if (!dest)
00793 return;
00794
00795 KMMessageList msgList = selectedMessages();
00796 KMCommand *command = new KMMoveCommand( dest, msgList );
00797 command->start();
00798 }
00799
00800
00801 void SearchWindow::copySelectedToFolder( int menuId )
00802 {
00803 KMFolder *dest = mMenuToFolder[menuId];
00804 if (!dest)
00805 return;
00806
00807 KMMessageList msgList = selectedMessages();
00808 KMCommand *command = new KMCopyCommand( dest, msgList );
00809 command->start();
00810 }
00811
00812
00813 void SearchWindow::updateContextMenuActions()
00814 {
00815 int count = selectedMessages().count();
00816 bool single_actions = count == 1;
00817 mReplyAction->setEnabled( single_actions );
00818 mReplyAllAction->setEnabled( single_actions );
00819 mReplyListAction->setEnabled( single_actions );
00820 mPrintAction->setEnabled( single_actions );
00821 mForwardDigestAction->setEnabled( !single_actions );
00822 mRedirectAction->setEnabled( single_actions );
00823 mCopyAction->setEnabled( count > 0 );
00824 mCutAction->setEnabled( count > 0 );
00825 }
00826
00827
00828 void SearchWindow::slotContextMenuRequested( TQListViewItem *lvi, const TQPoint &, int )
00829 {
00830 if (!lvi)
00831 return;
00832 mLbxMatches->setSelected( lvi, true );
00833 mLbxMatches->setCurrentItem( lvi );
00834
00835 if (!message())
00836 return;
00837 TQPopupMenu *menu = new TQPopupMenu(this);
00838 updateContextMenuActions();
00839
00840 mMenuToFolder.clear();
00841 TQPopupMenu *msgMoveMenu = new TQPopupMenu(menu);
00842 mKMMainWidget->folderTree()->folderToPopupMenu( KMFolderTree::MoveMessage,
00843 this, &mMenuToFolder, msgMoveMenu );
00844 TQPopupMenu *msgCopyMenu = new TQPopupMenu(menu);
00845 mKMMainWidget->folderTree()->folderToPopupMenu( KMFolderTree::CopyMessage,
00846 this, &mMenuToFolder, msgCopyMenu );
00847
00848
00849 mReplyAction->plug(menu);
00850 mReplyAllAction->plug(menu);
00851 mReplyListAction->plug(menu);
00852 mForwardActionMenu->plug(menu);
00853 menu->insertSeparator();
00854 mCopyAction->plug(menu);
00855 mCutAction->plug(menu);
00856 menu->insertItem(i18n("&Copy To"), msgCopyMenu);
00857 menu->insertItem(i18n("&Move To"), msgMoveMenu);
00858 menu->insertSeparator();
00859 mSaveAsAction->plug(menu);
00860 mSaveAtchAction->plug(menu);
00861 mPrintAction->plug(menu);
00862 menu->insertSeparator();
00863 mClearAction->plug(menu);
00864 menu->exec (TQCursor::pos(), 0);
00865 delete menu;
00866 }
00867
00868
00869 void SearchWindow::slotClearSelection()
00870 {
00871 mLbxMatches->clearSelection();
00872 }
00873
00874
00875 void SearchWindow::slotReplyToMsg()
00876 {
00877 KMCommand *command = new KMReplyToCommand(this, message());
00878 command->start();
00879 }
00880
00881
00882 void SearchWindow::slotReplyAllToMsg()
00883 {
00884 KMCommand *command = new KMReplyToAllCommand(this, message());
00885 command->start();
00886 }
00887
00888
00889 void SearchWindow::slotReplyListToMsg()
00890 {
00891 KMCommand *command = new KMReplyListCommand(this, message());
00892 command->start();
00893 }
00894
00895
00896 void SearchWindow::slotForwardInlineMsg()
00897 {
00898 KMCommand *command = new KMForwardInlineCommand(this, selectedMessages());
00899 command->start();
00900 }
00901
00902
00903 void SearchWindow::slotForwardAttachedMsg()
00904 {
00905 KMCommand *command = new KMForwardAttachedCommand(this, selectedMessages());
00906 command->start();
00907 }
00908
00909
00910 void SearchWindow::slotForwardDigestMsg()
00911 {
00912 KMCommand *command = new KMForwardDigestCommand(this, selectedMessages());
00913 command->start();
00914 }
00915
00916
00917 void SearchWindow::slotRedirectMsg()
00918 {
00919 KMCommand *command = new KMRedirectCommand(this, message());
00920 command->start();
00921 }
00922
00923
00924 void SearchWindow::slotSaveMsg()
00925 {
00926 KMSaveMsgCommand *saveCommand = new KMSaveMsgCommand(this,
00927 selectedMessages());
00928 if (saveCommand->url().isEmpty())
00929 delete saveCommand;
00930 else
00931 saveCommand->start();
00932 }
00933
00934 void SearchWindow::slotSaveAttachments()
00935 {
00936 KMSaveAttachmentsCommand *saveCommand = new KMSaveAttachmentsCommand(this,
00937 selectedMessages());
00938 saveCommand->start();
00939 }
00940
00941
00942
00943 void SearchWindow::slotPrintMsg()
00944 {
00945 KMCommand *command = new KMPrintCommand(this, message());
00946 command->start();
00947 }
00948
00949 void SearchWindow::slotCopyMsgs()
00950 {
00951 TQValueList<Q_UINT32> list = MessageCopyHelper::serNumListFromMsgList( selectedMessages() );
00952 mKMMainWidget->headers()->setCopiedMessages( list, false );
00953 }
00954
00955 void SearchWindow::slotCutMsgs()
00956 {
00957 TQValueList<Q_UINT32> list = MessageCopyHelper::serNumListFromMsgList( selectedMessages() );
00958 mKMMainWidget->headers()->setCopiedMessages( list, true );
00959 }
00960
00961
00962 void SearchWindow::setSearchPattern( const KMSearchPattern& pattern )
00963 {
00964 *mSearchPattern = pattern;
00965 mPatternEdit->setSearchPattern( mSearchPattern );
00966 }
00967
00968 }
00969 #include "searchwindow.moc"