/* * kmail: KDE mail client * Copyright (c) 1996-1998 Stefan Taferner * Copyright (c) 2001 Aaron J. Seigo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include #include "kmcommands.h" #include "searchwindow.h" #include "kmmainwidget.h" #include "kmmsgdict.h" #include "kmmsgpart.h" #include "kmfolderimap.h" #include "kmfoldermgr.h" #include "kmfoldersearch.h" #include "kmfoldertree.h" #include "kmheaders.h" #include "kmsearchpatternedit.h" #include "kmsearchpattern.h" #include "folderrequester.h" #include "messagecopyhelper.h" #include "textsource.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //for mPatternEdit->queryList( 0, "mRuleField" )->first(); #include #include #include using namespace KPIM; #include #include #include #include namespace KMail { const int SearchWindow::MSGID_COLUMN = 4; // TDEListView sub-class for dnd support class MatchListView : public TDEListView { public: MatchListView( TQWidget *parent, SearchWindow* sw, const char* name = 0 ) : TDEListView( parent, name ), mSearchWindow( sw ) {} protected: virtual TQDragObject* dragObject() { KMMessageList list = mSearchWindow->selectedMessages(); MailList mailList; for ( KMMsgBase* msg = list.first(); msg; msg = list.next() ) { if ( !msg ) continue; MailSummary mailSummary( msg->getMsgSerNum(), msg->msgIdMD5(), msg->subject(), msg->fromStrip(), msg->toStrip(), msg->date() ); mailList.append( mailSummary ); } MailListDrag *d = new MailListDrag( mailList, viewport(), new KMTextSource ); TQPixmap pixmap; if( mailList.count() == 1 ) pixmap = TQPixmap( DesktopIcon("message", TDEIcon::SizeSmall) ); else pixmap = TQPixmap( DesktopIcon("application-vnd.tde.tdemultiple", TDEIcon::SizeSmall) ); d->setPixmap( pixmap ); return d; } private: SearchWindow* mSearchWindow; }; //----------------------------------------------------------------------------- SearchWindow::SearchWindow(KMMainWidget* w, const char* name, KMFolder *curFolder, bool modal): KDialogBase(0, name, modal, i18n("Find Messages"), User1 | User2 | Close, User1, false, KGuiItem( i18n("&Search"), "edit-find" ), KStdGuiItem::stop()), mStopped(false), mCloseRequested(false), mSortColumn(0), mSortOrder(Ascending), mFolder(0), mTimer(new TQTimer(this, "mTimer")), mLastFocus(0), mKMMainWidget(w) { #if !KDE_IS_VERSION( 3, 2, 91 ) // HACK - KWin keeps all dialogs on top of their mainwindows, but that's probably // wrong (#76026), and should be done only for modals. CVS HEAD should get // proper fix in KWin (l.lunak@kde.org) XDeleteProperty( tqt_xdisplay(), winId(), XA_WM_TRANSIENT_FOR ); #endif KWin::setIcons(winId(), kapp->icon(), kapp->miniIcon()); TDEConfig* config = KMKernel::config(); config->setGroup("SearchDialog"); TQWidget* searchWidget = new TQWidget(this); TQVBoxLayout *vbl = new TQVBoxLayout( searchWidget, 0, spacingHint(), "kmfs_vbl" ); TQButtonGroup * radioGroup = new TQButtonGroup( searchWidget ); radioGroup->hide(); mChkbxAllFolders = new TQRadioButton(i18n("Search in &all local folders"), searchWidget); vbl->addWidget( mChkbxAllFolders ); radioGroup->insert( mChkbxAllFolders ); TQHBoxLayout *hbl = new TQHBoxLayout( vbl, spacingHint(), "kmfs_hbl" ); mChkbxSpecificFolders = new TQRadioButton(i18n("Search &only in:"), searchWidget); hbl->addWidget(mChkbxSpecificFolders); mChkbxSpecificFolders->setChecked(true); radioGroup->insert( mChkbxSpecificFolders ); mCbxFolders = new FolderRequester( searchWidget, kmkernel->getKMMainWidget()->folderTree() ); mCbxFolders->setMustBeReadWrite( false ); mCbxFolders->setFolder(curFolder); hbl->addWidget(mCbxFolders); mChkSubFolders = new TQCheckBox(i18n("I&nclude sub-folders"), searchWidget); mChkSubFolders->setChecked(true); hbl->addWidget(mChkSubFolders); TQWidget *spacer = new TQWidget( searchWidget, "spacer" ); spacer->setMinimumHeight( 2 ); vbl->addWidget( spacer ); mPatternEdit = new KMSearchPatternEdit( "", searchWidget , "spe", false, true ); mPatternEdit->setFrameStyle( TQFrame::NoFrame | TQFrame::Plain ); mPatternEdit->setInsideMargin( 0 ); mSearchPattern = new KMSearchPattern(); KMFolderSearch *searchFolder = 0; if (curFolder) searchFolder = dynamic_cast(curFolder->storage()); if (searchFolder) { TDEConfig config(curFolder->location()); KMFolder *root = searchFolder->search()->root(); config.setGroup("Search Folder"); mSearchPattern->readConfig(&config); if (root) { mChkbxSpecificFolders->setChecked(true); mCbxFolders->setFolder(root); mChkSubFolders->setChecked(searchFolder->search()->recursive()); } else { mChkbxAllFolders->setChecked(true); } } mPatternEdit->setSearchPattern( mSearchPattern ); TQObjectList *list = mPatternEdit->queryList( 0, "mRuleField" ); TQObject *object = 0; if ( list ) object = list->first(); delete list; if (!searchFolder && object && ::tqqt_cast(object)) static_cast(TQT_TQWIDGET(object))->setCurrentText("Subject"); vbl->addWidget( mPatternEdit ); // enable/disable widgets depending on radio buttons: connect( mChkbxSpecificFolders, TQT_SIGNAL(toggled(bool)), mCbxFolders, TQT_SLOT(setEnabled(bool)) ); connect( mChkbxSpecificFolders, TQT_SIGNAL(toggled(bool)), mChkSubFolders, TQT_SLOT(setEnabled(bool)) ); connect( mChkbxAllFolders, TQT_SIGNAL(toggled(bool)), TQT_TQOBJECT(this), TQT_SLOT(setEnabledSearchButton(bool)) ); mLbxMatches = new MatchListView(searchWidget, this, "Find Messages"); /* Default is to sort by date. TODO: Unfortunately this sorts *while* inserting, which looks rather strange - the user cannot read the results so far as they are constantly re-sorted --dnaber Sorting is now disabled when a search is started and reenabled when it stops. Items are appended to the list. This not only solves the above problem, but speeds searches with many hits up considerably. - till TODO: subclass TDEListViewItem and do proper (and performant) comapare functions */ mLbxMatches->setSorting(2, false); mLbxMatches->setShowSortIndicator(true); mLbxMatches->setAllColumnsShowFocus(true); mLbxMatches->setSelectionModeExt(TDEListView::Extended); mLbxMatches->addColumn(i18n("Subject"), config->readNumEntry("SubjectWidth", 150)); mLbxMatches->addColumn(i18n("Sender/Receiver"), config->readNumEntry("SenderWidth", 120)); mLbxMatches->addColumn(i18n("Date"), config->readNumEntry("DateWidth", 120)); mLbxMatches->addColumn(i18n("Folder"), config->readNumEntry("FolderWidth", 100)); mLbxMatches->addColumn(""); // should be hidden mLbxMatches->setColumnWidthMode( MSGID_COLUMN, TQListView::Manual ); mLbxMatches->setColumnWidth(MSGID_COLUMN, 0); mLbxMatches->header()->setResizeEnabled(false, MSGID_COLUMN); mLbxMatches->setDragEnabled( true ); connect( mLbxMatches, TQT_SIGNAL(clicked(TQListViewItem *)), TQT_TQOBJECT(this), TQT_SLOT(slotShowMsg(TQListViewItem *)) ); connect( mLbxMatches, TQT_SIGNAL(doubleClicked(TQListViewItem *)), TQT_TQOBJECT(this), TQT_SLOT(slotViewMsg(TQListViewItem *)) ); connect( mLbxMatches, TQT_SIGNAL(currentChanged(TQListViewItem *)), TQT_TQOBJECT(this), TQT_SLOT(slotCurrentChanged(TQListViewItem *)) ); connect( mLbxMatches, TQT_SIGNAL(contextMenuRequested(TQListViewItem *,const TQPoint &,int)), TQT_TQOBJECT(this), TQT_SLOT(slotContextMenuRequested(TQListViewItem *,const TQPoint &,int)) ); vbl->addWidget( mLbxMatches ); TQHBoxLayout *hbl2 = new TQHBoxLayout( vbl, spacingHint(), "kmfs_hbl2" ); mSearchFolderLbl = new TQLabel(i18n("Search folder &name:"), searchWidget); hbl2->addWidget(mSearchFolderLbl); mSearchFolderEdt = new KLineEdit(searchWidget); if (searchFolder) mSearchFolderEdt->setText(searchFolder->folder()->name()); else mSearchFolderEdt->setText(i18n("Last Search")); mSearchFolderLbl->setBuddy(mSearchFolderEdt); hbl2->addWidget(mSearchFolderEdt); mSearchFolderOpenBtn = new TQPushButton(i18n("Op&en Search Folder"), searchWidget); mSearchFolderOpenBtn->setEnabled(false); hbl2->addWidget(mSearchFolderOpenBtn); connect( mSearchFolderEdt, TQT_SIGNAL( textChanged( const TQString &)), TQT_TQOBJECT(this), TQT_SLOT( scheduleRename( const TQString & ))); connect( &mRenameTimer, TQT_SIGNAL( timeout() ), TQT_TQOBJECT(this), TQT_SLOT( renameSearchFolder() )); connect( mSearchFolderOpenBtn, TQT_SIGNAL( clicked() ), TQT_TQOBJECT(this), TQT_SLOT( openSearchFolder() )); mSearchResultOpenBtn = new TQPushButton(i18n("Open &Message"), searchWidget); mSearchResultOpenBtn->setEnabled(false); hbl2->addWidget(mSearchResultOpenBtn); connect( mSearchResultOpenBtn, TQT_SIGNAL( clicked() ), TQT_TQOBJECT(this), TQT_SLOT( slotViewSelectedMsg() )); mStatusBar = new KStatusBar(searchWidget); mStatusBar->insertFixedItem(i18n("AMiddleLengthText..."), 0, true); mStatusBar->changeItem(i18n("Ready."), 0); mStatusBar->setItemAlignment(0, AlignLeft | AlignVCenter); mStatusBar->insertItem(TQString(), 1, 1, true); mStatusBar->setItemAlignment(1, AlignLeft | AlignVCenter); vbl->addWidget(mStatusBar); int mainWidth = config->readNumEntry("SearchWidgetWidth", 0); int mainHeight = config->readNumEntry("SearchWidgetHeight", 0); if (mainWidth || mainHeight) resize(mainWidth, mainHeight); setMainWidget(searchWidget); setButtonBoxOrientation(Qt::Vertical); mBtnSearch = actionButton(KDialogBase::User1); mBtnStop = actionButton(KDialogBase::User2); mBtnStop->setEnabled(false); connect(this, TQT_SIGNAL(user1Clicked()), TQT_SLOT(slotSearch())); connect(this, TQT_SIGNAL(user2Clicked()), TQT_SLOT(slotStop())); connect(this, TQT_SIGNAL(finished()), TQT_TQOBJECT(this), TQT_SLOT(deleteLater())); // give focus to the value field of the first search rule object = mPatternEdit->child( "regExpLineEdit" ); if ( object && object->isWidgetType() ) { TQT_TQWIDGET(object)->setFocus(); //kdDebug(5006) << "SearchWindow: focus has been given to widget " // << object->name() << endl; } else kdDebug(5006) << "SearchWindow: regExpLineEdit not found" << endl; //set up actions TDEActionCollection *ac = actionCollection(); ac->setWidget( this ); mReplyAction = new TDEAction( i18n("&Reply..."), "mail-reply-sender", 0, TQT_TQOBJECT(this), TQT_SLOT(slotReplyToMsg()), ac, "search_reply" ); mReplyAllAction = new TDEAction( i18n("Reply to &All..."), "mail-reply-all", 0, TQT_TQOBJECT(this), TQT_SLOT(slotReplyAllToMsg()), ac, "search_reply_all" ); mReplyListAction = new TDEAction( i18n("Reply to Mailing-&List..."), "mail_replylist", 0, TQT_TQOBJECT(this), TQT_SLOT(slotReplyListToMsg()), ac, "search_reply_list" ); mForwardActionMenu = new TDEActionMenu( i18n("Message->","&Forward"), "mail-forward", ac, "search_message_forward" ); connect( mForwardActionMenu, TQT_SIGNAL(activated()), this, TQT_SLOT(slotForwardInlineMsg()) ); mForwardAttachedAction = new TDEAction( i18n("Message->Forward->","As &Attachment..."), "mail-forward", 0, TQT_TQOBJECT(this), TQT_SLOT(slotForwardAttachedMsg()), ac, "search_message_forward_as_attachment" ); mForwardInlineAction = new TDEAction( i18n("&Inline..."), "mail-forward", 0, TQT_TQOBJECT(this), TQT_SLOT(slotForwardInlineMsg()), ac, "search_message_forward_inline" ); if ( GlobalSettings::self()->forwardingInlineByDefault() ) { mForwardActionMenu->insert( mForwardInlineAction ); mForwardActionMenu->insert( mForwardAttachedAction ); } else { mForwardActionMenu->insert( mForwardAttachedAction ); mForwardActionMenu->insert( mForwardInlineAction ); } mForwardDigestAction = new TDEAction( i18n("Message->Forward->","As Di&gest..."), "mail-forward", 0, TQT_TQOBJECT(this), TQT_SLOT(slotForwardDigestMsg()), ac, "search_message_forward_as_digest" ); mForwardActionMenu->insert( mForwardDigestAction ); mRedirectAction = new TDEAction( i18n("Message->Forward->","&Redirect..."), "mail-forward", 0, TQT_TQOBJECT(this), TQT_SLOT(slotRedirectMsg()), ac, "search_message_forward_redirect" ); mForwardActionMenu->insert( mRedirectAction ); mSaveAsAction = KStdAction::saveAs( TQT_TQOBJECT(this), TQT_SLOT(slotSaveMsg()), ac, "search_file_save_as" ); mSaveAtchAction = new TDEAction( i18n("Save Attachments..."), "attach", 0, TQT_TQOBJECT(this), TQT_SLOT(slotSaveAttachments()), ac, "search_save_attachments" ); mPrintAction = KStdAction::print( TQT_TQOBJECT(this), TQT_SLOT(slotPrintMsg()), ac, "search_print" ); mClearAction = new TDEAction( i18n("Clear Selection"), 0, 0, TQT_TQOBJECT(this), TQT_SLOT(slotClearSelection()), ac, "search_clear_selection" ); mCopyAction = KStdAction::copy( TQT_TQOBJECT(this), TQT_SLOT(slotCopyMsgs()), ac, "search_copy_messages" ); mCutAction = KStdAction::cut( TQT_TQOBJECT(this), TQT_SLOT(slotCutMsgs()), ac, "search_cut_messages" ); connect(mTimer, TQT_SIGNAL(timeout()), TQT_TQOBJECT(this), TQT_SLOT(updStatus())); connect(kmkernel->searchFolderMgr(), TQT_SIGNAL(folderInvalidated(KMFolder*)), TQT_TQOBJECT(this), TQT_SLOT(folderInvalidated(KMFolder*))); connect(mCbxFolders, TQT_SIGNAL(folderChanged(KMFolder*)), TQT_TQOBJECT(this), TQT_SLOT(slotFolderActivated())); } //----------------------------------------------------------------------------- SearchWindow::~SearchWindow() { TQValueListIterator > fit; for ( fit = mFolders.begin(); fit != mFolders.end(); ++fit ) { if (!(*fit)) continue; (*fit)->close("searchwindow"); } TDEConfig* config = KMKernel::config(); config->setGroup("SearchDialog"); config->writeEntry("SubjectWidth", mLbxMatches->columnWidth(0)); config->writeEntry("SenderWidth", mLbxMatches->columnWidth(1)); config->writeEntry("DateWidth", mLbxMatches->columnWidth(2)); config->writeEntry("FolderWidth", mLbxMatches->columnWidth(3)); config->writeEntry("SearchWidgetWidth", width()); config->writeEntry("SearchWidgetHeight", height()); config->sync(); } void SearchWindow::setEnabledSearchButton(bool) { //Make sure that button is enable //Before when we selected a folder == "Local Folder" as that it was not a folder //search button was disable, and when we select "Search in all local folder" //Search button was never enabled :( mBtnSearch->setEnabled( true ); } //----------------------------------------------------------------------------- void SearchWindow::updStatus(void) { TQString genMsg, detailMsg, procMsg; int numMatches = 0, numProcessed = 0; KMSearch const *search = (mFolder) ? (mFolder->search()) : 0; TQString folderName; if (search) { numMatches = search->foundCount(); numProcessed = search->searchCount(); folderName = search->currentFolder(); } if (search && !search->running()) { procMsg = i18n("%n message searched", "%n messages searched", numProcessed); if(!mStopped) { genMsg = i18n("Done."); detailMsg = i18n("%n match in %1", "%n matches in %1", numMatches).arg(procMsg); } else { genMsg = i18n("Search canceled."); detailMsg = i18n("%n match so far in %1", "%n matches so far in %1", numMatches).arg(procMsg); } } else { procMsg = i18n("%n message", "%n messages", numProcessed); genMsg = i18n("%n match", "%n matches", numMatches); detailMsg = i18n("Searching in %1. %2 searched so far") .arg(folderName).arg(procMsg); } mStatusBar->changeItem(genMsg, 0); mStatusBar->changeItem(detailMsg, 1); } //----------------------------------------------------------------------------- void SearchWindow::keyPressEvent(TQKeyEvent *evt) { KMSearch const *search = (mFolder) ? mFolder->search() : 0; bool searching = (search) ? search->running() : false; if (evt->key() == Key_Escape && searching) { mFolder->stopSearch(); return; } KDialogBase::keyPressEvent(evt); } //----------------------------------------------------------------------------- void SearchWindow::slotFolderActivated() { mChkbxSpecificFolders->setChecked(true); } //----------------------------------------------------------------------------- void SearchWindow::activateFolder(KMFolder *curFolder) { mChkbxSpecificFolders->setChecked(true); mCbxFolders->setFolder(curFolder); } //----------------------------------------------------------------------------- void SearchWindow::slotSearch() { mLastFocus = focusWidget(); mBtnSearch->setFocus(); // set focus so we don't miss key event mStopped = false; mFetchingInProgress = 0; mSearchFolderOpenBtn->setEnabled(true); if ( mSearchFolderEdt->text().isEmpty() ) { mSearchFolderEdt->setText( i18n("Last Search") ); } mBtnSearch->setEnabled(false); mBtnStop->setEnabled(true); mLbxMatches->clear(); mSortColumn = mLbxMatches->sortColumn(); mSortOrder = mLbxMatches->sortOrder(); mLbxMatches->setSorting(-1); mLbxMatches->setShowSortIndicator(false); // If we haven't openend an existing search folder, find or // create one. if (!mFolder) { KMFolderMgr *mgr = kmkernel->searchFolderMgr(); TQString baseName = mSearchFolderEdt->text(); TQString fullName = baseName; int count = 0; KMFolder *folder; while ((folder = mgr->find(fullName))) { if (folder->storage()->inherits("KMFolderSearch")) break; fullName = TQString("%1 %2").arg(baseName).arg(++count); } if (!folder) folder = mgr->createFolder(fullName, false, KMFolderTypeSearch, &mgr->dir()); mFolder = dynamic_cast( folder->storage() ); } mFolder->stopSearch(); disconnect(mFolder, TQT_SIGNAL(msgAdded(int)), TQT_TQOBJECT(this), TQT_SLOT(slotAddMsg(int))); disconnect(mFolder, TQT_SIGNAL(msgRemoved(KMFolder*, TQ_UINT32)), TQT_TQOBJECT(this), TQT_SLOT(slotRemoveMsg(KMFolder*, TQ_UINT32))); connect(mFolder, TQT_SIGNAL(msgAdded(int)), TQT_TQOBJECT(this), TQT_SLOT(slotAddMsg(int))); connect(mFolder, TQT_SIGNAL(msgRemoved(KMFolder*, TQ_UINT32)), TQT_TQOBJECT(this), TQT_SLOT(slotRemoveMsg(KMFolder*, TQ_UINT32))); mSearchFolderEdt->setEnabled(false); KMSearch *search = new KMSearch(); connect(search, TQT_SIGNAL(finished(bool)), TQT_TQOBJECT(this), TQT_SLOT(searchDone())); if (mChkbxAllFolders->isChecked()) { search->setRecursive(true); } else { search->setRoot(mCbxFolders->folder()); search->setRecursive(mChkSubFolders->isChecked()); } mPatternEdit->updateSearchPattern(); KMSearchPattern *searchPattern = new KMSearchPattern(); *searchPattern = *mSearchPattern; //deep copy searchPattern->purify(); search->setSearchPattern(searchPattern); mFolder->setSearch(search); enableGUI(); mTimer->start(200); } //----------------------------------------------------------------------------- void SearchWindow::searchDone() { mTimer->stop(); updStatus(); TQTimer::singleShot(0, TQT_TQOBJECT(this), TQT_SLOT(enableGUI())); if(mLastFocus) mLastFocus->setFocus(); if (mCloseRequested) close(); mLbxMatches->setSorting(mSortColumn, mSortOrder == Ascending); mLbxMatches->setShowSortIndicator(true); mSearchFolderEdt->setEnabled(true); } void SearchWindow::slotAddMsg(int idx) { if (!mFolder) return; bool unget = !mFolder->isMessage(idx); KMMessage *msg = mFolder->getMsg(idx); TQString from, fName; KMFolder *pFolder = msg->parent(); if (!mFolders.contains(pFolder)) { mFolders.append(pFolder); pFolder->open("searchwindow"); } if(pFolder->whoField() == "To") from = msg->to(); else from = msg->from(); if (pFolder->isSystemFolder()) fName = i18n(pFolder->name().utf8()); else fName = pFolder->name(); (void)new TDEListViewItem(mLbxMatches, mLbxMatches->lastItem(), msg->subject(), from, msg->dateIsoStr(), fName, TQString::number(mFolder->serNum(idx))); if (unget) mFolder->unGetMsg(idx); } void SearchWindow::slotRemoveMsg(KMFolder *, TQ_UINT32 serNum) { if (!mFolder) return; TQListViewItemIterator it(mLbxMatches); while (it.current()) { TQListViewItem *item = *it; if (serNum == (*it)->text(MSGID_COLUMN).toUInt()) { delete item; return; } ++it; } } //----------------------------------------------------------------------------- void SearchWindow::slotStop() { if (mFolder) mFolder->stopSearch(); mStopped = true; mBtnStop->setEnabled(false); } //----------------------------------------------------------------------------- void SearchWindow::slotClose() { accept(); } //----------------------------------------------------------------------------- void SearchWindow::closeEvent(TQCloseEvent *e) { if (mFolder && mFolder->search() && mFolder->search()->running()) { mCloseRequested = true; //Cancel search in progress by setting the search folder search to //the null search mFolder->setSearch(new KMSearch()); TQTimer::singleShot(0, TQT_TQOBJECT(this), TQT_SLOT(slotClose())); } else { KDialogBase::closeEvent(e); } } //----------------------------------------------------------------------------- void SearchWindow::scheduleRename( const TQString &s) { if (!s.isEmpty() ) { mRenameTimer.start(250, true); mSearchFolderOpenBtn->setEnabled(false); } else { mRenameTimer.stop(); mSearchFolderOpenBtn->setEnabled(!s.isEmpty()); } } //----------------------------------------------------------------------------- void SearchWindow::renameSearchFolder() { if (mFolder && (mFolder->folder()->name() != mSearchFolderEdt->text())) { int i = 1; TQString name = mSearchFolderEdt->text(); while (i < 100) { if (!kmkernel->searchFolderMgr()->find( name )) { mFolder->rename( name ); kmkernel->searchFolderMgr()->contentsChanged(); break; } name.setNum( i ); name = mSearchFolderEdt->text() + " " + name; ++i; } } if ( mFolder ) mSearchFolderOpenBtn->setEnabled(true); } void SearchWindow::openSearchFolder() { Q_ASSERT( mFolder ); renameSearchFolder(); mKMMainWidget->slotSelectFolder( mFolder->folder() ); slotClose(); } //----------------------------------------------------------------------------- void SearchWindow::folderInvalidated(KMFolder *folder) { if (folder->storage() == mFolder) { mLbxMatches->clear(); if (mFolder->search()) connect(mFolder->search(), TQT_SIGNAL(finished(bool)), TQT_TQOBJECT(this), TQT_SLOT(searchDone())); mTimer->start(200); enableGUI(); } } //----------------------------------------------------------------------------- KMMessage *SearchWindow::indexToMessage( TQListViewItem *item ) { if( !item ) { return 0; } KMFolder *folder; int msgIndex; KMMsgDict::instance()->getLocation( item->text( MSGID_COLUMN ).toUInt(), &folder, &msgIndex ); if ( !folder || msgIndex < 0 ) { return 0; } mKMMainWidget->slotSelectFolder( folder ); return folder->getMsg( msgIndex ); } //----------------------------------------------------------------------------- bool SearchWindow::slotShowMsg( TQListViewItem *item ) { KMMessage *message = indexToMessage( item ); if ( message ) { mKMMainWidget->slotSelectMessage( message ); return true; } return false; } //----------------------------------------------------------------------------- void SearchWindow::slotViewSelectedMsg() { slotViewMsg( mLbxMatches->currentItem() ); } //----------------------------------------------------------------------------- bool SearchWindow::slotViewMsg( TQListViewItem *item ) { KMMessage *message = indexToMessage( item ); if ( message ) { mKMMainWidget->slotMsgActivated( message ); return true; } return false; } //----------------------------------------------------------------------------- void SearchWindow::slotCurrentChanged(TQListViewItem *item) { mSearchResultOpenBtn->setEnabled(item!=0); } //----------------------------------------------------------------------------- void SearchWindow::enableGUI() { KMSearch const *search = (mFolder) ? (mFolder->search()) : 0; bool searching = (search) ? (search->running()) : false; actionButton(KDialogBase::Close)->setEnabled(!searching); mCbxFolders->setEnabled(!searching && !mChkbxAllFolders->isChecked()); mChkSubFolders->setEnabled(!searching && !mChkbxAllFolders->isChecked()); mChkbxAllFolders->setEnabled(!searching); mChkbxSpecificFolders->setEnabled(!searching); mPatternEdit->setEnabled(!searching); mBtnSearch->setEnabled(!searching); mBtnStop->setEnabled(searching); } //----------------------------------------------------------------------------- KMMessageList SearchWindow::selectedMessages() { KMMessageList msgList; KMFolder* folder = 0; int msgIndex = -1; for (TQListViewItemIterator it(mLbxMatches); it.current(); it++) if (it.current()->isSelected()) { KMMsgDict::instance()->getLocation((*it)->text(MSGID_COLUMN).toUInt(), &folder, &msgIndex); if (folder && msgIndex >= 0) msgList.append(folder->getMsgBase(msgIndex)); } return msgList; } //----------------------------------------------------------------------------- KMMessage* SearchWindow::message() { TQListViewItem *item = mLbxMatches->currentItem(); KMFolder* folder = 0; int msgIndex = -1; if (!item) return 0; KMMsgDict::instance()->getLocation(item->text(MSGID_COLUMN).toUInt(), &folder, &msgIndex); if (!folder || msgIndex < 0) return 0; return folder->getMsg(msgIndex); } //----------------------------------------------------------------------------- void SearchWindow::moveSelectedToFolder( int menuId ) { KMFolder *dest = mMenuToFolder[menuId]; if (!dest) return; KMMessageList msgList = selectedMessages(); KMCommand *command = new KMMoveCommand( dest, msgList ); command->start(); } //----------------------------------------------------------------------------- void SearchWindow::copySelectedToFolder( int menuId ) { KMFolder *dest = mMenuToFolder[menuId]; if (!dest) return; KMMessageList msgList = selectedMessages(); KMCommand *command = new KMCopyCommand( dest, msgList ); command->start(); } //----------------------------------------------------------------------------- void SearchWindow::updateContextMenuActions() { int count = selectedMessages().count(); bool single_actions = count == 1; mReplyAction->setEnabled( single_actions ); mReplyAllAction->setEnabled( single_actions ); mReplyListAction->setEnabled( single_actions ); mPrintAction->setEnabled( single_actions ); mForwardDigestAction->setEnabled( !single_actions ); mRedirectAction->setEnabled( single_actions ); mCopyAction->setEnabled( count > 0 ); mCutAction->setEnabled( count > 0 ); } //----------------------------------------------------------------------------- void SearchWindow::slotContextMenuRequested( TQListViewItem *lvi, const TQPoint &, int ) { if (!lvi) return; mLbxMatches->setSelected( lvi, true ); mLbxMatches->setCurrentItem( lvi ); // FIXME is this ever unGetMsg()'d? if (!message()) return; TQPopupMenu *menu = new TQPopupMenu(this); updateContextMenuActions(); mMenuToFolder.clear(); TQPopupMenu *msgMoveMenu = new TQPopupMenu(menu); mKMMainWidget->folderTree()->folderToPopupMenu( KMFolderTree::MoveMessage, TQT_TQOBJECT(this), &mMenuToFolder, msgMoveMenu ); TQPopupMenu *msgCopyMenu = new TQPopupMenu(menu); mKMMainWidget->folderTree()->folderToPopupMenu( KMFolderTree::CopyMessage, TQT_TQOBJECT(this), &mMenuToFolder, msgCopyMenu ); // show most used actions mReplyAction->plug(menu); mReplyAllAction->plug(menu); mReplyListAction->plug(menu); mForwardActionMenu->plug(menu); menu->insertSeparator(); mCopyAction->plug(menu); mCutAction->plug(menu); menu->insertItem(i18n("&Copy To"), msgCopyMenu); menu->insertItem(i18n("&Move To"), msgMoveMenu); menu->insertSeparator(); mSaveAsAction->plug(menu); mSaveAtchAction->plug(menu); mPrintAction->plug(menu); menu->insertSeparator(); mClearAction->plug(menu); menu->exec (TQCursor::pos(), 0); delete menu; } //----------------------------------------------------------------------------- void SearchWindow::slotClearSelection() { mLbxMatches->clearSelection(); } //----------------------------------------------------------------------------- void SearchWindow::slotReplyToMsg() { KMCommand *command = new KMReplyToCommand(this, message()); command->start(); } //----------------------------------------------------------------------------- void SearchWindow::slotReplyAllToMsg() { KMCommand *command = new KMReplyToAllCommand(this, message()); command->start(); } //----------------------------------------------------------------------------- void SearchWindow::slotReplyListToMsg() { KMCommand *command = new KMReplyListCommand(this, message()); command->start(); } //----------------------------------------------------------------------------- void SearchWindow::slotForwardInlineMsg() { KMCommand *command = new KMForwardInlineCommand(this, selectedMessages()); command->start(); } //----------------------------------------------------------------------------- void SearchWindow::slotForwardAttachedMsg() { KMCommand *command = new KMForwardAttachedCommand(this, selectedMessages()); command->start(); } //----------------------------------------------------------------------------- void SearchWindow::slotForwardDigestMsg() { KMCommand *command = new KMForwardDigestCommand(this, selectedMessages()); command->start(); } //----------------------------------------------------------------------------- void SearchWindow::slotRedirectMsg() { KMCommand *command = new KMRedirectCommand(this, message()); command->start(); } //----------------------------------------------------------------------------- void SearchWindow::slotSaveMsg() { KMSaveMsgCommand *saveCommand = new KMSaveMsgCommand(this, selectedMessages()); if (saveCommand->url().isEmpty()) delete saveCommand; else saveCommand->start(); } //----------------------------------------------------------------------------- void SearchWindow::slotSaveAttachments() { KMSaveAttachmentsCommand *saveCommand = new KMSaveAttachmentsCommand(this, selectedMessages()); saveCommand->start(); } //----------------------------------------------------------------------------- void SearchWindow::slotPrintMsg() { KMCommand *command = new KMPrintCommand(this, message()); command->start(); } void SearchWindow::slotCopyMsgs() { TQValueList list = MessageCopyHelper::serNumListFromMsgList( selectedMessages() ); mKMMainWidget->headers()->setCopiedMessages( list, false ); } void SearchWindow::slotCutMsgs() { TQValueList list = MessageCopyHelper::serNumListFromMsgList( selectedMessages() ); mKMMainWidget->headers()->setCopiedMessages( list, true ); } void SearchWindow::setSearchPattern( const KMSearchPattern& pattern ) { *mSearchPattern = pattern; mPatternEdit->setSearchPattern( mSearchPattern ); } } // namespace KMail #include "searchwindow.moc"