/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the Qt Messaging Framework. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "emailfolderview.h" #include "messagelistview.h" #include "readmail.h" #include "searchview.h" #include "selectfolder.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const int maxMessageBytes = 100000000; static const int maxSearchTerms = 10; static const int minSearchTerms = 1; class SearchButton : public QPushButton { Q_OBJECT public: SearchButton(QWidget* parent = Q_NULLPTR); signals: void startSearch(); void stopSearch(); public slots: void searchActivityChanged(QMailServiceAction::Activity a); private slots: void thisClicked(); private: void updateView(); private: bool m_searching; }; SearchButton::SearchButton(QWidget* parent) : QPushButton("Search",parent), m_searching(false) { connect(this,SIGNAL(clicked(bool)),this,SLOT(thisClicked())); updateView(); } void SearchButton::thisClicked() { if (m_searching) emit stopSearch(); else emit startSearch(); } void SearchButton::searchActivityChanged(QMailServiceAction::Activity a) { m_searching = (a == QMailServiceAction::InProgress); updateView(); } void SearchButton::updateView() { if (m_searching) { setText("Stop"); setIcon(Qtmail::icon("cancel")); } else { setText("Search"); setIcon(Qtmail::icon("search")); } } class BodySearchWidget : public QWidget { Q_OBJECT public: BodySearchWidget(QWidget* parent = Q_NULLPTR); QString term() const; public slots: void reset(); private: QCheckBox* m_checkBox; QLineEdit* m_term; }; BodySearchWidget::BodySearchWidget(QWidget* parent) : QWidget(parent) { QHBoxLayout* layout = new QHBoxLayout(this); layout->setContentsMargins(0,0,0,0); m_checkBox = new QCheckBox("Body contains:",this); layout->addWidget(m_checkBox); m_term = new QLineEdit(this); layout->addWidget(m_term); connect(m_checkBox,SIGNAL(clicked(bool)),m_term,SLOT(setEnabled(bool))); reset(); } QString BodySearchWidget::term() const { if (m_checkBox->isChecked()) return m_term->text(); else return QString(); } void BodySearchWidget::reset() { m_checkBox->setCheckState(Qt::Unchecked); m_term->clear(); m_term->setEnabled(false); } class FolderSelectorWidget : public QWidget { Q_OBJECT public: FolderSelectorWidget(QWidget* parent = Q_NULLPTR); QMailMessageKey searchKey() const; QMailSearchAction::SearchSpecification searchSpecification() const; public slots: void reset(); private: void setupUi(); private slots: void selectFolder(); void specificFolderCheckChanged(int state); private: void updateDisplay(); bool haveSelection() const; private: QComboBox *m_searchSpecification; QCheckBox* m_specificFolderCheck; QLineEdit* m_specificFolderDisplay; QToolButton* m_selectFolderButton; QCheckBox* m_includeSubFoldersCheckBox; EmailFolderModel m_model; QMailMessageSet* m_selectedItem; }; FolderSelectorWidget::FolderSelectorWidget(QWidget* parent) : QWidget(parent), m_model(this), m_selectedItem(0) { m_model.init(); setupUi(); reset(); } QMailMessageKey FolderSelectorWidget::searchKey() const { QMailMessageKey k; if (m_selectedItem) { k = m_selectedItem->messageKey(); if (m_includeSubFoldersCheckBox->checkState() == Qt::Checked) { k |= m_selectedItem->descendantsMessageKey(); } } return k; } QMailSearchAction::SearchSpecification FolderSelectorWidget::searchSpecification() const { QVariant itemData = m_searchSpecification->itemData(m_searchSpecification->currentIndex()); Q_ASSERT(itemData != QVariant::Invalid); return static_cast(itemData.value()); } void FolderSelectorWidget::setupUi() { QVBoxLayout* vlayout = new QVBoxLayout(this); vlayout->setContentsMargins(0,0,0,0); m_searchSpecification = new QComboBox(this); m_searchSpecification->insertItem(0, Qtmail::icon("folder"), tr("Local Search"), static_cast(QMailSearchAction::Local)); m_searchSpecification->insertItem(1, Qtmail::icon("folderremote"), tr("Remote Search"), static_cast(QMailSearchAction::Remote)); vlayout->addWidget(m_searchSpecification); QHBoxLayout* layout = new QHBoxLayout; layout->setContentsMargins(0,0,0,0); m_specificFolderCheck = new QCheckBox(tr("Search only in:"),this); connect(m_specificFolderCheck,SIGNAL(stateChanged(int)),this,SLOT(specificFolderCheckChanged(int))); layout->addWidget(m_specificFolderCheck); m_specificFolderDisplay = new QLineEdit(this); m_specificFolderDisplay->setEnabled(false); layout->addWidget(m_specificFolderDisplay); m_selectFolderButton = new QToolButton(this); m_selectFolderButton->setIcon(Qtmail::icon("folder")); layout->addWidget(m_selectFolderButton); connect(m_selectFolderButton,SIGNAL(clicked()),this,SLOT(selectFolder())); m_includeSubFoldersCheckBox = new QCheckBox(tr("Include sub folders"),this); layout->addWidget(m_includeSubFoldersCheckBox); vlayout->addLayout(layout); } void FolderSelectorWidget::selectFolder() { SelectFolderDialog sfd(&m_model, this); if (sfd.exec() == QDialog::Accepted) { m_selectedItem = sfd.selectedItem(); m_specificFolderCheck->setChecked(true); } else if (!haveSelection()) { reset(); } updateDisplay(); } void FolderSelectorWidget::reset() { m_selectedItem = 0; m_specificFolderCheck->setChecked(false); m_includeSubFoldersCheckBox->setChecked(false); updateDisplay(); } void FolderSelectorWidget::specificFolderCheckChanged(int state) { if (state == Qt::Unchecked) reset(); else if (!haveSelection()) selectFolder(); } void FolderSelectorWidget::updateDisplay() { if (m_selectedItem) { m_specificFolderDisplay->setText(m_selectedItem->displayName()); } else { m_specificFolderDisplay->clear(); } m_includeSubFoldersCheckBox->setEnabled(!m_specificFolderDisplay->text().isEmpty()); } bool FolderSelectorWidget::haveSelection() const { return m_selectedItem; } class SearchTermWidget : public QWidget { Q_OBJECT public: enum TermFormat { TextTerm, NumericTerm, MessageFlagsTerm , DateTerm, NoTerm}; enum Comparator{ Contains = 1, DoesNotContain = 1 << 1, Equal = 1 << 2, NotEqual = 1 << 3, Is = 1 << 6, IsNot = 1 << 7, GreaterThan = 1 << 8, GreaterThanEqual = 1 << 9, LessThan = 1 << 10, LessThanEqual = 1 << 11 }; Q_DECLARE_FLAGS(Comparators,Comparator) static Comparators textComparators(){ return (QFlags(Contains) | DoesNotContain | Equal | NotEqual);}; static Comparators numericComparators(){ return QFlags(Equal) | NotEqual | GreaterThan | GreaterThanEqual | LessThan | LessThanEqual;} static Comparators booleanComparators(){ return QFlags(Is) | IsNot;}; static QMap comparatorMap() { static QMap s; if (s.isEmpty()) { s.insert(Contains,"Contains"); s.insert(DoesNotContain,"Does not contain"); s.insert(Equal,"Equal"); s.insert(NotEqual,"Not equal"); s.insert(Is,"Is"); s.insert(IsNot,"Is not"); s.insert(GreaterThan,"Greater than"); s.insert(GreaterThanEqual,"Greater than or equal"); s.insert(LessThan,"Less than"); s.insert(LessThanEqual,"Less than or equal"); } return s; } enum Property{ AllRecipients, SizeInBytes, MessageStatus, Subject, From, ReceptionDate }; static QMap propertyMap() { static QMap s; if (s.isEmpty()) { s.insert(AllRecipients,"All recipients"); s.insert(SizeInBytes,"Size in bytes"); s.insert(MessageStatus,"Message status"); s.insert(Subject,"Subject"); s.insert(From,"From"); s.insert(ReceptionDate,"Reception date"); } return s; } public: SearchTermWidget(QWidget* parent = Q_NULLPTR); void reset(); QMailMessageKey searchKey() const; private slots: void propertyChanged(); private: void setupUi(); void setComparators(Comparators c); void setTerm(TermFormat f); inline Property property() const; inline Comparator comparator() const; QVariant term() const; private: QComboBox* m_property; QComboBox* m_comparator; QLineEdit* m_textTerm; QComboBox* m_messageFlagsTerm; QSpinBox* m_numericTerm; QDateEdit* m_dateTerm; private: friend class SearchTermsComposer; }; class SearchKey : public QMailMessageKey { public: SearchKey(SearchTermWidget::Property p, SearchTermWidget::Comparator c, QVariant value); }; SearchKey::SearchKey(SearchTermWidget::Property property, SearchTermWidget::Comparator comparator, QVariant value) : QMailMessageKey() { QMailDataComparator::EqualityComparator ec = QMailDataComparator::Equal; QMailDataComparator::InclusionComparator ic = QMailDataComparator::Includes; QMailDataComparator::RelationComparator rc = QMailDataComparator::GreaterThan; enum compartorType{Equality,Inclusion,Relation,Presence,None} ct = None; switch (comparator) { case SearchTermWidget::Contains: { ct = Inclusion; ic = QMailDataComparator::Includes; } break; case SearchTermWidget::DoesNotContain: { ct = Inclusion; ic = QMailDataComparator::Excludes; } break; case SearchTermWidget::Equal: { ct = Equality; ec = QMailDataComparator::Equal; } break; case SearchTermWidget::NotEqual: { ct = Equality; ec = QMailDataComparator::NotEqual; } break; case SearchTermWidget::Is: { ct = Inclusion; ic = QMailDataComparator::Includes; } break; case SearchTermWidget::IsNot: { ct = Inclusion; ic = QMailDataComparator::Excludes; } break; case SearchTermWidget::GreaterThan: { ct = Relation; rc = QMailDataComparator::GreaterThan; } break; case SearchTermWidget::GreaterThanEqual: { ct = Relation; rc = QMailDataComparator::GreaterThanEqual; } break; case SearchTermWidget::LessThan: { ct = Relation; rc = QMailDataComparator::LessThan; } break; case SearchTermWidget::LessThanEqual: { ct = Relation; rc = QMailDataComparator::LessThanEqual; } break; } switch (property) { case SearchTermWidget::AllRecipients: { if (ct == Equality) QMailMessageKey::operator=(recipients(value.value(),ec)); else QMailMessageKey::operator=(recipients(value.value(),ic)); }break; case SearchTermWidget::SizeInBytes: { if (ct == Equality) QMailMessageKey::operator=(size(value.value(),ec)); else QMailMessageKey::operator=(size(value.value(),rc)); }break; case SearchTermWidget::MessageStatus: { QMailMessageKey::operator=(status(value.value(),ic)); }break; case SearchTermWidget::Subject: { if (ct == Equality) QMailMessageKey::operator=(subject(value.value(),ec)); else QMailMessageKey::operator=(subject(value.value(),ic)); }break; case SearchTermWidget::From: { if (ct == Equality) QMailMessageKey::operator=(sender(value.value(),ec)); else QMailMessageKey::operator=(sender(value.value(),ic)); }break; case SearchTermWidget::ReceptionDate: { //beacuse the storage system uses the more fine grained QDateTime, we need to construct keys that //consider time range as well if (ct == Equality) { QMailMessageKey startRange = receptionTimeStamp(value.value().startOfDay(),QMailDataComparator::GreaterThanEqual); QMailMessageKey endRange = receptionTimeStamp(value.value().addDays(1).startOfDay(),QMailDataComparator::LessThan); if (ec == QMailDataComparator::Equal) QMailMessageKey::operator=(startRange & endRange); else QMailMessageKey::operator=(~(startRange & endRange)); } else { if (rc == QMailDataComparator::GreaterThan) QMailMessageKey::operator=(receptionTimeStamp(value.value().addDays(1).startOfDay(),QMailDataComparator::GreaterThanEqual)); else if (rc == QMailDataComparator::LessThanEqual) QMailMessageKey::operator=(receptionTimeStamp(value.value().startOfDay().addDays(1),QMailDataComparator::LessThan)); else QMailMessageKey::operator=(receptionTimeStamp(value.value().startOfDay(),rc)); } }break; } } SearchTermWidget::SearchTermWidget(QWidget* parent) : QWidget(parent) { setupUi(); m_property->setCurrentIndex(1); m_property->setCurrentIndex(0); reset(); } void SearchTermWidget::reset() { m_textTerm->clear(); m_messageFlagsTerm->setCurrentIndex(0); m_numericTerm->setValue(m_numericTerm->minimum()); m_property->setCurrentIndex(1); m_property->setCurrentIndex(0); m_dateTerm->setDate(QDate::currentDate()); } QMailMessageKey SearchTermWidget::searchKey() const { if (term().isValid()) return SearchKey(property(),comparator(),term()); else return QMailMessageKey(); } void SearchTermWidget::propertyChanged() { switch (property()) { case SizeInBytes: setComparators(numericComparators()); setTerm(NumericTerm); break; case MessageStatus: setComparators(booleanComparators()); setTerm(MessageFlagsTerm); break; case ReceptionDate: setComparators(numericComparators()); setTerm(DateTerm); break; default: setComparators(textComparators()); setTerm(TextTerm); break; } } void SearchTermWidget::setupUi() { QHBoxLayout* layout = new QHBoxLayout(this); layout->setContentsMargins(0,0,0,0); m_property = new QComboBox(this); QMap::const_iterator itr = propertyMap().constBegin(); for (;itr != propertyMap().constEnd() ; itr++) m_property->addItem(*itr,itr.key()); layout->addWidget(m_property); m_comparator = new QComboBox(this); layout->addWidget(m_comparator); m_textTerm = new QLineEdit(this); layout->addWidget(m_textTerm); m_messageFlagsTerm = new QComboBox(this); layout->addWidget(m_messageFlagsTerm); m_messageFlagsTerm->addItem(QIcon(":icon/new"),"New",QMailMessage::New); m_messageFlagsTerm->addItem(QIcon(":icon/mail_generic"),"Read",QMailMessage::Read); m_messageFlagsTerm->addItem(QIcon(":icon/mail_reply"),"Replied",QMailMessage::Replied); m_messageFlagsTerm->addItem(QIcon(":icon/mail_forward"),"Forwarded",QMailMessage::Forwarded); m_messageFlagsTerm->addItem(QIcon(":icon/sent"),"Sent",QMailMessage::Sent); m_messageFlagsTerm->addItem(QIcon(":icon/attach"),"Has attachment(s)",QMailMessage::HasAttachments); m_messageFlagsTerm->setVisible(false); m_numericTerm = new QSpinBox(this); m_numericTerm->setMaximum(maxMessageBytes); layout->addWidget(m_numericTerm); m_numericTerm->setVisible(false); m_dateTerm = new QDateEdit(this); layout->addWidget(m_dateTerm); m_dateTerm->setVisible(false); m_dateTerm->setCalendarPopup(true); connect(m_property,SIGNAL(currentIndexChanged(int)),this,SLOT(propertyChanged())); } void SearchTermWidget::setComparators(Comparators c) { m_comparator->clear(); QMap::const_iterator itr = comparatorMap().constBegin(); for (;itr != comparatorMap().constEnd();itr++) { if (c & itr.key()) m_comparator->addItem(*itr,itr.key()); } } void SearchTermWidget::setTerm(TermFormat t) { m_textTerm->hide(); m_numericTerm->hide(); m_messageFlagsTerm->hide(); m_dateTerm->hide(); QWidget* w = 0; switch (t) { case TextTerm: w = m_textTerm; break; case NumericTerm: w = m_numericTerm; break; case MessageFlagsTerm: w = m_messageFlagsTerm; break; case DateTerm: w = m_dateTerm; break; case NoTerm: break; } if (w) w->show(); } SearchTermWidget::Property SearchTermWidget::property() const { Property p = static_cast(m_property->itemData(m_property->currentIndex()).toInt()); return p; } SearchTermWidget::Comparator SearchTermWidget::comparator() const { Comparator c = static_cast(m_comparator->itemData(m_comparator->currentIndex()).toInt()); return c; } QVariant SearchTermWidget::term() const { TermFormat f = NoTerm; if (m_textTerm->isVisible()) f = TextTerm; else if (m_numericTerm->isVisible()) f = NumericTerm; else if (m_messageFlagsTerm->isVisible()) f = MessageFlagsTerm; else if (m_dateTerm->isVisible()) f = DateTerm; QVariant keyValue; switch (f) { case TextTerm: if (!m_textTerm->text().isEmpty()) keyValue = m_textTerm->text(); break; case NumericTerm: keyValue = m_numericTerm->value(); break; case DateTerm: keyValue = m_dateTerm->dateTime(); break; case MessageFlagsTerm: keyValue = m_messageFlagsTerm->itemData(m_messageFlagsTerm->currentIndex()); break; case NoTerm: break; } return keyValue; } class SearchTermsComposer : public QWidget { Q_OBJECT public: SearchTermsComposer(QWidget* parent = Q_NULLPTR); QMailMessageKey searchKey() const; public slots: void reset(); private slots: void moreButtonClicked(); void lessButtonClicked(); private: void addSearchTerm(); void removeSearchTerm(); private: QWidget* m_termsListWidget; QList m_terms; QRadioButton* m_matchAllButton; QRadioButton* m_matchAnyButton; QPushButton* m_moreButton; QPushButton* m_lessButton; QVBoxLayout* m_termsLayout; }; SearchTermsComposer::SearchTermsComposer(QWidget* parent) : QWidget(parent) { QVBoxLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(0,0,0,0); m_matchAllButton = new QRadioButton("Match all of the following",this); layout->addWidget(m_matchAllButton); m_matchAllButton->setChecked(true); m_matchAnyButton = new QRadioButton("Match any of the following",this); layout->addWidget(m_matchAnyButton); m_termsListWidget = new QWidget(this); m_termsLayout = new QVBoxLayout(m_termsListWidget); m_termsLayout->setContentsMargins(0,0,0,0); layout->addWidget(m_termsListWidget); QHBoxLayout* controlButtonsLayout = new QHBoxLayout; m_moreButton = new QPushButton("More",this); m_moreButton->setIcon(Qtmail::icon("add")); connect(m_moreButton,SIGNAL(clicked(bool)),this,SLOT(moreButtonClicked())); controlButtonsLayout->addWidget(m_moreButton); m_lessButton = new QPushButton("Less",this); m_lessButton->setIcon(Qtmail::icon("remove")); connect(m_lessButton,SIGNAL(clicked(bool)),this,SLOT(lessButtonClicked())); controlButtonsLayout->addWidget(m_lessButton); controlButtonsLayout->addStretch(); layout->addLayout(controlButtonsLayout); for (int i = 0; i < minSearchTerms; ++i) addSearchTerm(); } QMailMessageKey SearchTermsComposer::searchKey() const { QList::const_iterator itr = m_terms.begin(); QMailMessageKey key = (*itr)->searchKey(); itr++; if (m_matchAllButton->isChecked()) { for (;itr != m_terms.end(); ++itr) key &= (*itr)->searchKey(); } else if (m_matchAnyButton->isChecked()) { for (;itr != m_terms.end(); ++itr) key |= (*itr)->searchKey(); } return key; } void SearchTermsComposer::reset() { setUpdatesEnabled(false); foreach(SearchTermWidget* stw, m_terms) stw->deleteLater(); m_terms = QList(); for (int i = 0 ; i < minSearchTerms; ++i) addSearchTerm(); updateGeometry(); setUpdatesEnabled(true); } void SearchTermsComposer::moreButtonClicked() { if (m_terms.count() < maxSearchTerms ) addSearchTerm(); } void SearchTermsComposer::lessButtonClicked() { if (m_terms.count() > minSearchTerms ) removeSearchTerm(); } void SearchTermsComposer::addSearchTerm() { setUpdatesEnabled(false); SearchTermWidget* stw = new SearchTermWidget(this); m_termsLayout->addWidget(stw); m_terms.append(stw); updateGeometry(); setUpdatesEnabled(true); m_lessButton->setVisible(m_terms.count() > minSearchTerms); m_moreButton->setVisible(m_terms.count() != maxSearchTerms); } void SearchTermsComposer::removeSearchTerm() { setUpdatesEnabled(false); SearchTermWidget* lastTerm = m_terms.last(); m_terms.removeLast(); m_termsLayout->removeWidget(lastTerm); lastTerm->deleteLater(); updateGeometry(); setUpdatesEnabled(true); m_lessButton->setVisible(m_terms.count() > minSearchTerms); m_moreButton->setVisible(m_terms.count() != maxSearchTerms); } SearchView::SearchView(QWidget* parent, Qt::WindowFlags f) : QMainWindow(parent,f), m_searched(false) { setupUi(); setGeometry(0,0,600,400); setupSearchAction(); } void SearchView::setVisible(bool visible) { if (visible) { //center the window on the parent QWidget* w = qobject_cast(parent()); QPoint p; if (w) { // Use mapToGlobal rather than geometry() in case w might // be embedded in another application QPoint pp = w->mapToGlobal(QPoint(0,0)); p = QPoint(pp.x() + w->width()/2, pp.y() + w->height()/ 2); } p = QPoint(p.x()-width()/2, p.y()-height()/2); move(p); } QMainWindow::setVisible(visible); } void SearchView::reset() { m_folderSelectorWidget->reset(); m_searchTermsComposer->reset(); m_searchResults->setKey(QMailMessageKey::nonMatchingKey()); m_searchResults->reset(); m_bodySearchWidget->reset(); } void SearchView::close() { if (m_searchAction->activity() == QMailServiceAction::InProgress) m_searchAction->cancelOperation(); QMainWindow::close(); } void SearchView::setupUi() { setWindowTitle("Search"); QWidget* centralWidget = new QWidget(this); setCentralWidget(centralWidget); QHBoxLayout* mainLayout = new QHBoxLayout(centralWidget); QVBoxLayout* searchSettingsLayout = new QVBoxLayout; QVBoxLayout* controlButtonsLayout = new QVBoxLayout; m_searchButton = new SearchButton(this); connect(m_searchButton,SIGNAL(startSearch()),this,SLOT(startSearch())); connect(m_searchButton,SIGNAL(stopSearch()),this,SLOT(stopSearch())); controlButtonsLayout->addWidget(m_searchButton); m_resetButton = new QPushButton("Reset",this); connect(m_resetButton,SIGNAL(clicked(bool)),this,SLOT(reset())); controlButtonsLayout->addWidget(m_resetButton); controlButtonsLayout->addStretch(); m_closeButton = new QPushButton("Close",this); m_closeButton->setIcon(Qtmail::icon("close")); connect(m_closeButton,SIGNAL(clicked(bool)),this,SLOT(close())); controlButtonsLayout->addWidget(m_closeButton); mainLayout->addLayout(searchSettingsLayout); mainLayout->addLayout(controlButtonsLayout); m_folderSelectorWidget = new FolderSelectorWidget(this); searchSettingsLayout->addWidget(m_folderSelectorWidget); m_searchTermsComposer = new SearchTermsComposer(this); searchSettingsLayout->addWidget(m_searchTermsComposer); searchSettingsLayout->addWidget(m_bodySearchWidget = new BodySearchWidget(this)); m_searchResults = new MessageListView(this); m_searchResults->showQuickSearch(false); connect(m_searchResults,SIGNAL(activated(const QMailMessageId&)),this,SIGNAL(searchResultSelected(const QMailMessageId&))); searchSettingsLayout->addWidget(m_searchResults); m_statusBar = new QStatusBar(this); setStatusBar(m_statusBar); m_statusBar->showMessage("Ready."); } QMailMessageKey SearchView::searchKey() const { QMailMessageKey key = m_searchTermsComposer->searchKey(); if (!m_folderSelectorWidget->searchKey().isEmpty()) { if (!key.isEmpty()) key &= m_folderSelectorWidget->searchKey(); else key = m_folderSelectorWidget->searchKey(); } return key; } void SearchView::startSearch() { m_searchResults->setKey(QMailMessageKey::nonMatchingKey()); if (m_searched) { //lets "restart" the search action delete m_searchAction; setupSearchAction(); } QMailMessageKey key = searchKey(); if (key.isEmpty() && m_bodySearchWidget->term().isEmpty()) return; if (m_searchAction->activity() != QMailServiceAction::InProgress) m_searchAction->searchMessages(key,m_bodySearchWidget->term(), m_folderSelectorWidget->searchSpecification()); m_searched = true; } void SearchView::stopSearch() { if (m_searched) m_searchAction->cancelOperation(); } void SearchView::messageIdsMatched(const QMailMessageIdList& ids) { m_searchResults->setKey(m_searchResults->key() | QMailMessageKey::id(ids)); } void SearchView::searchActivityChanged(QMailServiceAction::Activity a) { if (a == QMailServiceAction::Successful) m_statusBar->showMessage("Done."); } void SearchView::searchProgressChanged(uint value, uint total) { if (total > 0) m_statusBar->showMessage(QString("Searching %1%").arg((value*100)/total)); } void SearchView::setupSearchAction() { m_searchAction = new QMailSearchAction(this); connect(m_searchAction, SIGNAL(activityChanged(QMailServiceAction::Activity)), m_searchButton, SLOT(searchActivityChanged(QMailServiceAction::Activity))); connect(m_searchAction, SIGNAL(messageIdsMatched(const QMailMessageIdList&)), this, SLOT(messageIdsMatched(const QMailMessageIdList&))); connect(m_searchAction, SIGNAL(activityChanged(QMailServiceAction::Activity)), this, SLOT(searchActivityChanged(QMailServiceAction::Activity))); connect(m_searchAction, SIGNAL(progressChanged(uint,uint)), this, SLOT(searchProgressChanged(uint,uint))); } #include