9#include <QtCore/qmap.h>
10#include <QtCore/qset.h>
11#include <QtSql/qsqldatabase.h>
12#include <QtSql/qsqlquery.h>
16using namespace Qt::StringLiterals;
26 m_namespaceAttributes.clear();
27 m_filterEngineNamespaceList.clear();
28 m_useFilterEngine =
false;
32 m_namespaceAttributes.insert(namespaceName, attributes);
36 m_useFilterEngine =
true;
37 m_filterEngineNamespaceList = namespaceList;
44 QList<QHelpSearchResult> queryTable(
const QSqlDatabase &db,
const QString &tableName,
45 const QString &searchInput)
const;
47 QMultiMap<QString, QStringList> m_namespaceAttributes;
48 QStringList m_filterEngineNamespaceList;
49 QList<QHelpSearchResult> m_searchResults;
51 bool m_useFilterEngine =
false;
57 const auto &namespaceList = namespaces.uniqueKeys();
59 for (
const QString &ns : namespaceList) {
63 placeholders +=
" OR "_L1;
64 placeholders +=
"(namespace = ?"_L1;
66 const QList<QStringList> &attributeSets = namespaces.values(ns);
68 for (
const QStringList &attributeSet : attributeSets) {
69 if (!attributeSet.isEmpty()) {
72 placeholders +=
" AND ("_L1;
74 placeholders +=
" OR "_L1;
76 placeholders +=
"attributes = ?"_L1;
87 const QMultiMap<QString, QStringList> &namespaces)
89 const auto &namespaceList = namespaces.uniqueKeys();
90 for (
const QString &ns : namespaceList) {
91 query->addBindValue(ns);
93 const QList<QStringList> &attributeSets = namespaces.values(ns);
94 for (
const QStringList &attributeSet : attributeSets) {
95 if (!attributeSet.isEmpty())
96 query->addBindValue(attributeSet.join(u'|'));
103 QString placeholders;
105 for (
int i = namespaceList.size(); i; --i) {
109 placeholders +=
" OR "_L1;
110 placeholders +=
"namespace = ?"_L1;
117 for (
const QString &ns : namespaceList)
118 query->addBindValue(ns);
121QList<QHelpSearchResult>
Reader::queryTable(
const QSqlDatabase &db,
const QString &tableName,
122 const QString &searchInput)
const
124 const QString nsPlaceholders = m_useFilterEngine
125 ? namespacePlaceholders(m_filterEngineNamespaceList)
126 : namespacePlaceholders(m_namespaceAttributes);
128 query.prepare(
"SELECT url, title, snippet("_L1 + tableName +
129 ", -1, '<b>', '</b>', '...', '10') FROM "_L1 + tableName +
130 " WHERE ("_L1 + nsPlaceholders +
131 ") AND "_L1 + tableName +
132 " MATCH ? ORDER BY rank"_L1);
134 ? bindNamespacesAndAttributes(&query, m_filterEngineNamespaceList)
135 : bindNamespacesAndAttributes(&query, m_namespaceAttributes);
136 query.addBindValue(searchInput);
139 QList<QHelpSearchResult> results;
141 while (query.next()) {
142 const QString &url = query.value(
"url"_L1).toString();
143 const QString &title = query.value(
"title"_L1).toString();
144 const QString &snippet = query.value(2).toString();
145 results.append(QHelpSearchResult(QUrl(url), title, snippet));
152 const QString &uniqueId = QHelpGlobal::uniquifyConnectionName(
"QHelpReader"_L1,
this);
154 QSqlDatabase db = QSqlDatabase::addDatabase(
"QSQLITE"_L1, uniqueId);
155 db.setConnectOptions(
"QSQLITE_OPEN_READONLY"_L1);
156 db.setDatabaseName(m_indexPath +
"/fts"_L1);
159 const QList<QHelpSearchResult> titleResults = queryTable(db,
"titles"_L1, searchInput);
160 const QList<QHelpSearchResult> contentResults =
161 queryTable(db,
"contents"_L1, searchInput);
164 m_searchResults.clear();
166 for (
const QHelpSearchResult &result : titleResults) {
167 const auto size = urls.size();
168 urls.insert(result.url());
169 if (size != urls.size())
170 m_searchResults.append(result);
172 for (
const QHelpSearchResult &result : contentResults) {
173 const auto size = urls.size();
174 urls.insert(result.url());
175 if (size != urls.size())
176 m_searchResults.append(result);
180 QSqlDatabase::removeDatabase(uniqueId);
185 for (
const QString &attribute : filter) {
186 if (!attributes.contains(attribute, Qt::CaseInsensitive))
200 QMutexLocker lock(&m_mutex);
205 const QString &searchInput,
bool usesFilterEngine)
209 m_searchResults.clear();
211 m_searchInput = searchInput;
212 m_collectionFile = collectionFile;
213 m_indexFilesFolder = indexFilesFolder;
214 m_usesFilterEngine = usesFilterEngine;
216 start(QThread::NormalPriority);
221 QMutexLocker lock(&m_mutex);
222 return m_searchResults.size();
227 QMutexLocker lock(&m_mutex);
228 return m_searchResults.mid(start, end - start);
233 QMutexLocker lock(&m_mutex);
238 const QString searchInput = m_searchInput;
239 const QString collectionFile = m_collectionFile;
240 const QString indexPath = m_indexFilesFolder;
241 const bool usesFilterEngine = m_usesFilterEngine;
245 QHelpEngineCore engine(collectionFile,
nullptr);
246 if (!engine.setupData())
249 emit searchingStarted();
255 if (usesFilterEngine) {
256 reader.setFilterEngineNamespaceList(
257 engine.filterEngine()->namespacesForFilter(engine.filterEngine()->activeFilter()));
259 const QStringList ®isteredDocs = engine.registeredDocumentations();
260 const QStringList ¤tFilter = engine.filterAttributes(engine.currentFilter());
262 for (
const QString &namespaceName : registeredDocs) {
263 const QList<QStringList> &attributeSets =
264 engine.filterAttributeSets(namespaceName);
266 for (
const QStringList &attributes : attributeSets) {
267 if (attributesMatchFilter(attributes, currentFilter))
268 reader.addNamespaceAttributes(namespaceName, attributes);
276 emit searchingFinished();
279 m_searchResults.clear();
285 m_searchResults = reader.searchResults();
288 emit searchingFinished();
int searchResultCount() const
void search(const QString &collectionFile, const QString &indexFilesFolder, const QString &searchInput, bool usesFilterEngine=false)
QList< QHelpSearchResult > searchResults(int start, int end) const
QList< QHelpSearchResult > searchResults() const
void searchInDB(const QString &term)
void setIndexPath(const QString &path)
void addNamespaceAttributes(const QString &namespaceName, const QStringList &attributes)
void setFilterEngineNamespaceList(const QStringList &namespaceList)
Combined button and popup list for selecting options.
static bool attributesMatchFilter(const QStringList &attributes, const QStringList &filter)
static void bindNamespacesAndAttributes(QSqlQuery *query, const QMultiMap< QString, QStringList > &namespaces)
static QString namespacePlaceholders(const QMultiMap< QString, QStringList > &namespaces)