Warning, file /pim/akonadi-search/agent/contactindexer.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * This file is part of the KDE Akonadi Search Project 0003 * SPDX-FileCopyrightText: 2013 Vishesh Handa <me@vhanda.in> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 * 0007 */ 0008 0009 #include "contactindexer.h" 0010 #include "akonadi_indexer_agent_debug.h" 0011 #include "xapiandocument.h" 0012 0013 #include <Akonadi/Collection> 0014 #include <KContacts/Addressee> 0015 #include <KContacts/ContactGroup> 0016 0017 ContactIndexer::ContactIndexer(const QString &path) 0018 : AbstractIndexer() 0019 { 0020 try { 0021 m_db = new Akonadi::Search::XapianDatabase(path, true); 0022 } catch (const Xapian::DatabaseCorruptError &err) { 0023 qCWarning(AKONADI_INDEXER_AGENT_LOG) << "Database Corrupted - What did you do?"; 0024 qCWarning(AKONADI_INDEXER_AGENT_LOG) << err.get_error_string(); 0025 m_db = nullptr; 0026 } catch (const Xapian::Error &e) { 0027 qCWarning(AKONADI_INDEXER_AGENT_LOG) << QString::fromStdString(e.get_type()) << QString::fromStdString(e.get_description()); 0028 m_db = nullptr; 0029 } 0030 } 0031 0032 ContactIndexer::~ContactIndexer() 0033 { 0034 commit(); 0035 delete m_db; 0036 } 0037 0038 QStringList ContactIndexer::mimeTypes() const 0039 { 0040 return QStringList() << KContacts::Addressee::mimeType() << KContacts::ContactGroup::mimeType(); 0041 } 0042 0043 bool ContactIndexer::indexContact(const Akonadi::Item &item) 0044 { 0045 if (!m_db) { 0046 return false; 0047 } 0048 KContacts::Addressee addressee; 0049 try { 0050 addressee = item.payload<KContacts::Addressee>(); 0051 } catch (const Akonadi::PayloadException &) { 0052 return false; 0053 } 0054 0055 Akonadi::Search::XapianDocument doc; 0056 0057 QString name; 0058 if (!addressee.formattedName().isEmpty()) { 0059 name = addressee.formattedName(); 0060 } else if (!addressee.assembledName().isEmpty()) { 0061 name = addressee.assembledName(); 0062 } else { 0063 name = addressee.name(); 0064 } 0065 0066 qCDebug(AKONADI_INDEXER_AGENT_LOG) << "Indexing" << name << addressee.nickName(); 0067 0068 doc.indexText(name); 0069 doc.indexText(addressee.nickName()); 0070 doc.indexText(addressee.uid(), QStringLiteral("UID")); 0071 0072 doc.indexText(name, QStringLiteral("NA")); 0073 doc.indexText(addressee.nickName(), QStringLiteral("NI")); 0074 0075 const QStringList lstEmails = addressee.emails(); 0076 for (const QString &email : lstEmails) { 0077 doc.addTerm(email); 0078 doc.indexText(email); 0079 } 0080 0081 // Parent collection 0082 Q_ASSERT_X(item.parentCollection().isValid(), "Akonadi::Search::ContactIndexer::index", "Item does not have a valid parent collection"); 0083 0084 const Akonadi::Collection::Id colId = item.parentCollection().id(); 0085 doc.addBoolTerm(colId, QStringLiteral("C")); 0086 0087 if (addressee.birthday().isValid()) { 0088 const QString julianDay = QString::number(addressee.birthday().date().toJulianDay()); 0089 doc.addValue(0, julianDay); 0090 } 0091 // TODO index anniversary ? 0092 0093 m_db->replaceDocument(item.id(), doc); 0094 return true; 0095 } 0096 0097 void ContactIndexer::indexContactGroup(const Akonadi::Item &item) 0098 { 0099 if (!m_db) { 0100 return; 0101 } 0102 KContacts::ContactGroup group; 0103 try { 0104 group = item.payload<KContacts::ContactGroup>(); 0105 } catch (const Akonadi::PayloadException &) { 0106 return; 0107 } 0108 0109 Akonadi::Search::XapianDocument doc; 0110 0111 const QString name = group.name(); 0112 doc.indexText(name); 0113 doc.indexText(name, QStringLiteral("NA")); 0114 0115 // Parent collection 0116 Q_ASSERT_X(item.parentCollection().isValid(), "Akonadi::Search::ContactIndexer::index", "Item does not have a valid parent collection"); 0117 0118 const Akonadi::Collection::Id colId = item.parentCollection().id(); 0119 doc.addBoolTerm(colId, QStringLiteral("C")); 0120 m_db->replaceDocument(item.id(), doc); 0121 } 0122 0123 void ContactIndexer::index(const Akonadi::Item &item) 0124 { 0125 if (!indexContact(item)) { 0126 indexContactGroup(item); 0127 } 0128 } 0129 0130 void ContactIndexer::remove(const Akonadi::Item &item) 0131 { 0132 if (m_db) { 0133 m_db->deleteDocument(item.id()); 0134 } 0135 } 0136 0137 void ContactIndexer::remove(const Akonadi::Collection &collection) 0138 { 0139 if (!m_db) { 0140 return; 0141 } 0142 try { 0143 Xapian::Database *db = m_db->db(); 0144 Xapian::Query query('C' + QString::number(collection.id()).toStdString()); 0145 Xapian::Enquire enquire(*db); 0146 enquire.set_query(query); 0147 0148 Xapian::MSet mset = enquire.get_mset(0, db->get_doccount()); 0149 Xapian::MSetIterator end(mset.end()); 0150 for (Xapian::MSetIterator it = mset.begin(); it != end; ++it) { 0151 const qint64 id = *it; 0152 remove(Akonadi::Item(id)); 0153 } 0154 } catch (const Xapian::DocNotFoundError &) { 0155 return; 0156 } 0157 } 0158 0159 void ContactIndexer::commit() 0160 { 0161 if (!m_db) { 0162 return; 0163 } 0164 0165 try { 0166 m_db->commit(); 0167 } catch (const Xapian::Error &err) { 0168 qCWarning(AKONADI_INDEXER_AGENT_LOG) << err.get_error_string(); 0169 } 0170 qCDebug(AKONADI_INDEXER_AGENT_LOG) << "Xapian Committed"; 0171 } 0172 0173 void ContactIndexer::move(Akonadi::Item::Id itemId, Akonadi::Collection::Id from, Akonadi::Collection::Id to) 0174 { 0175 if (!m_db) { 0176 return; 0177 } 0178 0179 Akonadi::Search::XapianDocument doc; 0180 try { 0181 doc = m_db->document(itemId); 0182 } catch (const Xapian::DocNotFoundError &) { 0183 return; 0184 } 0185 0186 const QByteArray ft = 'C' + QByteArray::number(from); 0187 const QByteArray tt = 'C' + QByteArray::number(to); 0188 0189 doc.removeTermStartsWith(ft.data()); 0190 doc.addBoolTerm(QString::fromLatin1(tt.data())); 0191 m_db->replaceDocument(doc.doc().get_docid(), doc); 0192 }