File indexing completed on 2024-05-12 05:11:20
0001 /* 0002 * This file is part of the KDE Akonadi Search Project 0003 * SPDX-FileCopyrightText: 2013 Vishesh Handa <me@vhanda.in> 0004 * SPDX-FileCopyrightText: 2014 Christian Mollekopf <mollekopf@kolabsys.com> 0005 * 0006 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 * 0008 */ 0009 #include "pimsearchstore.h" 0010 #include "query.h" 0011 #include "term.h" 0012 0013 #include <Akonadi/ServerManager> 0014 #include <QDir> 0015 #include <QStandardPaths> 0016 #include <QUrl> 0017 #include <QUrlQuery> 0018 0019 using namespace Akonadi::Search; 0020 0021 PIMSearchStore::PIMSearchStore(QObject *parent) 0022 : XapianSearchStore(parent) 0023 { 0024 } 0025 0026 QStringList PIMSearchStore::types() 0027 { 0028 return QStringList() << QStringLiteral("Akonadi"); 0029 } 0030 0031 QString PIMSearchStore::findDatabase(const QString &dbName) const 0032 { 0033 // First look into the old location from Baloo times in ~/.local/share/baloo, 0034 // because we don't migrate the database files automatically. 0035 QString basePath; 0036 bool hasInstanceIdentifier = Akonadi::ServerManager::hasInstanceIdentifier(); 0037 if (hasInstanceIdentifier) { 0038 basePath = QStringLiteral("baloo/instances/%1").arg(Akonadi::ServerManager::instanceIdentifier()); 0039 } else { 0040 basePath = QStringLiteral("baloo"); 0041 } 0042 QString dbPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/%1/%2/").arg(basePath, dbName); 0043 if (QDir(dbPath).exists()) { 0044 return dbPath; 0045 } 0046 0047 // If the database does not exist in old Baloo folders, than use the new 0048 // location in Akonadi's datadir in ~/.local/share/akonadi/search_db. 0049 if (hasInstanceIdentifier) { 0050 basePath = QStringLiteral("akonadi/instance/%1/search_db").arg(Akonadi::ServerManager::instanceIdentifier()); 0051 } else { 0052 basePath = QStringLiteral("akonadi/search_db"); 0053 } 0054 dbPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/%1/%2/").arg(basePath, dbName); 0055 QDir().mkpath(dbPath); 0056 return dbPath; 0057 } 0058 0059 Xapian::Query PIMSearchStore::constructQuery(const QString &property, const QVariant &value, Term::Comparator com) 0060 { 0061 if (value.isNull()) { 0062 return {}; 0063 } 0064 0065 QString prop = property.toLower(); 0066 if (m_boolProperties.contains(prop)) { 0067 QString p = m_prefix.value(prop); 0068 if (p.isEmpty()) { 0069 return {}; 0070 } 0071 0072 std::string term("B"); 0073 bool isTrue = false; 0074 0075 if (value.isNull()) { 0076 isTrue = true; 0077 } 0078 if (value.userType() == QMetaType::Bool) { 0079 isTrue = value.toBool(); 0080 } 0081 0082 if (isTrue) { 0083 term += p.toStdString(); 0084 } else { 0085 term += 'N' + p.toStdString(); 0086 } 0087 0088 return Xapian::Query(term); 0089 } 0090 0091 if (m_boolWithValue.contains(prop)) { 0092 std::string term(m_prefix.value(prop).toStdString()); 0093 std::string val(value.toString().toStdString()); 0094 return Xapian::Query(term + val); 0095 } 0096 0097 if (m_valueProperties.contains(prop) 0098 && (com == Term::Equal || com == Term::Greater || com == Term::GreaterEqual || com == Term::Less || com == Term::LessEqual)) { 0099 qlonglong numVal = value.toLongLong(); 0100 if (com == Term::Greater) { 0101 ++numVal; 0102 } 0103 if (com == Term::Less) { 0104 --numVal; 0105 } 0106 int valueNumber = m_valueProperties.value(prop); 0107 if (com == Term::GreaterEqual || com == Term::Greater) { 0108 return Xapian::Query(Xapian::Query::OP_VALUE_GE, valueNumber, QString::number(numVal).toStdString()); 0109 } else if (com == Term::LessEqual || com == Term::Less) { 0110 return Xapian::Query(Xapian::Query::OP_VALUE_LE, valueNumber, QString::number(numVal).toStdString()); 0111 } else if (com == Term::Equal) { 0112 const Xapian::Query gtQuery(Xapian::Query::OP_VALUE_GE, valueNumber, QString::number(numVal).toStdString()); 0113 const Xapian::Query ltQuery(Xapian::Query::OP_VALUE_LE, valueNumber, QString::number(numVal).toStdString()); 0114 return Xapian::Query(Xapian::Query::OP_AND, gtQuery, ltQuery); 0115 } 0116 } else if ((com == Term::Contains || com == Term::Equal) && m_prefix.contains(prop)) { 0117 Xapian::QueryParser parser; 0118 parser.set_database(*xapianDb()); 0119 0120 std::string p = m_prefix.value(prop).toStdString(); 0121 std::string str(value.toString().toStdString()); 0122 int flags = Xapian::QueryParser::FLAG_DEFAULT; 0123 if (com == Term::Contains) { 0124 flags |= Xapian::QueryParser::FLAG_PARTIAL; 0125 } 0126 return parser.parse_query(str, flags, p); 0127 } 0128 return Xapian::Query(value.toString().toStdString()); 0129 } 0130 0131 QUrl PIMSearchStore::constructUrl(const Xapian::docid &docid) 0132 { 0133 QUrl url; 0134 url.setScheme(QStringLiteral("akonadi")); 0135 0136 QUrlQuery query; 0137 query.addQueryItem(QStringLiteral("item"), QString::number(docid)); 0138 url.setQuery(query); 0139 0140 return url; 0141 } 0142 0143 #include "moc_pimsearchstore.cpp"