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)
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
224
225
226
227
228
229bool QHelpEngineCore::isReadOnly()
const
234void QHelpEngineCore::setReadOnly(
bool enable)
236 if (d->readOnly == enable)
239 d->readOnly = enable;
240 d->init(collectionFile());
244
245
246
247
248
249
250
251QHelpFilterEngine *QHelpEngineCore::filterEngine()
const
253 return d->filterEngine;
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274bool QHelpEngineCore::setupData()
276 d->needsSetup =
true;
281
282
283
284
285
286
287
288bool QHelpEngineCore::copyCollectionFile(
const QString &fileName)
292 return d->collectionHandler->copyCollectionFile(fileName);
296
297
298
299
300
301
302QString QHelpEngineCore::namespaceName(
const QString &documentationFileName)
304 void *pointer =
const_cast<QString *>(&documentationFileName);
305 QHelpDBReader reader(documentationFileName, QHelpGlobal::uniquifyConnectionName(
306 "GetNamespaceName"_L1, pointer),
nullptr);
308 return reader.namespaceName();
313
314
315
316
317
318
319
320
321bool QHelpEngineCore::registerDocumentation(
const QString &documentationFileName)
324 d->needsSetup =
true;
325 return d->collectionHandler->registerDocumentation(documentationFileName);
329
330
331
332
333
334
335bool QHelpEngineCore::unregisterDocumentation(
const QString &namespaceName)
338 d->needsSetup =
true;
339 return d->collectionHandler->unregisterDocumentation(namespaceName);
343
344
345
346
347
348
349QString QHelpEngineCore::documentationFileName(
const QString &namespaceName)
354 const QHelpCollectionHandler::FileInfo fileInfo =
355 d->collectionHandler->registeredDocumentation(namespaceName);
357 if (fileInfo.namespaceName.isEmpty())
360 if (QDir::isAbsolutePath(fileInfo.fileName))
361 return fileInfo.fileName;
363 return QFileInfo(QFileInfo(d->collectionHandler->collectionFile()).absolutePath()
364 + u'/' + fileInfo.fileName).absoluteFilePath();
368
369
370
371QStringList QHelpEngineCore::registeredDocumentations()
const
375 const auto &docList = d->collectionHandler->registeredDocumentations();
377 for (
const QHelpCollectionHandler::FileInfo &info : docList)
378 list.append(info.namespaceName);
383
384
385
386
387
388
389
390
391QStringList QHelpEngineCore::customFilters()
const
395 return d->collectionHandler->customFilters();
399
400
401
402
403
404
405
406
407
408
409
410bool QHelpEngineCore::addCustomFilter(
const QString &filterName,
411 const QStringList &attributes)
414 d->needsSetup =
true;
415 return d->collectionHandler->addCustomFilter(filterName, attributes);
419
420
421
422
423
424
425
426
427
428bool QHelpEngineCore::removeCustomFilter(
const QString &filterName)
431 d->needsSetup =
true;
432 return d->collectionHandler->removeCustomFilter(filterName);
436
437
438
439
440
441
442QStringList QHelpEngineCore::filterAttributes()
const
446 return d->collectionHandler->filterAttributes();
450
451
452
453
454
455
456
457QStringList QHelpEngineCore::filterAttributes(
const QString &filterName)
const
461 return d->collectionHandler->filterAttributes(filterName);
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479QString QHelpEngineCore::currentFilter()
const
484 if (d->currentFilter.isEmpty()) {
485 const QString &filter =
486 d->collectionHandler->customValue(
"CurrentFilter"_L1, QString()).toString();
487 if (!filter.isEmpty() && d->collectionHandler->customFilters().contains(filter))
488 d->currentFilter = filter;
490 return d->currentFilter;
493void QHelpEngineCore::setCurrentFilter(
const QString &filterName)
495 if (!d->setup() || filterName == d->currentFilter)
497 d->currentFilter = filterName;
498 if (d->autoSaveFilter && !d->readOnly)
499 d->collectionHandler->setCustomValue(
"CurrentFilter"_L1, d->currentFilter);
500 emit currentFilterChanged(d->currentFilter);
504
505
506
507
508
509
510
511
512QList<QStringList> QHelpEngineCore::filterAttributeSets(
const QString &namespaceName)
const
516 return d->collectionHandler->filterAttributeSets(namespaceName);
520
521
522
523
524
525
526
527
528QList<QUrl> QHelpEngineCore::files(
const QString namespaceName,
529 const QStringList &filterAttributes,
530 const QString &extensionFilter)
537 url.setScheme(
"qthelp"_L1);
538 url.setAuthority(namespaceName);
540 const QStringList &files = d->collectionHandler->files(
541 namespaceName, filterAttributes, extensionFilter);
542 for (
const QString &file : files) {
543 url.setPath(
"/"_L1 + file);
550
551
552
553
554QList<QUrl> QHelpEngineCore::files(
const QString namespaceName,
555 const QString &filterName,
556 const QString &extensionFilter)
563 url.setScheme(
"qthelp"_L1);
564 url.setAuthority(namespaceName);
566 const QStringList &files = d->collectionHandler->files(
567 namespaceName, filterName, extensionFilter);
568 for (
const QString &file : files) {
569 url.setPath(
"/"_L1 + file);
576
577
578
579
580
581
582
583
584
585QUrl QHelpEngineCore::findFile(
const QUrl &url)
const
590 QUrl result = d->usesFilterEngine
591 ? d->collectionHandler->findFile(url, d->filterEngine->activeFilter())
592 : d->collectionHandler->findFile(url, filterAttributes(currentFilter()));
593 if (!result.isEmpty())
596 result = d->usesFilterEngine
597 ? d->collectionHandler->findFile(url, QString())
598 : d->collectionHandler->findFile(url, QStringList());
599 if (!result.isEmpty())
606
607
608
609
610
611
612
613
614
615
616QByteArray QHelpEngineCore::fileData(
const QUrl &url)
const
620 return d->collectionHandler->fileData(url);
624
625
626
627
628
629
630QList<QHelpLink> QHelpEngineCore::documentsForIdentifier(
const QString &id)
const
632 return documentsForIdentifier(
633 id, d->usesFilterEngine ? d->filterEngine->activeFilter() : d->currentFilter);
637
638
639
640
641
642
643
644QList<QHelpLink> QHelpEngineCore::documentsForIdentifier(
const QString &id,
const QString &filterName)
const
649 if (d->usesFilterEngine)
650 return d->collectionHandler->documentsForIdentifier(id, filterName);
651 return d->collectionHandler->documentsForIdentifier(id, filterAttributes(filterName));
655
656
657
658
659
660
661QList<QHelpLink> QHelpEngineCore::documentsForKeyword(
const QString &keyword)
const
663 return documentsForKeyword(
664 keyword, d->usesFilterEngine ? d->filterEngine->activeFilter() : d->currentFilter);
668
669
670
671
672
673
674
675QList<QHelpLink> QHelpEngineCore::documentsForKeyword(
const QString &keyword,
const QString &filterName)
const
680 if (d->usesFilterEngine)
681 return d->collectionHandler->documentsForKeyword(keyword, filterName);
682 return d->collectionHandler->documentsForKeyword(keyword, filterAttributes(filterName));
686
687
688
689
690
691
692bool QHelpEngineCore::removeCustomValue(
const QString &key)
695 return d->collectionHandler->removeCustomValue(key);
699
700
701
702
703
704
705QVariant QHelpEngineCore::customValue(
const QString &key,
const QVariant &defaultValue)
const
709 return d->collectionHandler->customValue(key, defaultValue);
713
714
715
716
717
718
719bool QHelpEngineCore::setCustomValue(
const QString &key,
const QVariant &value)
722 return d->collectionHandler->setCustomValue(key, value);
726
727
728
729
730
731
732
733QVariant QHelpEngineCore::metaData(
const QString &documentationFileName,
736 QHelpDBReader reader(documentationFileName,
"GetMetaData"_L1,
nullptr);
739 return reader.metaData(name);
744
745
746QString QHelpEngineCore::error()
const
752
753
754
755
756
757
758
759
760
761
762
763void QHelpEngineCore::setAutoSaveFilter(
bool save)
765 d->autoSaveFilter = save;
768bool QHelpEngineCore::autoSaveFilter()
const
770 return d->autoSaveFilter;
774
775
776
777
778
779
780
781void QHelpEngineCore::setUsesFilterEngine(
bool uses)
783 d->usesFilterEngine = uses;
787
788
789
790
791
792
793bool QHelpEngineCore::usesFilterEngine()
const
795 return d->usesFilterEngine;
799static QUrl constructUrl(
const QString &namespaceName,
const QString &folderName,
800 const QString &relativePath)
802 const int idx = relativePath.indexOf(u'#');
803 const QString &rp = idx < 0 ? relativePath : relativePath.left(idx);
804 const QString anchor = idx < 0 ? QString() : relativePath.mid(idx + 1);
805 return QHelpCollectionHandler::buildQUrl(namespaceName, folderName, rp, anchor);
808using ContentProviderResult = QList<QHelpCollectionHandler::ContentsData>;
809using ContentProvider = std::function<ContentProviderResult(
const QString &)>;
810using ContentResult = std::shared_ptr<QHelpContentItem>;
813QHelpContentItem *createContentItem(
const QString &name = {},
const QUrl &link = {},
814 QHelpContentItem *parent = {})
816 return new QHelpContentItem(name, link, parent);
819static void requestContentHelper(QPromise<ContentResult> &promise,
const ContentProvider &provider,
820 const QString &collectionFile)
822 ContentResult rootItem(createContentItem());
823 const ContentProviderResult result = provider(collectionFile);
824 for (
const auto &contentsData : result) {
825 const QString namespaceName = contentsData.namespaceName;
826 const QString folderName = contentsData.folderName;
827 for (
const QByteArray &contents : contentsData.contentsList) {
828 if (promise.isCanceled())
831 if (contents.isEmpty())
836 QList<std::pair<
int, QHelpContentItem *>> stack;
837 QDataStream s(contents);
866 depth = qMax(depth, 0);
867 while (!stack.isEmpty() && stack.constLast().first >= depth)
870 const QUrl url = constructUrl(namespaceName, folderName, link);
871 QHelpContentItem *parent = stack.isEmpty() ? rootItem.get()
872 : stack.constLast().second;
873 stack.push_back({depth, createContentItem(title, url, parent)});
877 promise.addResult(rootItem);
880static ContentProvider contentProviderFromFilterEngine(
const QString &filter)
882 return [filter](
const QString &collectionFile) -> ContentProviderResult {
883 QHelpCollectionHandler collectionHandler(collectionFile);
884 if (!collectionHandler.openCollectionFile())
886 return collectionHandler.contentsForFilter(filter);
890static ContentProvider contentProviderFromAttributes(
const QStringList &attributes)
892 return [attributes](
const QString &collectionFile) -> ContentProviderResult {
893 QHelpCollectionHandler collectionHandler(collectionFile);
894 if (!collectionHandler.openCollectionFile())
896 return collectionHandler.contentsForFilter(attributes);
900QFuture<ContentResult> QHelpEngineCore::requestContentForCurrentFilter()
const
902 const ContentProvider provider = usesFilterEngine()
903 ? contentProviderFromFilterEngine(filterEngine()->activeFilter())
904 : contentProviderFromAttributes(filterAttributes(d->currentFilter));
905 return QtConcurrent::run(requestContentHelper, provider, collectionFile());
908QFuture<ContentResult> QHelpEngineCore::requestContent(
const QString &filter)
const
910 const ContentProvider provider = usesFilterEngine()
911 ? contentProviderFromFilterEngine(filter)
912 : contentProviderFromAttributes(filterAttributes(filter));
913 return QtConcurrent::run(requestContentHelper, provider, collectionFile());
916using IndexProvider = std::function<QStringList(
const QString &)>;
917using IndexResult = QStringList;
919static IndexProvider indexProviderFromFilterEngine(
const QString &filter)
921 return [filter](
const QString &collectionFile) -> IndexResult {
922 QHelpCollectionHandler collectionHandler(collectionFile);
923 if (!collectionHandler.openCollectionFile())
925 return collectionHandler.indicesForFilter(filter);
929static IndexProvider indexProviderFromAttributes(
const QStringList &attributes)
931 return [attributes](
const QString &collectionFile) -> IndexResult {
932 QHelpCollectionHandler collectionHandler(collectionFile);
933 if (!collectionHandler.openCollectionFile())
935 return collectionHandler.indicesForFilter(attributes);
939QFuture<IndexResult> QHelpEngineCore::requestIndexForCurrentFilter()
const
941 const IndexProvider provider = usesFilterEngine()
942 ? indexProviderFromFilterEngine(filterEngine()->activeFilter())
943 : indexProviderFromAttributes(filterAttributes(d->currentFilter));
944 return QtConcurrent::run(std::move(provider), collectionFile());
947QFuture<IndexResult> QHelpEngineCore::requestIndex(
const QString &filter)
const
949 const IndexProvider provider = usesFilterEngine()
950 ? indexProviderFromFilterEngine(filter)
951 : indexProviderFromAttributes(filterAttributes(filter));
952 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.