12#include <QtConcurrent/qtconcurrentrun.h>
13#include <QtCore/qpromise.h>
16#include <QtCore/qdir.h>
17#include <QtCore/qfileinfo.h>
21using namespace Qt::StringLiterals;
28 void init(
const QString &collectionFile);
44 QHelpEngineCore *helpEngineCore)
47 filterEngine =
new QHelpFilterEngine(q);
53 collectionHandler.reset(
new QHelpCollectionHandler(collectionFile, q));
54 QObject::connect(collectionHandler.get(), &QHelpCollectionHandler::error, q,
55 [
this](
const QString &msg) { error = msg; });
56 filterEngine->setCollectionHandler(collectionHandler.get());
67 emit q->setupStarted();
69 collectionHandler->setReadOnly(q->isReadOnly());
70 const bool opened = collectionHandler->openCollectionFile();
74 emit q->setupFinished();
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
128
129
130
131
134
135
136
137
140
141
142
145
146
147
148
149
150
151
152
155
156
157
158
159
162
163
164
165
166QHelpEngineCore::QHelpEngineCore(
const QString &collectionFile, QObject *parent)
168 , d(
new QHelpEngineCorePrivate(collectionFile,
this))
172
173
174#if QT_DEPRECATED_SINCE(6
, 8
)
175QHelpEngineCore::QHelpEngineCore(QHelpEngineCorePrivate *helpEngineCorePrivate, QObject *parent)
177 , d(helpEngineCorePrivate)
182
183
184QHelpEngineCore::~QHelpEngineCore()
190
191
192
193
194
195
196
197
198QString QHelpEngineCore::collectionFile()
const
200 return d->collectionHandler->collectionFile();
203void QHelpEngineCore::setCollectionFile(
const QString &fileName)
205 if (fileName != collectionFile())
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224bool QHelpEngineCore::isReadOnly()
const
229void QHelpEngineCore::setReadOnly(
bool enable)
231 if (d->readOnly == enable)
234 d->readOnly = enable;
235 d->init(collectionFile());
239
240
241
242
243
244
245
246QHelpFilterEngine *QHelpEngineCore::filterEngine()
const
248 return d->filterEngine;
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269bool QHelpEngineCore::setupData()
271 d->needsSetup =
true;
276
277
278
279
280
281
282
283bool QHelpEngineCore::copyCollectionFile(
const QString &fileName)
287 return d->collectionHandler->copyCollectionFile(fileName);
291
292
293
294
295
296
297QString QHelpEngineCore::namespaceName(
const QString &documentationFileName)
299 void *pointer =
const_cast<QString *>(&documentationFileName);
300 QHelpDBReader reader(documentationFileName, QHelpGlobal::uniquifyConnectionName(
301 "GetNamespaceName"_L1, pointer),
nullptr);
303 return reader.namespaceName();
308
309
310
311
312
313
314
315
316bool QHelpEngineCore::registerDocumentation(
const QString &documentationFileName)
319 d->needsSetup =
true;
320 return d->collectionHandler->registerDocumentation(documentationFileName);
324
325
326
327
328
329
330bool QHelpEngineCore::unregisterDocumentation(
const QString &namespaceName)
333 d->needsSetup =
true;
334 return d->collectionHandler->unregisterDocumentation(namespaceName);
338
339
340
341
342
343
344QString QHelpEngineCore::documentationFileName(
const QString &namespaceName)
349 const QHelpCollectionHandler::FileInfo fileInfo =
350 d->collectionHandler->registeredDocumentation(namespaceName);
352 if (fileInfo.namespaceName.isEmpty())
355 if (QDir::isAbsolutePath(fileInfo.fileName))
356 return fileInfo.fileName;
358 return QFileInfo(QFileInfo(d->collectionHandler->collectionFile()).absolutePath()
359 + u'/' + fileInfo.fileName).absoluteFilePath();
363
364
365
366QStringList QHelpEngineCore::registeredDocumentations()
const
370 const auto &docList = d->collectionHandler->registeredDocumentations();
372 for (
const QHelpCollectionHandler::FileInfo &info : docList)
373 list.append(info.namespaceName);
378
379
380
381
382
383
384
385
386QStringList QHelpEngineCore::customFilters()
const
390 return d->collectionHandler->customFilters();
394
395
396
397
398
399
400
401
402
403
404
405bool QHelpEngineCore::addCustomFilter(
const QString &filterName,
406 const QStringList &attributes)
409 d->needsSetup =
true;
410 return d->collectionHandler->addCustomFilter(filterName, attributes);
414
415
416
417
418
419
420
421
422
423bool QHelpEngineCore::removeCustomFilter(
const QString &filterName)
426 d->needsSetup =
true;
427 return d->collectionHandler->removeCustomFilter(filterName);
431
432
433
434
435
436
437QStringList QHelpEngineCore::filterAttributes()
const
441 return d->collectionHandler->filterAttributes();
445
446
447
448
449
450
451
452QStringList QHelpEngineCore::filterAttributes(
const QString &filterName)
const
456 return d->collectionHandler->filterAttributes(filterName);
460
461
462
463
464
465
466
467
468
469
470
471
472
473QString QHelpEngineCore::currentFilter()
const
478 if (d->currentFilter.isEmpty()) {
479 const QString &filter =
480 d->collectionHandler->customValue(
"CurrentFilter"_L1, QString()).toString();
481 if (!filter.isEmpty() && d->collectionHandler->customFilters().contains(filter))
482 d->currentFilter = filter;
484 return d->currentFilter;
487void QHelpEngineCore::setCurrentFilter(
const QString &filterName)
489 if (!d->setup() || filterName == d->currentFilter)
491 d->currentFilter = filterName;
492 if (d->autoSaveFilter)
493 d->collectionHandler->setCustomValue(
"CurrentFilter"_L1, d->currentFilter);
494 emit currentFilterChanged(d->currentFilter);
498
499
500
501
502
503
504
505
506QList<QStringList> QHelpEngineCore::filterAttributeSets(
const QString &namespaceName)
const
510 return d->collectionHandler->filterAttributeSets(namespaceName);
514
515
516
517
518
519
520
521
522QList<QUrl> QHelpEngineCore::files(
const QString namespaceName,
523 const QStringList &filterAttributes,
524 const QString &extensionFilter)
531 url.setScheme(
"qthelp"_L1);
532 url.setAuthority(namespaceName);
534 const QStringList &files = d->collectionHandler->files(
535 namespaceName, filterAttributes, extensionFilter);
536 for (
const QString &file : files) {
537 url.setPath(
"/"_L1 + file);
544
545
546
547
548QList<QUrl> QHelpEngineCore::files(
const QString namespaceName,
549 const QString &filterName,
550 const QString &extensionFilter)
557 url.setScheme(
"qthelp"_L1);
558 url.setAuthority(namespaceName);
560 const QStringList &files = d->collectionHandler->files(
561 namespaceName, filterName, extensionFilter);
562 for (
const QString &file : files) {
563 url.setPath(
"/"_L1 + file);
570
571
572
573
574
575
576
577
578
579QUrl QHelpEngineCore::findFile(
const QUrl &url)
const
584 QUrl result = d->usesFilterEngine
585 ? d->collectionHandler->findFile(url, d->filterEngine->activeFilter())
586 : d->collectionHandler->findFile(url, filterAttributes(currentFilter()));
587 if (!result.isEmpty())
590 result = d->usesFilterEngine
591 ? d->collectionHandler->findFile(url, QString())
592 : d->collectionHandler->findFile(url, QStringList());
593 if (!result.isEmpty())
600
601
602
603
604
605
606
607
608
609
610QByteArray QHelpEngineCore::fileData(
const QUrl &url)
const
614 return d->collectionHandler->fileData(url);
618
619
620
621
622
623
624QList<QHelpLink> QHelpEngineCore::documentsForIdentifier(
const QString &id)
const
626 return documentsForIdentifier(
627 id, d->usesFilterEngine ? d->filterEngine->activeFilter() : d->currentFilter);
631
632
633
634
635
636
637
638QList<QHelpLink> QHelpEngineCore::documentsForIdentifier(
const QString &id,
const QString &filterName)
const
643 if (d->usesFilterEngine)
644 return d->collectionHandler->documentsForIdentifier(id, filterName);
645 return d->collectionHandler->documentsForIdentifier(id, filterAttributes(filterName));
649
650
651
652
653
654
655QList<QHelpLink> QHelpEngineCore::documentsForKeyword(
const QString &keyword)
const
657 return documentsForKeyword(
658 keyword, d->usesFilterEngine ? d->filterEngine->activeFilter() : d->currentFilter);
662
663
664
665
666
667
668
669QList<QHelpLink> QHelpEngineCore::documentsForKeyword(
const QString &keyword,
const QString &filterName)
const
674 if (d->usesFilterEngine)
675 return d->collectionHandler->documentsForKeyword(keyword, filterName);
676 return d->collectionHandler->documentsForKeyword(keyword, filterAttributes(filterName));
680
681
682
683
684
685
686bool QHelpEngineCore::removeCustomValue(
const QString &key)
689 return d->collectionHandler->removeCustomValue(key);
693
694
695
696
697
698
699QVariant QHelpEngineCore::customValue(
const QString &key,
const QVariant &defaultValue)
const
703 return d->collectionHandler->customValue(key, defaultValue);
707
708
709
710
711
712
713bool QHelpEngineCore::setCustomValue(
const QString &key,
const QVariant &value)
716 return d->collectionHandler->setCustomValue(key, value);
720
721
722
723
724
725
726
727QVariant QHelpEngineCore::metaData(
const QString &documentationFileName,
730 QHelpDBReader reader(documentationFileName,
"GetMetaData"_L1,
nullptr);
733 return reader.metaData(name);
738
739
740QString QHelpEngineCore::error()
const
746
747
748
749
750
751
752
753
754
755
756void QHelpEngineCore::setAutoSaveFilter(
bool save)
758 d->autoSaveFilter = save;
761bool QHelpEngineCore::autoSaveFilter()
const
763 return d->autoSaveFilter;
767
768
769
770
771
772
773
774void QHelpEngineCore::setUsesFilterEngine(
bool uses)
776 d->usesFilterEngine = uses;
780
781
782
783
784
785
786bool QHelpEngineCore::usesFilterEngine()
const
788 return d->usesFilterEngine;
792static QUrl constructUrl(
const QString &namespaceName,
const QString &folderName,
793 const QString &relativePath)
795 const int idx = relativePath.indexOf(u'#');
796 const QString &rp = idx < 0 ? relativePath : relativePath.left(idx);
797 const QString anchor = idx < 0 ? QString() : relativePath.mid(idx + 1);
798 return QHelpCollectionHandler::buildQUrl(namespaceName, folderName, rp, anchor);
801using ContentProviderResult = QList<QHelpCollectionHandler::ContentsData>;
802using ContentProvider = std::function<ContentProviderResult(
const QString &)>;
803using ContentResult = std::shared_ptr<QHelpContentItem>;
806QHelpContentItem *createContentItem(
const QString &name = {},
const QUrl &link = {},
807 QHelpContentItem *parent = {})
809 return new QHelpContentItem(name, link, parent);
812static void requestContentHelper(QPromise<ContentResult> &promise,
const ContentProvider &provider,
813 const QString &collectionFile)
815 ContentResult rootItem(createContentItem());
816 const ContentProviderResult result = provider(collectionFile);
817 for (
const auto &contentsData : result) {
818 const QString namespaceName = contentsData.namespaceName;
819 const QString folderName = contentsData.folderName;
820 for (
const QByteArray &contents : contentsData.contentsList) {
821 if (promise.isCanceled())
824 if (contents.isEmpty())
829 QList<std::pair<
int, QHelpContentItem *>> stack;
830 QDataStream s(contents);
859 depth = qMax(depth, 0);
860 while (!stack.isEmpty() && stack.constLast().first >= depth)
863 const QUrl url = constructUrl(namespaceName, folderName, link);
864 QHelpContentItem *parent = stack.isEmpty() ? rootItem.get()
865 : stack.constLast().second;
866 stack.push_back({depth, createContentItem(title, url, parent)});
870 promise.addResult(rootItem);
873static ContentProvider contentProviderFromFilterEngine(
const QString &filter)
875 return [filter](
const QString &collectionFile) -> ContentProviderResult {
876 QHelpCollectionHandler collectionHandler(collectionFile);
877 if (!collectionHandler.openCollectionFile())
879 return collectionHandler.contentsForFilter(filter);
883static ContentProvider contentProviderFromAttributes(
const QStringList &attributes)
885 return [attributes](
const QString &collectionFile) -> ContentProviderResult {
886 QHelpCollectionHandler collectionHandler(collectionFile);
887 if (!collectionHandler.openCollectionFile())
889 return collectionHandler.contentsForFilter(attributes);
893QFuture<ContentResult> QHelpEngineCore::requestContentForCurrentFilter()
const
895 const ContentProvider provider = usesFilterEngine()
896 ? contentProviderFromFilterEngine(filterEngine()->activeFilter())
897 : contentProviderFromAttributes(filterAttributes(d->currentFilter));
898 return QtConcurrent::run(requestContentHelper, provider, collectionFile());
901QFuture<ContentResult> QHelpEngineCore::requestContent(
const QString &filter)
const
903 const ContentProvider provider = usesFilterEngine()
904 ? contentProviderFromFilterEngine(filter)
905 : contentProviderFromAttributes(filterAttributes(filter));
906 return QtConcurrent::run(requestContentHelper, provider, collectionFile());
909using IndexProvider = std::function<QStringList(
const QString &)>;
910using IndexResult = QStringList;
912static IndexProvider indexProviderFromFilterEngine(
const QString &filter)
914 return [filter](
const QString &collectionFile) -> IndexResult {
915 QHelpCollectionHandler collectionHandler(collectionFile);
916 if (!collectionHandler.openCollectionFile())
918 return collectionHandler.indicesForFilter(filter);
922static IndexProvider indexProviderFromAttributes(
const QStringList &attributes)
924 return [attributes](
const QString &collectionFile) -> IndexResult {
925 QHelpCollectionHandler collectionHandler(collectionFile);
926 if (!collectionHandler.openCollectionFile())
928 return collectionHandler.indicesForFilter(attributes);
932QFuture<IndexResult> QHelpEngineCore::requestIndexForCurrentFilter()
const
934 const IndexProvider provider = usesFilterEngine()
935 ? indexProviderFromFilterEngine(filterEngine()->activeFilter())
936 : indexProviderFromAttributes(filterAttributes(d->currentFilter));
937 return QtConcurrent::run(std::move(provider), collectionFile());
940QFuture<IndexResult> QHelpEngineCore::requestIndex(
const QString &filter)
const
942 const IndexProvider provider = usesFilterEngine()
943 ? indexProviderFromFilterEngine(filter)
944 : indexProviderFromAttributes(filterAttributes(filter));
945 return QtConcurrent::run(std::move(provider), collectionFile());
std::unique_ptr< QHelpCollectionHandler > collectionHandler
QHelpFilterEngine * filterEngine
QHelpEngineCorePrivate(const QString &collectionFile, QHelpEngineCore *helpEngineCore)
void init(const QString &collectionFile)
Combined button and popup list for selecting options.