File indexing completed on 2024-05-19 05:11:52

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 <xapian.h>
0010 
0011 #include "akonadi_search_pim_debug.h"
0012 #include "notequery.h"
0013 #include "resultiterator_p.h"
0014 
0015 #include <QDebug>
0016 #include <QFile>
0017 #include <QList>
0018 #include <QStandardPaths>
0019 
0020 using namespace Akonadi::Search::PIM;
0021 
0022 class Akonadi::Search::PIM::NoteQueryPrivate
0023 {
0024 public:
0025     NoteQueryPrivate() = default;
0026 
0027     QString title;
0028     QString note;
0029     int limit = 0;
0030 };
0031 
0032 NoteQuery::NoteQuery()
0033     : Query()
0034     , d(new NoteQueryPrivate)
0035 {
0036 }
0037 
0038 NoteQuery::~NoteQuery() = default;
0039 
0040 void NoteQuery::matchTitle(const QString &title)
0041 {
0042     d->title = title;
0043 }
0044 
0045 void NoteQuery::matchNote(const QString &note)
0046 {
0047     d->note = note;
0048 }
0049 
0050 void NoteQuery::setLimit(int limit)
0051 {
0052     d->limit = limit;
0053 }
0054 
0055 int NoteQuery::limit() const
0056 {
0057     return d->limit;
0058 }
0059 
0060 ResultIterator NoteQuery::exec()
0061 {
0062     const QString dir = defaultLocation(QStringLiteral("notes"));
0063 
0064     Xapian::Database db;
0065     try {
0066         db = Xapian::Database(QFile::encodeName(dir).toStdString());
0067     } catch (const Xapian::DatabaseOpeningError &) {
0068         qCWarning(AKONADI_SEARCH_PIM_LOG) << "Xapian Database does not exist at " << dir;
0069         return {};
0070     } catch (const Xapian::DatabaseCorruptError &) {
0071         qCWarning(AKONADI_SEARCH_PIM_LOG) << "Xapian Database corrupted";
0072         return {};
0073     } catch (const Xapian::DatabaseError &e) {
0074         qCWarning(AKONADI_SEARCH_PIM_LOG) << "Failed to open Xapian database:" << QString::fromStdString(e.get_error_string());
0075         return {};
0076     } catch (...) {
0077         qCWarning(AKONADI_SEARCH_PIM_LOG) << "Random exception, but we do not want to crash";
0078         return {};
0079     }
0080 
0081     QList<Xapian::Query> m_queries;
0082 
0083     if (!d->note.isEmpty()) {
0084         Xapian::QueryParser parser;
0085         parser.set_database(db);
0086         parser.add_prefix("", "BO");
0087 
0088         const QByteArray baNote = d->note.toUtf8();
0089         m_queries << parser.parse_query(baNote.constData(), Xapian::QueryParser::FLAG_PARTIAL);
0090     }
0091 
0092     if (!d->title.isEmpty()) {
0093         Xapian::QueryParser parser;
0094         parser.set_database(db);
0095         parser.add_prefix("", "SU");
0096         parser.set_default_op(Xapian::Query::OP_AND);
0097 
0098         const QByteArray baTitle = d->title.toUtf8();
0099         m_queries << parser.parse_query(baTitle.constData(), Xapian::QueryParser::FLAG_PARTIAL);
0100     }
0101     try {
0102         Xapian::Query query(Xapian::Query::OP_OR, m_queries.begin(), m_queries.end());
0103         // qDebug() << query.get_description().c_str();
0104 
0105         Xapian::Enquire enquire(db);
0106         enquire.set_query(query);
0107 
0108         if (d->limit == 0) {
0109             d->limit = 10000;
0110         }
0111 
0112         Xapian::MSet matches = enquire.get_mset(0, d->limit);
0113 
0114         ResultIterator iter;
0115         iter.d->init(matches);
0116         return iter;
0117     } catch (const Xapian::Error &e) {
0118         qCWarning(AKONADI_SEARCH_PIM_LOG) << QString::fromStdString(e.get_type()) << QString::fromStdString(e.get_description());
0119         return {};
0120     }
0121 }