Akonadi Search

contactquery.cpp
1/*
2 * This file is part of the KDE Akonadi Search Project
3 * SPDX-FileCopyrightText: 2013 Vishesh Handa <me@vhanda.in>
4 *
5 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6 *
7 */
8
9#include <xapian.h>
10
11#include "akonadi_search_pim_debug.h"
12#include "contactquery.h"
13#include "resultiterator_p.h"
14
15#include <QFile>
16#include <QList>
17#include <QStandardPaths>
18
19using namespace Akonadi::Search::PIM;
20
21class Akonadi::Search::PIM::ContactQueryPrivate
22{
23public:
24 QString name;
25 QString nick;
26 QString email;
27 QString uid;
28 QString any;
29
30 int limit;
31 ContactQuery::MatchCriteria criteria;
32};
33
34ContactQuery::ContactQuery()
35 : Query()
36 , d(new ContactQueryPrivate)
37{
38 d->criteria = StartsWithMatch;
39}
40
41ContactQuery::~ContactQuery() = default;
42
43void ContactQuery::matchName(const QString &name)
44{
45 d->name = name;
46}
47
48void ContactQuery::matchNickname(const QString &nick)
49{
50 d->nick = nick;
51}
52
53void ContactQuery::matchEmail(const QString &email)
54{
55 d->email = email;
56}
57
58void ContactQuery::matchUID(const QString &uid)
59{
60 d->uid = uid;
61}
62
63void ContactQuery::match(const QString &str)
64{
65 d->any = str;
66}
67
68int ContactQuery::limit() const
69{
70 return d->limit;
71}
72
73void ContactQuery::setLimit(int limit)
74{
75 d->limit = limit;
76}
77
78ContactQuery::MatchCriteria ContactQuery::matchCriteria() const
79{
80 return d->criteria;
81}
82
83void ContactQuery::setMatchCriteria(ContactQuery::MatchCriteria m)
84{
85 d->criteria = m;
86}
87
88ResultIterator ContactQuery::exec()
89{
90 const QString dir = defaultLocation(QStringLiteral("contacts"));
91 Xapian::Database db;
92
93 try {
94 db = Xapian::Database(QFile::encodeName(dir).toStdString());
95 } catch (const Xapian::DatabaseOpeningError &) {
96 qCWarning(AKONADI_SEARCH_PIM_LOG) << "Xapian Database does not exist at " << dir;
97 return {};
98 } catch (const Xapian::DatabaseCorruptError &) {
99 qCWarning(AKONADI_SEARCH_PIM_LOG) << "Xapian Database corrupted";
100 return {};
101 } catch (const Xapian::DatabaseError &e) {
102 qCWarning(AKONADI_SEARCH_PIM_LOG) << "Failed to open Xapian database:" << QString::fromStdString(e.get_error_string());
103 return {};
104 } catch (...) {
105 qCWarning(AKONADI_SEARCH_PIM_LOG) << "Random exception, but we do not want to crash";
106 return {};
107 }
108
109 QList<Xapian::Query> m_queries;
110
111 if (d->criteria == ExactMatch) {
112 if (!d->any.isEmpty()) {
113 const QByteArray ba = d->any.toUtf8();
114 m_queries << Xapian::Query(ba.constData());
115 }
116
117 if (!d->name.isEmpty()) {
118 const QByteArray ba = "NA" + d->name.toUtf8();
119 m_queries << Xapian::Query(ba.constData());
120 }
121
122 if (!d->nick.isEmpty()) {
123 const QByteArray ba = "NI" + d->nick.toUtf8();
124 m_queries << Xapian::Query(ba.constData());
125 }
126
127 if (!d->email.isEmpty()) {
128 const QByteArray ba = d->email.toUtf8();
129 m_queries << Xapian::Query(ba.constData());
130 }
131
132 if (!d->uid.isEmpty()) {
133 const QByteArray ba = "UID" + d->uid.toUtf8();
134 m_queries << Xapian::Query(ba.constData());
135 }
136 } else if (d->criteria == StartsWithMatch) {
137 if (!d->any.isEmpty()) {
138 Xapian::QueryParser parser;
139 parser.set_database(db);
140 const QByteArray ba = d->any.toUtf8();
141 m_queries << parser.parse_query(ba.constData(), Xapian::QueryParser::FLAG_PARTIAL);
142 }
143
144 if (!d->name.isEmpty()) {
145 Xapian::QueryParser parser;
146 parser.set_database(db);
147 parser.add_prefix("", "NA");
148 const QByteArray ba = d->name.toUtf8();
149 m_queries << parser.parse_query(ba.constData(), Xapian::QueryParser::FLAG_PARTIAL);
150 }
151
152 if (!d->nick.isEmpty()) {
153 Xapian::QueryParser parser;
154 parser.set_database(db);
155 parser.add_prefix("", "NI");
156 const QByteArray ba = d->nick.toUtf8();
157 m_queries << parser.parse_query(ba.constData(), Xapian::QueryParser::FLAG_PARTIAL);
158 }
159
160 // FIXME: Check for exact match?
161 if (!d->email.isEmpty()) {
162 Xapian::QueryParser parser;
163 parser.set_database(db);
164 const QByteArray ba = d->email.toUtf8();
165 m_queries << parser.parse_query(ba.constData(), Xapian::QueryParser::FLAG_PARTIAL);
166 }
167
168 if (!d->uid.isEmpty()) {
169 Xapian::QueryParser parser;
170 parser.set_database(db);
171 parser.add_prefix("", "UID");
172 const QByteArray ba = d->uid.toUtf8();
173 m_queries << parser.parse_query(ba.constData(), Xapian::QueryParser::FLAG_PARTIAL);
174 }
175 }
176 try {
177 Xapian::Query query(Xapian::Query::OP_OR, m_queries.begin(), m_queries.end());
178 qCDebug(AKONADI_SEARCH_PIM_LOG) << query.get_description().c_str();
179
180 Xapian::Enquire enquire(db);
181 enquire.set_query(query);
182
183 if (d->limit == 0) {
184 d->limit = 10000;
185 }
186
187 Xapian::MSet matches = enquire.get_mset(0, d->limit);
188
189 ResultIterator iter;
190 iter.d->init(matches);
191 return iter;
192 } catch (const Xapian::Error &e) {
193 qCWarning(AKONADI_SEARCH_PIM_LOG) << QString::fromStdString(e.get_type()) << QString::fromStdString(e.get_description());
194 return {};
195 }
196}
Query base class.
Definition lib/query.h:24
PIM specific search API.
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
KIOCORE_EXPORT QString dir(const QString &fileClass)
QString name(StandardShortcut id)
const char * constData() const const
QByteArray encodeName(const QString &fileName)
iterator begin()
iterator end()
QString fromStdString(const std::string &str)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:15:27 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.