summaryrefslogtreecommitdiffstats
path: root/examples/qtmail/searchview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/qtmail/searchview.cpp')
-rw-r--r--examples/qtmail/searchview.cpp1007
1 files changed, 1007 insertions, 0 deletions
diff --git a/examples/qtmail/searchview.cpp b/examples/qtmail/searchview.cpp
new file mode 100644
index 00000000..4a7cbd61
--- /dev/null
+++ b/examples/qtmail/searchview.cpp
@@ -0,0 +1,1007 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Messaging Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "emailfolderview.h"
+#include "messagelistview.h"
+#include "readmail.h"
+#include "searchview.h"
+#include "selectfolder.h"
+
+#include <qmailaccount.h>
+#include <qmailserviceaction.h>
+
+#include <QButtonGroup>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QDialog>
+#include <QDateEdit>
+#include <QFlags>
+#include <QHBoxLayout>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QSpinBox>
+#include <QStatusBar>
+#include <QToolButton>
+#include <QVBoxLayout>
+#include <qtmailnamespace.h>
+
+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 = 0);
+
+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 = 0);
+
+ 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 = 0);
+ 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<QMailSearchAction::SearchSpecification>(itemData.value<int>());
+}
+
+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<int>(QMailSearchAction::Local));
+ m_searchSpecification->insertItem(1, Qtmail::icon("folderremote"), tr("Remote Search"), static_cast<int>(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<Comparator>(Contains) | DoesNotContain | Equal | NotEqual);};
+ static Comparators numericComparators(){ return QFlags<Comparator>(Equal) | NotEqual | GreaterThan | GreaterThanEqual | LessThan | LessThanEqual;}
+ static Comparators booleanComparators(){ return QFlags<Comparator>(Is) | IsNot;};
+
+ static QMap<Comparator,QString> comparatorMap()
+ {
+ static QMap<Comparator,QString> 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<Property,QString> propertyMap()
+ {
+ static QMap<Property,QString> 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 = 0);
+ 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<QString>(),ec));
+ else
+ QMailMessageKey::operator=(recipients(value.value<QString>(),ic));
+ }break;
+ case SearchTermWidget::SizeInBytes:
+ {
+ if(ct == Equality)
+ QMailMessageKey::operator=(size(value.value<int>(),ec));
+ else
+ QMailMessageKey::operator=(size(value.value<int>(),rc));
+ }break;
+ case SearchTermWidget::MessageStatus:
+ {
+ QMailMessageKey::operator=(status(value.value<quint64>(),ic));
+ }break;
+ case SearchTermWidget::Subject:
+ {
+ if(ct == Equality)
+ QMailMessageKey::operator=(subject(value.value<QString>(),ec));
+ else
+ QMailMessageKey::operator=(subject(value.value<QString>(),ic));
+ }break;
+ case SearchTermWidget::From:
+ {
+ if(ct == Equality)
+ QMailMessageKey::operator=(sender(value.value<QString>(),ec));
+ else
+ QMailMessageKey::operator=(sender(value.value<QString>(),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(QDateTime(value.value<QDate>()),QMailDataComparator::GreaterThanEqual);
+ QMailMessageKey endRange = receptionTimeStamp(QDateTime(value.value<QDate>().addDays(1)),QMailDataComparator::LessThan);
+
+ if(ec == QMailDataComparator::Equal)
+ QMailMessageKey::operator=(startRange & endRange);
+ else
+ QMailMessageKey::operator=(~(startRange & endRange));
+ }
+ else
+ {
+ if(rc == QMailDataComparator::GreaterThan)
+ QMailMessageKey::operator=(receptionTimeStamp(QDateTime(value.value<QDate>().addDays(1)),QMailDataComparator::GreaterThanEqual));
+ else if(rc == QMailDataComparator::LessThanEqual)
+ QMailMessageKey::operator=(receptionTimeStamp(QDateTime(value.value<QDate>()).addDays(1),QMailDataComparator::LessThan));
+ else
+ QMailMessageKey::operator=(receptionTimeStamp(QDateTime(value.value<QDate>()),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<Property,QString>::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<Comparator,QString>::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<Property>(m_property->itemData(m_property->currentIndex()).toInt());
+ return p;
+}
+
+SearchTermWidget::Comparator SearchTermWidget::comparator() const
+{
+ Comparator c = static_cast<Comparator>(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 = 0);
+ QMailMessageKey searchKey() const;
+
+public slots:
+ void reset();
+
+private slots:
+ void moreButtonClicked();
+ void lessButtonClicked();
+
+private:
+ void addSearchTerm();
+ void removeSearchTerm();
+
+private:
+ QWidget* m_termsListWidget;
+ QList<SearchTermWidget*> 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<SearchTermWidget*>::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<SearchTermWidget*>();
+ 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<QWidget*>(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 <searchview.moc>