11#include <QtConcurrent/qtconcurrentrun.h>
12#include <QtCore/qpromise.h>
15#include <QtCore/qdir.h>
16#include <QtCore/qfileinfo.h>
20using namespace Qt::StringLiterals;
27 void init(
const QString &collectionFile);
43 QHelpEngineCore *helpEngineCore)
46 filterEngine =
new QHelpFilterEngine(q);
52 collectionHandler.reset(
new QHelpCollectionHandler(collectionFile, q));
53 QObject::connect(collectionHandler.get(), &QHelpCollectionHandler::error, q,
54 [
this](
const QString &msg) { error = msg; });
55 filterEngine->setCollectionHandler(collectionHandler.get());
66 emit q->setupStarted();
68 collectionHandler->setReadOnly(q->isReadOnly());
69 const bool opened = collectionHandler->openCollectionFile();
73 emit q->setupFinished();
78
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
127
128
129
130
133
134
135
136
139
140
141
144
145
146
147
148
149
150
151
154
155
156
157
158
161
162
163
164
165QHelpEngineCore::QHelpEngineCore(
const QString &collectionFile, QObject *parent)
167 , d(
new QHelpEngineCorePrivate(collectionFile,
this))
171
172
173#if QT_DEPRECATED_SINCE(6
, 8
)
174QHelpEngineCore::QHelpEngineCore(QHelpEngineCorePrivate *helpEngineCorePrivate, QObject *parent)
176 , d(helpEngineCorePrivate)
181
182
183QHelpEngineCore::~QHelpEngineCore()
189
190
191
192
193
194
195
196
197QString QHelpEngineCore::collectionFile()
const
199 return d->collectionHandler->collectionFile();
202void QHelpEngineCore::setCollectionFile(
const QString &fileName)
204 if (fileName != collectionFile())
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223bool QHelpEngineCore::isReadOnly()
const
228void QHelpEngineCore::setReadOnly(
bool enable)
230 if (d->readOnly == enable)
233 d->readOnly = enable;
234 d->init(collectionFile());
238
239
240
241
242
243
244
245QHelpFilterEngine *QHelpEngineCore::filterEngine()
const
247 return d->filterEngine;
251
252
253
254
255
256
257
258
259
260
261
262
263
264bool QHelpEngineCore::setupData()
266 d->needsSetup =
true;
271
272
273
274
275
276
277
278bool QHelpEngineCore::copyCollectionFile(
const QString &fileName)
282 return d->collectionHandler->copyCollectionFile(fileName);
286
287
288
289
290
291
292QString QHelpEngineCore::namespaceName(
const QString &documentationFileName)
294 void *pointer =
const_cast<QString *>(&documentationFileName);
295 QHelpDBReader reader(documentationFileName, QHelpGlobal::uniquifyConnectionName(
296 "GetNamespaceName"_L1, pointer),
nullptr);
298 return reader.namespaceName();
303
304
305
306
307
308
309
310
311bool QHelpEngineCore::registerDocumentation(
const QString &documentationFileName)
314 d->needsSetup =
true;
315 return d->collectionHandler->registerDocumentation(documentationFileName);
319
320
321
322
323
324
325bool QHelpEngineCore::unregisterDocumentation(
const QString &namespaceName)
328 d->needsSetup =
true;
329 return d->collectionHandler->unregisterDocumentation(namespaceName);
333
334
335
336
337
338
339QString QHelpEngineCore::documentationFileName(
const QString &namespaceName)
344 const QHelpCollectionHandler::FileInfo fileInfo =
345 d->collectionHandler->registeredDocumentation(namespaceName);
347 if (fileInfo.namespaceName.isEmpty())
350 if (QDir::isAbsolutePath(fileInfo.fileName))
351 return fileInfo.fileName;
353 return QFileInfo(QFileInfo(d->collectionHandler->collectionFile()).absolutePath()
354 + u'/' + fileInfo.fileName).absoluteFilePath();
358
359
360
361QStringList QHelpEngineCore::registeredDocumentations()
const
365 const auto &docList = d->collectionHandler->registeredDocumentations();
367 for (
const QHelpCollectionHandler::FileInfo &info : docList)
368 list.append(info.namespaceName);
373
374
375
376
377
378
379
380
381QStringList QHelpEngineCore::customFilters()
const
385 return d->collectionHandler->customFilters();
389
390
391
392
393
394
395
396
397
398
399
400bool QHelpEngineCore::addCustomFilter(
const QString &filterName,
401 const QStringList &attributes)
404 d->needsSetup =
true;
405 return d->collectionHandler->addCustomFilter(filterName, attributes);
409
410
411
412
413
414
415
416
417
418bool QHelpEngineCore::removeCustomFilter(
const QString &filterName)
421 d->needsSetup =
true;
422 return d->collectionHandler->removeCustomFilter(filterName);
426
427
428
429
430
431
432QStringList QHelpEngineCore::filterAttributes()
const
436 return d->collectionHandler->filterAttributes();
440
441
442
443
444
445
446
447QStringList QHelpEngineCore::filterAttributes(
const QString &filterName)
const
451 return d->collectionHandler->filterAttributes(filterName);
455
456
457
458
459
460
461
462
463
464
465
466
467
468QString QHelpEngineCore::currentFilter()
const
473 if (d->currentFilter.isEmpty()) {
474 const QString &filter =
475 d->collectionHandler->customValue(
"CurrentFilter"_L1, QString()).toString();
476 if (!filter.isEmpty() && d->collectionHandler->customFilters().contains(filter))
477 d->currentFilter = filter;
479 return d->currentFilter;
482void QHelpEngineCore::setCurrentFilter(
const QString &filterName)
484 if (!d->setup() || filterName == d->currentFilter)
486 d->currentFilter = filterName;
487 if (d->autoSaveFilter)
488 d->collectionHandler->setCustomValue(
"CurrentFilter"_L1, d->currentFilter);
489 emit currentFilterChanged(d->currentFilter);
493
494
495
496
497
498
499
500
501QList<QStringList> QHelpEngineCore::filterAttributeSets(
const QString &namespaceName)
const
505 return d->collectionHandler->filterAttributeSets(namespaceName);
509
510
511
512
513
514
515
516
517QList<QUrl> QHelpEngineCore::files(
const QString namespaceName,
518 const QStringList &filterAttributes,
519 const QString &extensionFilter)
526 url.setScheme(
"qthelp"_L1);
527 url.setAuthority(namespaceName);
529 const QStringList &files = d->collectionHandler->files(
530 namespaceName, filterAttributes, extensionFilter);
531 for (
const QString &file : files) {
532 url.setPath(
"/"_L1 + file);
539
540
541
542
543QList<QUrl> QHelpEngineCore::files(
const QString namespaceName,
544 const QString &filterName,
545 const QString &extensionFilter)
552 url.setScheme(
"qthelp"_L1);
553 url.setAuthority(namespaceName);
555 const QStringList &files = d->collectionHandler->files(
556 namespaceName, filterName, extensionFilter);
557 for (
const QString &file : files) {
558 url.setPath(
"/"_L1 + file);
565
566
567
568
569
570
571
572
573
574QUrl QHelpEngineCore::findFile(
const QUrl &url)
const
579 QUrl result = d->usesFilterEngine
580 ? d->collectionHandler->findFile(url, d->filterEngine->activeFilter())
581 : d->collectionHandler->findFile(url, filterAttributes(currentFilter()));
582 if (!result.isEmpty())
585 result = d->usesFilterEngine
586 ? d->collectionHandler->findFile(url, QString())
587 : d->collectionHandler->findFile(url, QStringList());
588 if (!result.isEmpty())
595
596
597
598
599
600QByteArray QHelpEngineCore::fileData(
const QUrl &url)
const
604 return d->collectionHandler->fileData(url);
608
609
610
611
612
613
614QList<QHelpLink> QHelpEngineCore::documentsForIdentifier(
const QString &id)
const
616 return documentsForIdentifier(
617 id, d->usesFilterEngine ? d->filterEngine->activeFilter() : d->currentFilter);
621
622
623
624
625
626
627
628QList<QHelpLink> QHelpEngineCore::documentsForIdentifier(
const QString &id,
const QString &filterName)
const
633 if (d->usesFilterEngine)
634 return d->collectionHandler->documentsForIdentifier(id, filterName);
635 return d->collectionHandler->documentsForIdentifier(id, filterAttributes(filterName));
639
640
641
642
643
644
645QList<QHelpLink> QHelpEngineCore::documentsForKeyword(
const QString &keyword)
const
647 return documentsForKeyword(
648 keyword, d->usesFilterEngine ? d->filterEngine->activeFilter() : d->currentFilter);
652
653
654
655
656
657
658
659QList<QHelpLink> QHelpEngineCore::documentsForKeyword(
const QString &keyword,
const QString &filterName)
const
664 if (d->usesFilterEngine)
665 return d->collectionHandler->documentsForKeyword(keyword, filterName);
666 return d->collectionHandler->documentsForKeyword(keyword, filterAttributes(filterName));
670
671
672
673
674
675
676bool QHelpEngineCore::removeCustomValue(
const QString &key)
679 return d->collectionHandler->removeCustomValue(key);
683
684
685
686
687
688
689QVariant QHelpEngineCore::customValue(
const QString &key,
const QVariant &defaultValue)
const
693 return d->collectionHandler->customValue(key, defaultValue);
697
698
699
700
701
702
703bool QHelpEngineCore::setCustomValue(
const QString &key,
const QVariant &value)
706 return d->collectionHandler->setCustomValue(key, value);
710
711
712
713
714
715
716
717QVariant QHelpEngineCore::metaData(
const QString &documentationFileName,
720 QHelpDBReader reader(documentationFileName,
"GetMetaData"_L1,
nullptr);
723 return reader.metaData(name);
728
729
730QString QHelpEngineCore::error()
const
736
737
738
739
740
741
742
743
744
745
746void QHelpEngineCore::setAutoSaveFilter(
bool save)
748 d->autoSaveFilter = save;
751bool QHelpEngineCore::autoSaveFilter()
const
753 return d->autoSaveFilter;
757
758
759
760
761
762
763
764void QHelpEngineCore::setUsesFilterEngine(
bool uses)
766 d->usesFilterEngine = uses;
770
771
772
773
774
775
776bool QHelpEngineCore::usesFilterEngine()
const
778 return d->usesFilterEngine;
782static QUrl constructUrl(
const QString &namespaceName,
const QString &folderName,
783 const QString &relativePath)
785 const int idx = relativePath.indexOf(u'#');
786 const QString &rp = idx < 0 ? relativePath : relativePath.left(idx);
787 const QString anchor = idx < 0 ? QString() : relativePath.mid(idx + 1);
788 return QHelpCollectionHandler::buildQUrl(namespaceName, folderName, rp, anchor);
791using ContentProviderResult = QList<QHelpCollectionHandler::ContentsData>;
792using ContentProvider = std::function<ContentProviderResult(
const QString &)>;
793using ContentResult = std::shared_ptr<QHelpContentItem>;
796QHelpContentItem *createContentItem(
const QString &name = {},
const QUrl &link = {},
797 QHelpContentItem *parent = {})
799 return new QHelpContentItem(name, link, parent);
802static void requestContentHelper(QPromise<ContentResult> &promise,
const ContentProvider &provider,
803 const QString &collectionFile)
805 ContentResult rootItem(createContentItem());
806 const ContentProviderResult result = provider(collectionFile);
807 for (
const auto &contentsData : result) {
808 const QString namespaceName = contentsData.namespaceName;
809 const QString folderName = contentsData.folderName;
810 for (
const QByteArray &contents : contentsData.contentsList) {
811 if (promise.isCanceled())
814 if (contents.isEmpty())
817 QList<QHelpContentItem *> stack;
818 QDataStream s(contents);
844 }
else if (depth < stack.size()) {
845 stack = stack.sliced(0, depth);
846 }
else if (depth > stack.size()) {
851 QHelpContentItem *substituteItem =
852 stack.isEmpty() ? rootItem.get() : stack.constLast();
853 while (depth > stack.size())
854 stack.append(substituteItem);
857 const QUrl url = constructUrl(namespaceName, folderName, link);
858 QHelpContentItem *parent = stack.isEmpty() ? rootItem.get() : stack.constLast();
859 stack.push_back(createContentItem(title, url, parent));
863 promise.addResult(rootItem);
866static ContentProvider contentProviderFromFilterEngine(
const QString &filter)
868 return [filter](
const QString &collectionFile) -> ContentProviderResult {
869 QHelpCollectionHandler collectionHandler(collectionFile);
870 if (!collectionHandler.openCollectionFile())
872 return collectionHandler.contentsForFilter(filter);
876static ContentProvider contentProviderFromAttributes(
const QStringList &attributes)
878 return [attributes](
const QString &collectionFile) -> ContentProviderResult {
879 QHelpCollectionHandler collectionHandler(collectionFile);
880 if (!collectionHandler.openCollectionFile())
882 return collectionHandler.contentsForFilter(attributes);
886QFuture<ContentResult> QHelpEngineCore::requestContentForCurrentFilter()
const
888 const ContentProvider provider = usesFilterEngine()
889 ? contentProviderFromFilterEngine(filterEngine()->activeFilter())
890 : contentProviderFromAttributes(filterAttributes(d->currentFilter));
891 return QtConcurrent::run(requestContentHelper, provider, collectionFile());
894QFuture<ContentResult> QHelpEngineCore::requestContent(
const QString &filter)
const
896 const ContentProvider provider = usesFilterEngine()
897 ? contentProviderFromFilterEngine(filter)
898 : contentProviderFromAttributes(filterAttributes(filter));
899 return QtConcurrent::run(requestContentHelper, provider, collectionFile());
902using IndexProvider = std::function<QStringList(
const QString &)>;
903using IndexResult = QStringList;
905static IndexProvider indexProviderFromFilterEngine(
const QString &filter)
907 return [filter](
const QString &collectionFile) -> IndexResult {
908 QHelpCollectionHandler collectionHandler(collectionFile);
909 if (!collectionHandler.openCollectionFile())
911 return collectionHandler.indicesForFilter(filter);
915static IndexProvider indexProviderFromAttributes(
const QStringList &attributes)
917 return [attributes](
const QString &collectionFile) -> IndexResult {
918 QHelpCollectionHandler collectionHandler(collectionFile);
919 if (!collectionHandler.openCollectionFile())
921 return collectionHandler.indicesForFilter(attributes);
925QFuture<IndexResult> QHelpEngineCore::requestIndexForCurrentFilter()
const
927 const IndexProvider provider = usesFilterEngine()
928 ? indexProviderFromFilterEngine(filterEngine()->activeFilter())
929 : indexProviderFromAttributes(filterAttributes(d->currentFilter));
930 return QtConcurrent::run(std::move(provider), collectionFile());
933QFuture<IndexResult> QHelpEngineCore::requestIndex(
const QString &filter)
const
935 const IndexProvider provider = usesFilterEngine()
936 ? indexProviderFromFilterEngine(filter)
937 : indexProviderFromAttributes(filterAttributes(filter));
938 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.