File indexing completed on 2024-05-12 05:11:15
0001 /* 0002 * This file is part of the KDE Akonadi Search Project 0003 * SPDX-FileCopyrightText: 2014-2024 Laurent Montel <montel@kde.org> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 * 0007 */ 0008 0009 #include "calendarindexer.h" 0010 #include "akonadi_indexer_agent_calendar_debug.h" 0011 #include "xapiandocument.h" 0012 0013 #include <KCalendarCore/Attendee> 0014 #include <KCalendarCore/FreeBusy> 0015 0016 CalendarIndexer::CalendarIndexer(const QString &path) 0017 : AbstractIndexer() 0018 { 0019 try { 0020 m_db = std::make_unique<Akonadi::Search::XapianDatabase>(path, true); 0021 } catch (const Xapian::DatabaseCorruptError &err) { 0022 qCWarning(AKONADI_INDEXER_AGENT_CALENDAR_LOG) << "Database Corrupted - What did you do?"; 0023 qCWarning(AKONADI_INDEXER_AGENT_CALENDAR_LOG) << err.get_error_string(); 0024 m_db = nullptr; 0025 } catch (const Xapian::Error &e) { 0026 qCWarning(AKONADI_INDEXER_AGENT_CALENDAR_LOG) << QString::fromStdString(e.get_type()) << QString::fromStdString(e.get_description()); 0027 m_db = nullptr; 0028 } 0029 } 0030 0031 CalendarIndexer::~CalendarIndexer() 0032 { 0033 commit(); 0034 } 0035 0036 QStringList CalendarIndexer::mimeTypes() const 0037 { 0038 return { 0039 KCalendarCore::Event::eventMimeType(), 0040 KCalendarCore::Todo::todoMimeType(), 0041 KCalendarCore::Journal::journalMimeType(), 0042 KCalendarCore::FreeBusy::freeBusyMimeType(), 0043 }; 0044 } 0045 0046 void CalendarIndexer::index(const Akonadi::Item &item) 0047 { 0048 if (item.hasPayload<KCalendarCore::Event::Ptr>()) { 0049 indexEventItem(item, item.payload<KCalendarCore::Event::Ptr>()); 0050 } else if (item.hasPayload<KCalendarCore::Journal::Ptr>()) { 0051 indexJournalItem(item, item.payload<KCalendarCore::Journal::Ptr>()); 0052 } else if (item.hasPayload<KCalendarCore::Todo::Ptr>()) { 0053 indexTodoItem(item, item.payload<KCalendarCore::Todo::Ptr>()); 0054 } else { 0055 return; 0056 } 0057 } 0058 0059 void CalendarIndexer::commit() 0060 { 0061 if (!m_db) { 0062 return; 0063 } 0064 0065 try { 0066 m_db->commit(); 0067 } catch (const Xapian::Error &err) { 0068 qCWarning(AKONADI_INDEXER_AGENT_CALENDAR_LOG) << err.get_error_string(); 0069 } 0070 qCDebug(AKONADI_INDEXER_AGENT_CALENDAR_LOG) << "Xapian Committed"; 0071 } 0072 0073 void CalendarIndexer::remove(const Akonadi::Item &item) 0074 { 0075 if (!m_db) { 0076 return; 0077 } 0078 try { 0079 m_db->deleteDocument(item.id()); 0080 } catch (const Xapian::DocNotFoundError &) { 0081 return; 0082 } 0083 } 0084 0085 void CalendarIndexer::remove(const Akonadi::Collection &collection) 0086 { 0087 if (!m_db) { 0088 return; 0089 } 0090 try { 0091 const Xapian::Query query('C' + QString::number(collection.id()).toStdString()); 0092 Xapian::Enquire enquire(*(m_db->db())); 0093 enquire.set_query(query); 0094 0095 Xapian::MSet mset = enquire.get_mset(0, m_db->db()->get_doccount()); 0096 Xapian::MSetIterator end(mset.end()); 0097 for (Xapian::MSetIterator it = mset.begin(); it != end; ++it) { 0098 const qint64 id = *it; 0099 remove(Akonadi::Item(id)); 0100 } 0101 } catch (const Xapian::DocNotFoundError &) { 0102 return; 0103 } 0104 } 0105 0106 void CalendarIndexer::move(Akonadi::Item::Id itemId, Akonadi::Collection::Id from, Akonadi::Collection::Id to) 0107 { 0108 if (!m_db) { 0109 return; 0110 } 0111 Xapian::Document doc; 0112 try { 0113 doc = m_db->db()->get_document(itemId); 0114 } catch (const Xapian::DocNotFoundError &) { 0115 return; 0116 } 0117 0118 const QByteArray ft = 'C' + QByteArray::number(from); 0119 const QByteArray tt = 'C' + QByteArray::number(to); 0120 0121 doc.remove_term(ft.data()); 0122 doc.add_boolean_term(tt.data()); 0123 m_db->replaceDocument(doc.get_docid(), doc); 0124 } 0125 0126 void CalendarIndexer::indexEventItem(const Akonadi::Item &item, const KCalendarCore::Event::Ptr &event) 0127 { 0128 qCDebug(AKONADI_INDEXER_AGENT_CALENDAR_LOG) << "Indexing calendar event:" << normalizeString(event->summary()) << event->organizer().email(); 0129 0130 Akonadi::Search::XapianDocument doc; 0131 0132 doc.indexText(event->organizer().email(), QStringLiteral("O")); 0133 doc.indexText(normalizeString(event->summary()), QStringLiteral("S")); 0134 doc.indexText(normalizeString(event->location()), QStringLiteral("L")); 0135 const KCalendarCore::Attendee::List attendees = event->attendees(); 0136 for (const KCalendarCore::Attendee &attendee : attendees) { 0137 doc.addBoolTerm(attendee.email() + QString::number(attendee.status()), QStringLiteral("PS")); 0138 } 0139 0140 // Parent collection 0141 Q_ASSERT_X(item.parentCollection().isValid(), "Akonadi::Search::CalenderIndexer::index", "Item does not have a valid parent collection"); 0142 0143 const Akonadi::Collection::Id colId = item.parentCollection().id(); 0144 doc.addBoolTerm(colId, QStringLiteral("C")); 0145 0146 m_db->replaceDocument(item.id(), doc); 0147 } 0148 0149 void CalendarIndexer::indexJournalItem(const Akonadi::Item &item, const KCalendarCore::Journal::Ptr &journal) 0150 { 0151 // TODO 0152 Q_UNUSED(item) 0153 Q_UNUSED(journal) 0154 } 0155 0156 void CalendarIndexer::indexTodoItem(const Akonadi::Item &item, const KCalendarCore::Todo::Ptr &todo) 0157 { 0158 // TODO 0159 Q_UNUSED(item) 0160 Q_UNUSED(todo) 0161 } 0162 0163 void CalendarIndexer::updateIncidenceItem(const KCalendarCore::Incidence::Ptr &calInc) 0164 { 0165 // TODO 0166 Q_UNUSED(calInc) 0167 }