1 /****************************************************************************
2 **
3 ** Copyright (C) 2018 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Assistant of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qhelpfilterengine.h"
41 #include "qhelpenginecore.h"
42 #include "qhelpfilterdata.h"
43 #include "qhelpdbreader_p.h"
44 #include "qhelpcollectionhandler_p.h"
45 
46 #include <QtCore/QThread>
47 #include <QtCore/QVersionNumber>
48 
49 QT_BEGIN_NAMESPACE
50 
51 static const char ActiveFilter[] = "activeFilter";
52 
53 class QHelpFilterEnginePrivate
54 {
55 public:
56     bool setup();
57 
58     QHelpFilterEngine *q = nullptr;
59     QHelpEngineCore *m_helpEngine = nullptr;
60     QHelpCollectionHandler *m_collectionHandler = nullptr;
61     QString m_currentFilter;
62     bool m_needsSetup = true;
63 };
64 
setup()65 bool QHelpFilterEnginePrivate::setup()
66 {
67     if (!m_collectionHandler)
68         return false;
69 
70     if (!m_needsSetup)
71         return true;
72 
73     if (!m_helpEngine->setupData())
74         return false;
75 
76     m_needsSetup = false;
77 
78     const QString filter = m_collectionHandler->customValue(
79                 QLatin1String(ActiveFilter), QString()).toString();
80     if (!filter.isEmpty() && m_collectionHandler->filters().contains(filter))
81         m_currentFilter = filter;
82 
83     emit q->filterActivated(m_currentFilter);
84     return true;
85 }
86 
87 //////////////
88 
89 /*!
90     \class QHelpFilterEngine
91     \since 5.13
92     \inmodule QtHelp
93     \brief The QHelpFilterEngine class provides a filtered view of the
94     help contents.
95 
96     The filter engine allows the management of filters associated with
97     a QHelpEngineCore instance. The help engine internally creates an
98     instance of the filter engine, which can be accessed by calling
99     QHelpEngineCore::filterEngine(). Therefore, the public constructor
100     of this class is disabled.
101 
102     The filters are identified by a filter name string. Filter details are
103     described by the \l QHelpFilterData class.
104 
105     The filter engine allows for adding new filters and changing the existing
106     filters' data through the setFilterData() method. An existing filter can
107     be removed through the removeFilter() method.
108 
109     Out of the registered filters one can be marked as the active one.
110     The active filter will be used by the associated help engine for returning
111     filtered results of many different functions, such as content, index, or
112     search results. If no filter is marked active, the help engine returns the
113     full results list available.
114 
115     The active filter is returned by activeFilter() and it can be changed by
116     setActiveFilter().
117 
118     \sa QHelpEngineCore
119 */
120 
121 /*!
122     \fn void QHelpFilterEngine::filterActivated(const QString &newFilter)
123 
124     This signal is emitted when the active filter is set. \a newFilter
125     specifies the name of the filter.
126 
127     \sa setActiveFilter()
128 */
129 
130 /*!
131     \internal
132     Constructs the filter engine for \a helpEngine.
133 */
QHelpFilterEngine(QHelpEngineCore * helpEngine)134 QHelpFilterEngine::QHelpFilterEngine(QHelpEngineCore *helpEngine)
135     : QObject(helpEngine),
136       d(new QHelpFilterEnginePrivate)
137 {
138     d->q = this;
139     d->m_helpEngine = helpEngine;
140 }
141 
142 /*!
143     \internal
144     Destroys the existing filter engine.
145 */
~QHelpFilterEngine()146 QHelpFilterEngine::~QHelpFilterEngine()
147 {
148     delete d;
149 }
150 
151 /*!
152     \internal
153     Sets the \a collectionHandler to be used for this filter engine.
154 */
setCollectionHandler(QHelpCollectionHandler * collectionHandler)155 void QHelpFilterEngine::setCollectionHandler(QHelpCollectionHandler *collectionHandler)
156 {
157     d->m_collectionHandler = collectionHandler;
158     d->m_currentFilter = QString();
159     d->m_needsSetup = true;
160 }
161 
162 /*!
163     Returns the map of all the available namespaces as keys
164     together with their associated components as values.
165 */
namespaceToComponent() const166 QMap<QString, QString> QHelpFilterEngine::namespaceToComponent() const
167 {
168     if (!d->setup())
169         return QMap<QString, QString>();
170     return d->m_collectionHandler->namespaceToComponent();
171 }
172 
173 /*!
174     Returns the map of all the available namespaces as keys
175     together with their associated versions as values.
176 */
namespaceToVersion() const177 QMap<QString, QVersionNumber> QHelpFilterEngine::namespaceToVersion() const
178 {
179     if (!d->setup())
180         return QMap<QString, QVersionNumber>();
181 
182     return d->m_collectionHandler->namespaceToVersion();
183 }
184 
185 /*!
186     Returns the list of all filter names defined inside the filter engine.
187 */
filters() const188 QStringList QHelpFilterEngine::filters() const
189 {
190     if (!d->setup())
191         return QStringList();
192     return d->m_collectionHandler->filters();
193 }
194 
195 /*!
196     Returns the list of all available components defined in all
197     registered documentation files.
198 */
availableComponents() const199 QStringList QHelpFilterEngine::availableComponents() const
200 {
201     if (!d->setup())
202         return QStringList();
203     return d->m_collectionHandler->availableComponents();
204 }
205 
206 /*!
207     \since 5.15
208 
209     Returns the list of all available versions defined in all
210     registered documentation files.
211 */
availableVersions() const212 QList<QVersionNumber> QHelpFilterEngine::availableVersions() const
213 {
214     if (!d->setup())
215         return QList<QVersionNumber>();
216     return d->m_collectionHandler->availableVersions();
217 }
218 
219 /*!
220     Returns the filter details associated with \a filterName.
221 */
filterData(const QString & filterName) const222 QHelpFilterData QHelpFilterEngine::filterData(const QString &filterName) const
223 {
224     if (!d->setup())
225         return QHelpFilterData();
226     return d->m_collectionHandler->filterData(filterName);
227 }
228 
229 /*!
230     Changes the existing filter details of the filter identified by
231     \a filterName to \a filterData. If the filter does not exist, a
232     new filter is created.
233 
234     Returns \c true if setting the filter succeeded, otherwise returns \c false.
235 */
setFilterData(const QString & filterName,const QHelpFilterData & filterData)236 bool QHelpFilterEngine::setFilterData(const QString &filterName, const QHelpFilterData &filterData)
237 {
238     if (!d->setup())
239         return false;
240     return d->m_collectionHandler->setFilterData(filterName, filterData);
241 }
242 
243 /*!
244     Removes the filter identified by \a filterName.
245 
246     Returns \c true if removing the filter succeeded, otherwise returns
247     \c false.
248 */
removeFilter(const QString & filterName)249 bool QHelpFilterEngine::removeFilter(const QString &filterName)
250 {
251     if (!d->setup())
252         return false;
253     return d->m_collectionHandler->removeFilter(filterName);
254 }
255 
256 /*!
257     Returns the name of the currently active filter.
258 */
activeFilter() const259 QString QHelpFilterEngine::activeFilter() const
260 {
261     if (!d->setup())
262         return QString();
263     return d->m_currentFilter;
264 }
265 
266 /*!
267     Changes the currently active filter to \a filterName.
268 
269     Returns \c true if changing the filter succeeded, otherwise
270     returns \c false.
271 */
setActiveFilter(const QString & filterName)272 bool QHelpFilterEngine::setActiveFilter(const QString &filterName)
273 {
274     if (!d->setup())
275         return false;
276 
277     if (filterName == d->m_currentFilter)
278         return true;
279 
280     if (!filterName.isEmpty() && !d->m_collectionHandler->filters().contains(filterName))
281         return false;
282 
283     d->m_currentFilter = filterName;
284     d->m_collectionHandler->setCustomValue(QLatin1String(ActiveFilter),
285             d->m_currentFilter);
286 
287     emit filterActivated(d->m_currentFilter);
288 
289     return true;
290 }
291 
292 /*!
293     Returns the list of all registered documentation namespaces that match
294     the filter identified by \a filterName.
295 */
namespacesForFilter(const QString & filterName) const296 QStringList QHelpFilterEngine::namespacesForFilter(const QString &filterName) const
297 {
298     if (!d->setup())
299         return QStringList();
300     return  d->m_collectionHandler->namespacesForFilter(filterName);
301 }
302 
303 /*!
304     \since 5.15
305 
306     Returns a sorted list of available indices.
307     The returned list contents depend on the active filter, and therefore only
308     the indices registered for the active filter will be returned.
309 */
indices() const310 QStringList QHelpFilterEngine::indices() const
311 {
312     return indices(activeFilter());
313 }
314 
315 /*!
316     \since 5.15
317 
318     Returns a sorted list of available indices, filtered by \a filterName.
319     The returned list contents depend on the passed filter, and therefore only
320     the indices registered for this filter will be returned.
321     If you want to get all available indices unfiltered,
322     pass empty string as \a filterName.
323 */
indices(const QString & filterName) const324 QStringList QHelpFilterEngine::indices(const QString &filterName) const
325 {
326     if (!d->setup())
327         return QStringList();
328     return d->m_collectionHandler->indicesForFilter(filterName);
329 }
330 
331 QT_END_NAMESPACE
332