8#include <QtCore/qmap.h>
9#include <QtCore/qset.h>
10#include <QtSql/qsqldatabase.h>
11#include <QtSql/qsqlquery.h>
15using namespace Qt::StringLiterals;
25 m_namespaceAttributes.clear();
26 m_filterEngineNamespaceList.clear();
27 m_useFilterEngine =
false;
31 m_namespaceAttributes.insert(namespaceName, attributes);
35 m_useFilterEngine =
true;
36 m_filterEngineNamespaceList = namespaceList;
43 QList<QHelpSearchResult> queryTable(
const QSqlDatabase &db,
const QString &tableName,
44 const QString &searchInput)
const;
46 QMultiMap<QString, QStringList> m_namespaceAttributes;
47 QStringList m_filterEngineNamespaceList;
48 QList<QHelpSearchResult> m_searchResults;
50 bool m_useFilterEngine =
false;
56 const auto &namespaceList = namespaces.uniqueKeys();
58 for (
const QString &ns : namespaceList) {
62 placeholders +=
" OR "_L1;
63 placeholders +=
"(namespace = ?"_L1;
65 const QList<QStringList> &attributeSets = namespaces.values(ns);
67 for (
const QStringList &attributeSet : attributeSets) {
68 if (!attributeSet.isEmpty()) {
71 placeholders +=
" AND ("_L1;
73 placeholders +=
" OR "_L1;
75 placeholders +=
"attributes = ?"_L1;
86 const QMultiMap<QString, QStringList> &namespaces)
88 const auto &namespaceList = namespaces.uniqueKeys();
89 for (
const QString &ns : namespaceList) {
90 query->addBindValue(ns);
92 const QList<QStringList> &attributeSets = namespaces.values(ns);
93 for (
const QStringList &attributeSet : attributeSets) {
94 if (!attributeSet.isEmpty())
95 query->addBindValue(attributeSet.join(u'|'));
102 QString placeholders;
104 for (
int i = namespaceList.size(); i; --i) {
108 placeholders +=
" OR "_L1;
109 placeholders +=
"namespace = ?"_L1;
116 for (
const QString &ns : namespaceList)
117 query->addBindValue(ns);
120QList<QHelpSearchResult>
Reader::queryTable(
const QSqlDatabase &db,
const QString &tableName,
121 const QString &searchInput)
const
123 const QString nsPlaceholders = m_useFilterEngine
124 ? namespacePlaceholders(m_filterEngineNamespaceList)
125 : namespacePlaceholders(m_namespaceAttributes);
127 query.prepare(
"SELECT url, title, snippet("_L1 + tableName +
128 ", -1, '<b>', '</b>', '...', '10') FROM "_L1 + tableName +
129 " WHERE ("_L1 + nsPlaceholders +
130 ") AND "_L1 + tableName +
131 " MATCH ? ORDER BY rank"_L1);
133 ? bindNamespacesAndAttributes(&query, m_filterEngineNamespaceList)
134 : bindNamespacesAndAttributes(&query, m_namespaceAttributes);
135 query.addBindValue(searchInput);
138 QList<QHelpSearchResult> results;
140 while (query.next()) {
141 const QString &url = query.value(
"url"_L1).toString();
142 const QString &title = query.value(
"title"_L1).toString();
143 const QString &snippet = query.value(2).toString();
144 results.append(QHelpSearchResult(url, title, snippet));
151 const QString &uniqueId = QHelpGlobal::uniquifyConnectionName(
"QHelpReader"_L1,
this);
153 QSqlDatabase db = QSqlDatabase::addDatabase(
"QSQLITE"_L1, uniqueId);
154 db.setConnectOptions(
"QSQLITE_OPEN_READONLY"_L1);
155 db.setDatabaseName(m_indexPath +
"/fts"_L1);
158 const QList<QHelpSearchResult> titleResults = queryTable(db,
"titles"_L1, searchInput);
159 const QList<QHelpSearchResult> contentResults =
160 queryTable(db,
"contents"_L1, searchInput);
163 m_searchResults.clear();
165 for (
const QHelpSearchResult &result : titleResults) {
166 const auto size = urls.size();
167 urls.insert(result.url());
168 if (size != urls.size())
169 m_searchResults.append(result);
171 for (
const QHelpSearchResult &result : contentResults) {
172 const auto size = urls.size();
173 urls.insert(result.url());
174 if (size != urls.size())
175 m_searchResults.append(result);
179 QSqlDatabase::removeDatabase(uniqueId);
184 for (
const QString &attribute : filter) {
185 if (!attributes.contains(attribute, Qt::CaseInsensitive))
199 QMutexLocker lock(&m_mutex);
204 const QString &searchInput,
bool usesFilterEngine)
208 m_searchResults.clear();
210 m_searchInput = searchInput;
211 m_collectionFile = collectionFile;
212 m_indexFilesFolder = indexFilesFolder;
213 m_usesFilterEngine = usesFilterEngine;
215 start(QThread::NormalPriority);
220 QMutexLocker lock(&m_mutex);
221 return m_searchResults.size();
226 QMutexLocker lock(&m_mutex);
227 return m_searchResults.mid(start, end - start);
232 QMutexLocker lock(&m_mutex);
237 const QString searchInput = m_searchInput;
238 const QString collectionFile = m_collectionFile;
239 const QString indexPath = m_indexFilesFolder;
240 const bool usesFilterEngine = m_usesFilterEngine;
244 QHelpEngineCore engine(collectionFile,
nullptr);
245 if (!engine.setupData())
248 emit searchingStarted();
254 if (usesFilterEngine) {
255 reader.setFilterEngineNamespaceList(
256 engine.filterEngine()->namespacesForFilter(engine.filterEngine()->activeFilter()));
258 const QStringList ®isteredDocs = engine.registeredDocumentations();
259 const QStringList ¤tFilter = engine.filterAttributes(engine.currentFilter());
261 for (
const QString &namespaceName : registeredDocs) {
262 const QList<QStringList> &attributeSets =
263 engine.filterAttributeSets(namespaceName);
265 for (
const QStringList &attributes : attributeSets) {
266 if (attributesMatchFilter(attributes, currentFilter))
267 reader.addNamespaceAttributes(namespaceName, attributes);
275 emit searchingFinished();
278 m_searchResults.clear();
284 m_searchResults = reader.searchResults();
287 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)