diff --git a/src/core/searchquery.cpp b/src/core/searchquery.cpp index 71f4be352..9d9e5cdbc 100644 --- a/src/core/searchquery.cpp +++ b/src/core/searchquery.cpp @@ -1,568 +1,599 @@ /* Copyright (c) 2014 Daniel Vrátil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "searchquery.h" #include "akonadicore_debug.h" #include #include #include using namespace Akonadi; class SearchTerm::Private : public QSharedData { public: Private() : QSharedData() , condition(SearchTerm::CondEqual) , relation(SearchTerm::RelAnd) { } Private(const Private &other) : QSharedData(other) , key(other.key) , value(other.value) , condition(other.condition) , relation(other.relation) , terms(other.terms) , isNegated(other.isNegated) { } bool operator==(const Private &other) const { return relation == other.relation && isNegated == other.isNegated && terms == other.terms && key == other.key && value == other.value && condition == other.condition; } QString key; QVariant value; Condition condition; Relation relation; QList terms; bool isNegated = false; }; class SearchQuery::Private : public QSharedData { public: Private() : QSharedData() , limit(-1) { } Private(const Private &other) : QSharedData(other) , rootTerm(other.rootTerm) , limit(other.limit) { } bool operator==(const Private &other) const { return rootTerm == other.rootTerm && limit == other.limit; } static QVariantMap termToJSON(const SearchTerm &term) { const QList &subTerms = term.subTerms(); QVariantMap termJSON; termJSON.insert(QStringLiteral("negated"), term.isNegated()); if (subTerms.isEmpty()) { if (!term.isNull()) { termJSON.insert(QStringLiteral("key"), term.key()); termJSON.insert(QStringLiteral("value"), term.value()); termJSON.insert(QStringLiteral("cond"), static_cast(term.condition())); } } else { termJSON.insert(QStringLiteral("rel"), static_cast(term.relation())); QVariantList subTermsJSON; subTermsJSON.reserve(subTerms.count()); for (const SearchTerm &term : qAsConst(subTerms)) { subTermsJSON.append(termToJSON(term)); } termJSON.insert(QStringLiteral("subTerms"), subTermsJSON); } return termJSON; } static SearchTerm JSONToTerm(const QVariantMap &map) { if (map.isEmpty()) { return SearchTerm(); } else if (map.contains(QStringLiteral("key"))) { SearchTerm term(map[QStringLiteral("key")].toString(), map[QStringLiteral("value")], static_cast(map[QStringLiteral("cond")].toInt())); term.setIsNegated(map[QStringLiteral("negated")].toBool()); return term; } else if (map.contains(QStringLiteral("rel"))) { SearchTerm term(static_cast(map[QStringLiteral("rel")].toInt())); term.setIsNegated(map[QStringLiteral("negated")].toBool()); const QList list = map[QStringLiteral("subTerms")].toList(); for (const QVariant &var : list) { term.addSubTerm(JSONToTerm(var.toMap())); } return term; } else { qCWarning(AKONADICORE_LOG) << "Invalid JSON for term: " << map; return SearchTerm(); } } SearchTerm rootTerm; int limit; }; namespace { static QMap searchFieldMapping() { static QMap mapping; if (mapping.isEmpty()) { mapping.insert(SearchTerm::Collection, QStringLiteral("collection")); } return mapping; } } SearchTerm::SearchTerm(SearchTerm::Relation relation) : d(new Private) { d->relation = relation; } SearchTerm::SearchTerm(const QString &key, const QVariant &value, SearchTerm::Condition condition) : d(new Private) { d->relation = RelAnd; d->key = key; d->value = value; d->condition = condition; } SearchTerm::SearchTerm(SearchField field, const QVariant &value, SearchTerm::Condition condition) : SearchTerm(toKey(field), value, condition) { } SearchTerm::SearchTerm(const SearchTerm &other) : d(other.d) { } SearchTerm::~SearchTerm() { } SearchTerm &SearchTerm::operator=(const SearchTerm &other) { d = other.d; return *this; } bool SearchTerm::operator==(const SearchTerm &other) const { return *d == *other.d; } bool SearchTerm::isNull() const { return d->key.isEmpty() && d->value.isNull() && d->terms.isEmpty(); } QString SearchTerm::key() const { return d->key; } QVariant SearchTerm::value() const { return d->value; } SearchTerm::Condition SearchTerm::condition() const { return d->condition; } void SearchTerm::setIsNegated(bool negated) { d->isNegated = negated; } bool SearchTerm::isNegated() const { return d->isNegated; } void SearchTerm::addSubTerm(const SearchTerm &term) { d->terms << term; } QList< SearchTerm > SearchTerm::subTerms() const { return d->terms; } SearchTerm::Relation SearchTerm::relation() const { return d->relation; } QString SearchTerm::toKey(SearchField field) { return searchFieldMapping().value(field); } SearchTerm::SearchField SearchTerm::fromKey(const QString &key) { return searchFieldMapping().key(key); } +SearchTerm SearchTerm::inCollection(qint64 collection) +{ + return SearchTerm(Collection, collection); +} + + + SearchQuery::SearchQuery(SearchTerm::Relation rel) : d(new Private) { d->rootTerm = SearchTerm(rel); } SearchQuery::SearchQuery(const SearchQuery &other) : d(other.d) { } SearchQuery::~SearchQuery() { } SearchQuery &SearchQuery::operator=(const SearchQuery &other) { d = other.d; return *this; } bool SearchQuery::operator==(const SearchQuery &other) const { return *d == *other.d; } bool SearchQuery::isNull() const { return d->rootTerm.isNull(); } SearchTerm SearchQuery::term() const { return d->rootTerm; } void SearchQuery::addTerm(const QString &key, const QVariant &value, SearchTerm::Condition condition) { addTerm(SearchTerm(key, value, condition)); } void SearchQuery::addTerm(const SearchTerm &term) { d->rootTerm.addSubTerm(term); } void SearchQuery::setTerm(const SearchTerm &term) { d->rootTerm = term; } void SearchQuery::setLimit(int limit) { d->limit = limit; } int SearchQuery::limit() const { return d->limit; } QByteArray SearchQuery::toJSON() const { QVariantMap root; if (!d->rootTerm.isNull()) { root = Private::termToJSON(d->rootTerm); root.insert(QStringLiteral("limit"), d->limit); } QJsonObject jo = QJsonObject::fromVariantMap(root); QJsonDocument jdoc; jdoc.setObject(jo); return jdoc.toJson(); } SearchQuery SearchQuery::fromJSON(const QByteArray &jsonData) { QJsonParseError error; const QJsonDocument json = QJsonDocument::fromJson(jsonData, &error); if (error.error != QJsonParseError::NoError || json.isNull()) { return SearchQuery(); } SearchQuery query; const QJsonObject obj = json.object(); query.d->rootTerm = Private::JSONToTerm(obj.toVariantMap()); if (obj.contains(QStringLiteral("limit"))) { query.d->limit = obj.value(QStringLiteral("limit")).toInt(); } return query; } static QMap emailSearchFieldMapping() { static QMap mapping; if (mapping.isEmpty()) { mapping.insert(EmailSearchTerm::Body, QStringLiteral("body")); mapping.insert(EmailSearchTerm::Headers, QStringLiteral("headers")); mapping.insert(EmailSearchTerm::Subject, QStringLiteral("subject")); mapping.insert(EmailSearchTerm::Message, QStringLiteral("message")); mapping.insert(EmailSearchTerm::HeaderFrom, QStringLiteral("from")); mapping.insert(EmailSearchTerm::HeaderTo, QStringLiteral("to")); mapping.insert(EmailSearchTerm::HeaderCC, QStringLiteral("cc")); mapping.insert(EmailSearchTerm::HeaderBCC, QStringLiteral("bcc")); mapping.insert(EmailSearchTerm::HeaderReplyTo, QStringLiteral("replyto")); mapping.insert(EmailSearchTerm::HeaderOrganization, QStringLiteral("organization")); mapping.insert(EmailSearchTerm::HeaderListId, QStringLiteral("listid")); mapping.insert(EmailSearchTerm::HeaderResentFrom, QStringLiteral("resentfrom")); mapping.insert(EmailSearchTerm::HeaderXLoop, QStringLiteral("xloop")); mapping.insert(EmailSearchTerm::HeaderXMailingList, QStringLiteral("xmailinglist")); mapping.insert(EmailSearchTerm::HeaderXSpamFlag, QStringLiteral("xspamflag")); mapping.insert(EmailSearchTerm::HeaderDate, QStringLiteral("date")); mapping.insert(EmailSearchTerm::HeaderOnlyDate, QStringLiteral("onlydate")); mapping.insert(EmailSearchTerm::MessageStatus, QStringLiteral("messagestatus")); mapping.insert(EmailSearchTerm::MessageTag, QStringLiteral("messagetag")); mapping.insert(EmailSearchTerm::ByteSize, QStringLiteral("size")); mapping.insert(EmailSearchTerm::Attachment, QStringLiteral("attachment")); } return mapping; } EmailSearchTerm::EmailSearchTerm(EmailSearchTerm::EmailSearchField field, const QVariant &value, SearchTerm::Condition condition) : SearchTerm(toKey(field), value, condition) { } QString EmailSearchTerm::toKey(EmailSearchTerm::EmailSearchField field) { return emailSearchFieldMapping().value(field); } EmailSearchTerm::EmailSearchField EmailSearchTerm::fromKey(const QString &key) { return emailSearchFieldMapping().key(key); } namespace { SearchTerm matchStringList(EmailSearchTerm::EmailSearchField field, const QStringList &list, SearchTerm::Relation relation) { if (list.size() == 1) { return EmailSearchTerm(field, list.first()); } SearchTerm relTerm(relation); for (const auto &e : list) { relTerm.addSubTerm(EmailSearchTerm(field, e)); } return relTerm; } } SearchTerm EmailSearchTerm::from(const QStringList &from, SearchTerm::Relation relation) { return matchStringList(HeaderFrom, from, relation); } SearchTerm EmailSearchTerm::to(const QStringList &to, SearchTerm::Relation relation) { return matchStringList(HeaderTo, to, relation); } SearchTerm EmailSearchTerm::cc(const QStringList &cc, SearchTerm::Relation relation) { return matchStringList(HeaderCC, cc, relation); } SearchTerm EmailSearchTerm::bcc(const QStringList &bcc, SearchTerm::Relation relation) { return matchStringList(HeaderBCC, bcc, relation); } SearchTerm EmailSearchTerm::involves(const QStringList &involves, SearchTerm::Relation relation) { SearchTerm rootTerm(relation); for (const auto person : involves) { SearchTerm orTerm(SearchTerm::RelOr); for (const auto field : { HeaderFrom, HeaderTo, HeaderCC, HeaderBCC }) { orTerm.addSubTerm(EmailSearchTerm(field, person)); } rootTerm.addSubTerm(orTerm); } return rootTerm; } SearchTerm EmailSearchTerm::isRead(bool isRead) { // FIXME: The strings are in akonadi-mime - should this whole thing go there? EmailSearchTerm term(MessageStatus, QLatin1String("\\SEEN")); term.setIsNegated(!isRead); return term; } SearchTerm EmailSearchTerm::isImportant(bool isImportant) { EmailSearchTerm term(MessageStatus, QLatin1String("\\FLAGGED")); term.setIsNegated(!isImportant); return term; } SearchTerm EmailSearchTerm::hasAttachment(bool hasAttachment) { EmailSearchTerm term(MessageStatus, QLatin1String("$ATTACHMENT")); term.setIsNegated(!hasAttachment); return term; } SearchTerm EmailSearchTerm::subjectMatches(const QString &subject) { return EmailSearchTerm(Subject, subject, SearchTerm::CondContains); } SearchTerm EmailSearchTerm::bodyMatches(const QString &bodyMatches) { return EmailSearchTerm(Body, bodyMatches, SearchTerm::CondContains); } SearchTerm EmailSearchTerm::matches(const QString &match) { return EmailSearchTerm(Message, match, SearchTerm::CondContains); } static QMap contactSearchFieldMapping() { static QMap mapping; if (mapping.isEmpty()) { mapping.insert(ContactSearchTerm::Name, QStringLiteral("name")); mapping.insert(ContactSearchTerm::Nickname, QStringLiteral("nickname")); mapping.insert(ContactSearchTerm::Email, QStringLiteral("email")); mapping.insert(ContactSearchTerm::Uid, QStringLiteral("uid")); mapping.insert(ContactSearchTerm::All, QStringLiteral("all")); mapping.insert(ContactSearchTerm::Birthday, QStringLiteral("birthday")); mapping.insert(ContactSearchTerm::Anniversary, QStringLiteral("anniversary")); } return mapping; } ContactSearchTerm::ContactSearchTerm(ContactSearchTerm::ContactSearchField field, const QVariant &value, SearchTerm::Condition condition) : SearchTerm(toKey(field), value, condition) { } QString ContactSearchTerm::toKey(ContactSearchTerm::ContactSearchField field) { return contactSearchFieldMapping().value(field); } ContactSearchTerm::ContactSearchField ContactSearchTerm::fromKey(const QString &key) { return contactSearchFieldMapping().key(key); } QMap incidenceSearchFieldMapping() { static QMap mapping; if (mapping.isEmpty()) { mapping.insert(IncidenceSearchTerm::All, QStringLiteral("all")); mapping.insert(IncidenceSearchTerm::PartStatus, QStringLiteral("partstatus")); mapping.insert(IncidenceSearchTerm::Organizer, QStringLiteral("organizer")); mapping.insert(IncidenceSearchTerm::Summary, QStringLiteral("summary")); mapping.insert(IncidenceSearchTerm::Location, QStringLiteral("location")); } return mapping; } IncidenceSearchTerm::IncidenceSearchTerm(IncidenceSearchTerm::IncidenceSearchField field, const QVariant &value, SearchTerm::Condition condition) : SearchTerm(toKey(field), value, condition) { } QString IncidenceSearchTerm::toKey(IncidenceSearchTerm::IncidenceSearchField field) { return incidenceSearchFieldMapping().value(field); } IncidenceSearchTerm::IncidenceSearchField IncidenceSearchTerm::fromKey(const QString &key) { return incidenceSearchFieldMapping().key(key); } QMap collectionSearchFieldMapping() { static QMap mapping; if (mapping.isEmpty()) { mapping.insert(CollectionSearchTerm::Name, QStringLiteral("name")); mapping.insert(CollectionSearchTerm::Namespace, QStringLiteral("namespace")); mapping.insert(CollectionSearchTerm::Identification, QStringLiteral("identification")); mapping.insert(CollectionSearchTerm::MimeType, QStringLiteral("mimetype")); } return mapping; } CollectionSearchTerm::CollectionSearchTerm(CollectionSearchTerm::CollectionSearchField field, const QVariant &value, SearchTerm::Condition condition) : SearchTerm(toKey(field), value, condition) { } QString CollectionSearchTerm::toKey(CollectionSearchTerm::CollectionSearchField field) { return collectionSearchFieldMapping().value(field); } Akonadi::CollectionSearchTerm::CollectionSearchField Akonadi::CollectionSearchTerm::fromKey(const QString &key) { return collectionSearchFieldMapping().key(key); } + +SearchTerm CollectionSearchTerm::hasMimeTypes(const QStringList &mimeTypes) +{ + SearchTerm andTerm(RelAnd); + for (const auto &mt : mimeTypes) { + andTerm.addSubTerm(CollectionSearchTerm(MimeType, mt)); + } + return andTerm; +} + +SearchTerm CollectionSearchTerm::hasNamespaces(const QStringList &namespaces) +{ + SearchTerm andTerm(RelAnd); + for (const auto &ns : namespaces) { + andTerm.addSubTerm(CollectionSearchTerm(Namespace, ns)); + } + return andTerm; +} + +SearchTerm CollectionSearchTerm::nameMatches(const QString &name) +{ + return CollectionSearchTerm(Name, name, SearchTerm::CondContains); +} + diff --git a/src/core/searchquery.h b/src/core/searchquery.h index 017a3f6a0..059b626a2 100644 --- a/src/core/searchquery.h +++ b/src/core/searchquery.h @@ -1,348 +1,354 @@ /* Copyright (c) 2014 Daniel Vrátil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_SEARCHQUERY_H #define AKONADI_SEARCHQUERY_H #include #include "akonadicore_export.h" namespace Akonadi { /** * Search term represents the actual condition within query. * * SearchTerm can either have multiple subterms, or can be so-called endterm, when * there are no more subterms, but instead the actual condition is specified, that * is have key, value and relation between them. * * @since 4.13 */ class AKONADICORE_EXPORT SearchTerm { public: enum Relation { RelAnd, RelOr }; enum Condition { CondEqual, CondGreaterThan, CondGreaterOrEqual, CondLessThan, CondLessOrEqual, CondContains }; enum SearchField { Unknown = 0, ///< Invalid search field Collection = 1 ///< Match entities from given Collection (expects Collection ID (qint64)) }; /** * Constructs a term where all subterms will be in given relation */ explicit SearchTerm(SearchTerm::Relation relation = SearchTerm::RelAnd); /** * Constructs an end term */ SearchTerm(const QString &key, const QVariant &value, SearchTerm::Condition condition = SearchTerm::CondEqual); SearchTerm(SearchField field, const QVariant &value, SearchTerm::Condition condition = SearchTerm::CondEqual); SearchTerm(const SearchTerm &other); ~SearchTerm(); SearchTerm &operator=(const SearchTerm &other); Q_REQUIRED_RESULT bool operator==(const SearchTerm &other) const; Q_REQUIRED_RESULT bool isNull() const; /** * Returns key of this end term. */ Q_REQUIRED_RESULT QString key() const; /** * Returns value of this end term. */ Q_REQUIRED_RESULT QVariant value() const; /** * Returns relation between key and value. */ Q_REQUIRED_RESULT SearchTerm::Condition condition() const; /** * Adds a new subterm to this term. * * Subterms will be in relation as specified in SearchTerm constructor. * * If there are subterms in a term, key, value and condition are ignored. */ void addSubTerm(const SearchTerm &term); /** * Returns all subterms, or an empty list if this is an end term. */ Q_REQUIRED_RESULT QList subTerms() const; /** * Returns relation in which all subterms are. */ Q_REQUIRED_RESULT SearchTerm::Relation relation() const; /** * Sets whether the entire term is negated. */ void setIsNegated(bool negated); /** * Returns whether the entire term is negated. */ Q_REQUIRED_RESULT bool isNegated() const; static QString toKey(SearchField field); static SearchField fromKey(const QString &key); + static SearchTerm inCollection(qint64 collection); + private: class Private; QSharedDataPointer d; }; /** * @brief A query that can be passed to ItemSearchJob or others. * * @since 4.13 */ class AKONADICORE_EXPORT SearchQuery { public: /** * Constructs query where all added terms will be in given relation */ explicit SearchQuery(SearchTerm::Relation rel = SearchTerm::RelAnd); ~SearchQuery(); SearchQuery(const SearchQuery &other); SearchQuery &operator=(const SearchQuery &other); bool operator==(const SearchQuery &other) const; bool isNull() const; /** * Adds a new term. */ void addTerm(const QString &key, const QVariant &value, SearchTerm::Condition condition = SearchTerm::CondEqual); /** * Adds a new term with subterms */ void addTerm(const SearchTerm &term); /** * Sets the root term */ void setTerm(const SearchTerm &term); /** * Returns the root term. */ SearchTerm term() const; /** * Sets the maximum number of results. * * Note that this limit is only evaluated per search backend, * so the total number of results retrieved may be larger. */ void setLimit(int limit); /** * Returns the maximum number of results. * * The default value is -1, indicating no limit. */ int limit() const; QByteArray toJSON() const; static SearchQuery fromJSON(const QByteArray &json); private: class Private; QSharedDataPointer d; }; /** * A search term for an email field. * * This class can be used to create queries that akonadi email search backends understand. * * @since 4.13 */ class AKONADICORE_EXPORT EmailSearchTerm : public SearchTerm { public: /** * All fields expect a search string unless noted otherwise. */ enum EmailSearchField { Subject = 100, ///< Search in the subject field (expects QString) Body, ///< Search in the email body (expects QString) Headers, ///< @deprecated Will be removed HeaderFrom, ///< Search in the From header (expects QString) HeaderTo, ///< Search in the To header (expects QString) HeaderCC, ///< Search in the CC header (expects QString) HeaderBCC, ///< Search in the BCC header (expects QString) HeaderReplyTo, ///< Search in the ReplyTo header (expects QString) HeaderOrganization, ///< Search in the Organization header (expects QString) HeaderListId, ///< Search in the ListId header (expects QString) HeaderResentFrom, ///< @deprecated Will be removed HeaderXLoop, ///< @deprecated Will be removed HeaderXMailingList, ///< @deprecated Will be removed HeaderXSpamFlag, ///< @deprecated Will be removed HeaderDate, ///< Match by the Date header (expects QDateTime) HeaderOnlyDate, ///< Match by the Date header, but only by date (expects QDate) MessageStatus, ///< Match by message flags (expects Akonadi::MessageFlag), boolean filter. ByteSize, ///< Match by message size (expects integer) AttachmentName, ///< Search in attachment names (expects QString) Attachment, ///< Search in bodies of plaintext attachments (expects QString) Message, ///< Search in all the QString-based fields listed above MessageTag ///< @deprecated Will be removed }; /** * Constructs an email end term */ EmailSearchTerm(EmailSearchField field, const QVariant &value, SearchTerm::Condition condition = SearchTerm::CondEqual); /** * Translates field to key */ static QString toKey(EmailSearchField); /** * Translates key to field */ static EmailSearchField fromKey(const QString &key); static SearchTerm from(const QStringList &from, SearchTerm::Relation rel = SearchTerm::RelOr); static SearchTerm to(const QStringList &to, SearchTerm::Relation rel = SearchTerm::RelOr); static SearchTerm cc(const QStringList &cc, SearchTerm::Relation rel = SearchTerm::RelOr); static SearchTerm bcc(const QStringList &bcc, SearchTerm::Relation rel = SearchTerm::RelOr); static SearchTerm involves(const QStringList &involves, SearchTerm::Relation rel = SearchTerm::RelOr); static SearchTerm isRead(bool isRead = true); static SearchTerm isImportant(bool isImportant = true); static SearchTerm hasAttachment(bool hasAttachment = true); static SearchTerm matches(const QString &match); static SearchTerm subjectMatches(const QString &subject); static SearchTerm bodyMatches(const QString &bodyMatches); }; /** * A search term for a contact field. * * This class can be used to create queries that akonadi contact search backends understand. * * @since 4.13 */ class AKONADICORE_EXPORT ContactSearchTerm : public SearchTerm { public: enum ContactSearchField { Name = 200, ///< Search by full name (expects QString) Email, ///< Search by email address (expects QString) Nickname, ///< Search by nickname (expects QString) Uid, ///< Search by vCard UID (expects QString) Birthday, ///< Match by birthday (expects QDate) Anniversary, ///< Match by anniversary (expects QDate) All ///< Matches all contacts regardless of value }; ContactSearchTerm(ContactSearchField field, const QVariant &value, SearchTerm::Condition condition = SearchTerm::CondEqual); /** * Translates field to key */ static QString toKey(ContactSearchField); /** * Translates key to field */ static ContactSearchField fromKey(const QString &key); }; /** * A search term for a incidence field. * * This class can be used to create queries that akonadi incidence search backends understand. * * @since 5.0 */ class AKONADICORE_EXPORT IncidenceSearchTerm : public SearchTerm { public: enum IncidenceSearchField { All = 300, ///< Matches all events regardless of value PartStatus, ///< Match events based on participant status Organizer, ///< Search by incidence organizer name or email Summary, ///< Search by incidence summary Location ///< Search by incidence location }; IncidenceSearchTerm(IncidenceSearchField field, const QVariant &value, SearchTerm::Condition condition = SearchTerm::CondEqual); /** * Translates field to key */ static QString toKey(IncidenceSearchField); /** * Translates key to field */ static IncidenceSearchField fromKey(const QString &key); }; /** * A search term for Collections. */ class AKONADICORE_EXPORT CollectionSearchTerm : public SearchTerm { public: enum CollectionSearchField { Name = 400, ///< Search by collection name Namespace, ///< Search by collection namespace Identification, ///< Search by additional collection identification MimeType ///< Search by collection mimetype }; CollectionSearchTerm(CollectionSearchField field, const QVariant &value, SearchTerm::Condition condition = SearchTerm::CondEqual); static QString toKey(CollectionSearchField field); static CollectionSearchField fromKey(const QString &key); + + static SearchTerm nameMatches(const QString &name); + static SearchTerm hasNamespaces(const QStringList &namespaces); + static SearchTerm hasMimeTypes(const QStringList &mimeTypes); }; } #endif // AKONADI_SEARCHQUERY_H