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 Christian Mollekopf <mollekopf@kolabsys.com> 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 "collectionquery.h" 0013 #include "resultiterator_p.h" 0014 #include <QFile> 0015 #include <QList> 0016 0017 #include <QStandardPaths> 0018 0019 using namespace Akonadi::Search::PIM; 0020 0021 class Akonadi::Search::PIM::CollectionQueryPrivate 0022 { 0023 public: 0024 QStringList ns; 0025 QStringList mimeType; 0026 QString nameString; 0027 QString identifierString; 0028 QString pathString; 0029 QString databaseDir; 0030 int limit; 0031 }; 0032 0033 CollectionQuery::CollectionQuery() 0034 : Query() 0035 , d(new CollectionQueryPrivate) 0036 { 0037 d->databaseDir = defaultLocation(QStringLiteral("collections")); 0038 d->limit = 0; 0039 } 0040 0041 CollectionQuery::~CollectionQuery() = default; 0042 0043 void CollectionQuery::setDatabaseDir(const QString &dir) 0044 { 0045 d->databaseDir = dir; 0046 } 0047 0048 void CollectionQuery::nameMatches(const QString &match) 0049 { 0050 d->nameString = match; 0051 } 0052 0053 void CollectionQuery::identifierMatches(const QString &match) 0054 { 0055 d->identifierString = match; 0056 } 0057 0058 void CollectionQuery::pathMatches(const QString &match) 0059 { 0060 d->pathString = match; 0061 } 0062 0063 void CollectionQuery::setNamespace(const QStringList &ns) 0064 { 0065 d->ns = ns; 0066 } 0067 0068 void CollectionQuery::setMimetype(const QStringList &mt) 0069 { 0070 d->mimeType = mt; 0071 } 0072 0073 void CollectionQuery::setLimit(int limit) 0074 { 0075 d->limit = limit; 0076 } 0077 0078 ResultIterator CollectionQuery::exec() 0079 { 0080 Xapian::Database db; 0081 try { 0082 db = Xapian::Database(QFile::encodeName(d->databaseDir).toStdString()); 0083 } catch (const Xapian::DatabaseError &e) { 0084 qCWarning(AKONADI_SEARCH_PIM_LOG) << "Failed to open Xapian database:" << d->databaseDir << "; error:" << QString::fromStdString(e.get_error_string()); 0085 return {}; 0086 } 0087 0088 QList<Xapian::Query> queries; 0089 0090 if (!d->nameString.isEmpty()) { 0091 // qDebug() << "searching by name"; 0092 Xapian::QueryParser parser; 0093 parser.set_database(db); 0094 parser.add_prefix("", "N"); 0095 parser.set_default_op(Xapian::Query::OP_AND); 0096 queries << parser.parse_query(d->nameString.toStdString(), Xapian::QueryParser::FLAG_PARTIAL); 0097 } 0098 0099 if (!d->identifierString.isEmpty()) { 0100 Xapian::QueryParser parser; 0101 parser.set_database(db); 0102 parser.add_prefix("", "I"); 0103 parser.set_default_op(Xapian::Query::OP_AND); 0104 queries << parser.parse_query(d->identifierString.toStdString(), Xapian::QueryParser::FLAG_PARTIAL); 0105 } 0106 0107 if (!d->pathString.isEmpty()) { 0108 Xapian::QueryParser parser; 0109 parser.set_database(db); 0110 parser.add_prefix("", "P"); 0111 parser.set_default_op(Xapian::Query::OP_AND); 0112 queries << parser.parse_query(d->pathString.toStdString(), Xapian::QueryParser::FLAG_PARTIAL | Xapian::QueryParser::FLAG_PHRASE); 0113 } 0114 0115 if (!d->ns.isEmpty()) { 0116 QList<Xapian::Query> queryList; 0117 queryList.reserve(d->ns.count()); 0118 for (const QString &n : std::as_const(d->ns)) { 0119 const QByteArray term = "NS" + n.toUtf8(); 0120 queryList << Xapian::Query(term.constData()); 0121 } 0122 queries << Xapian::Query(Xapian::Query::OP_OR, queryList.begin(), queryList.end()); 0123 } 0124 0125 if (!d->mimeType.isEmpty()) { 0126 QList<Xapian::Query> queryList; 0127 queryList.reserve(d->mimeType.count()); 0128 for (const QString &n : std::as_const(d->mimeType)) { 0129 const QByteArray term = "M" + n.toUtf8(); 0130 queryList << Xapian::Query(term.constData()); 0131 } 0132 queries << Xapian::Query(Xapian::Query::OP_OR, queryList.begin(), queryList.end()); 0133 } 0134 0135 Xapian::Query query = Xapian::Query(Xapian::Query::OP_AND, queries.begin(), queries.end()); 0136 0137 if (d->limit == 0) { 0138 d->limit = 1000000; 0139 } 0140 0141 Xapian::Enquire enquire(db); 0142 enquire.set_query(query); 0143 0144 Xapian::MSet mset = enquire.get_mset(0, d->limit); 0145 0146 ResultIterator iter; 0147 iter.d->init(mset); 0148 return iter; 0149 }