Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
helpenginewrapper.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3#include "tracer.h"
4
6#include "../shared/collectionconfiguration.h"
7
8#include <QtCore/QDateTime>
9#include <QtCore/QFileInfo>
10#include <QtCore/QFileSystemWatcher>
11#include <QtCore/QTimer>
12#include <QtHelp/QHelpContentModel>
13#include <QtHelp/QHelpEngine>
14#include <QtHelp/QHelpFilterEngine>
15#include <QtHelp/QHelpIndexModel>
16#include <QtHelp/QHelpLink>
17#include <QtHelp/QHelpSearchEngine>
18
19#include <map>
20#include <memory>
21
22QT_BEGIN_NAMESPACE
23
24using namespace Qt::StringLiterals;
25
26namespace {
27 const QString AppFontKey("appFont"_L1);
28 const QString AppWritingSystemKey("appWritingSystem"_L1);
29 const QString BookmarksKey("Bookmarks"_L1);
30 const QString BrowserFontKey("browserFont"_L1);
31 const QString BrowserWritingSystemKey("browserWritingSystem"_L1);
32 const QString HomePageKey("homepage"_L1);
33 const QString MainWindowKey("MainWindow"_L1);
34 const QString MainWindowGeometryKey("MainWindowGeometry"_L1);
35 const QString SearchWasAttachedKey("SearchWasAttached"_L1);
36 const QString StartOptionKey("StartOption"_L1);
37 const QString UseAppFontKey("useAppFont"_L1);
38 const QString UseBrowserFontKey("useBrowserFont"_L1);
39 const QString VersionKey("qtVersion%1$$$%2"_L1.arg(QLatin1StringView(QT_VERSION_STR)));
40 const QString ShowTabsKey("showTabs"_L1);
41 const QString TopicChooserGeometryKey("TopicChooserGeometry"_L1);
42} // anonymous namespace
43
45{
47public:
49private slots:
50 void forward();
51private:
53
54 const QString m_fileName;
55};
56
58{
60 friend class HelpEngineWrapper;
61 friend class TimeoutForwarder;
62private slots:
63 void qchFileChanged(const QString &fileName);
64
67 void documentationUpdated(const QString &namespaceName);
68
69private:
70 HelpEngineWrapperPrivate(const QString &collectionFile);
71
72 void removeStaleDocumentation();
73 void initFileSystemWatchers();
74 void checkDocFilesWatched();
75 void qchFileChanged(const QString &fileName, bool fromTimeout);
76
77 static const int UpdateGracePeriod = 2000;
78
79 QHelpEngine * const m_helpEngine;
80 QFileSystemWatcher * const m_qchWatcher;
81 struct RecentSignal {
82 QDateTime timestamp;
83 std::unique_ptr<TimeoutForwarder> forwarder;
84 };
85 std::map<QString, RecentSignal> m_recentQchUpdates;
86};
87
88HelpEngineWrapper *HelpEngineWrapper::helpEngineWrapper = nullptr;
89
94
95HelpEngineWrapper &HelpEngineWrapper::instance(const QString &collectionFile)
96{
98 /*
99 * Note that this Singleton cannot be static, because it has to be
100 * deleted before the QApplication.
101 */
102 if (!helpEngineWrapper)
103 helpEngineWrapper = new HelpEngineWrapper(collectionFile);
104 return *helpEngineWrapper;
105}
106
108{
110 delete helpEngineWrapper;
111 helpEngineWrapper = nullptr;
112}
113
114HelpEngineWrapper::HelpEngineWrapper(const QString &collectionFile)
115 : d(new HelpEngineWrapperPrivate(collectionFile))
116{
118
119 /*
120 * Otherwise we will waste time if several new docs are found,
121 * because we will start to index them, only to be interrupted
122 * by the next request. Also, there is a nasty SQLITE bug that will
123 * cause the application to hang for minutes in that case.
124 * This call is reverted by initialDocSetupDone(), which must be
125 * called after the new docs have been installed.
126 */
127// TODO: probably remove it
128 disconnect(d->m_helpEngine, &QHelpEngineCore::setupFinished,
129 searchEngine(), &QHelpSearchEngine::scheduleIndexDocumentation);
130
131 connect(d, &HelpEngineWrapperPrivate::documentationRemoved,
132 this, &HelpEngineWrapper::documentationRemoved);
133 connect(d, &HelpEngineWrapperPrivate::documentationUpdated,
134 this, &HelpEngineWrapper::documentationUpdated);
135 connect(d->m_helpEngine, &QHelpEngineCore::setupFinished,
137}
138
139HelpEngineWrapper::~HelpEngineWrapper()
140{
142 const QStringList &namespaces = d->m_helpEngine->registeredDocumentations();
143 for (const QString &nameSpace : namespaces) {
144 const QString &docFile
145 = d->m_helpEngine->documentationFileName(nameSpace);
146 d->m_qchWatcher->removePath(docFile);
147 }
148
149 delete d;
150}
151
153{
155// TODO: probably remove it
156 connect(d->m_helpEngine, &QHelpEngineCore::setupFinished,
157 searchEngine(), &QHelpSearchEngine::scheduleIndexDocumentation);
159}
160
161QHelpSearchEngine *HelpEngineWrapper::searchEngine() const
162{
164 return d->m_helpEngine->searchEngine();
165}
166
167QHelpContentModel *HelpEngineWrapper::contentModel() const
168{
170 return d->m_helpEngine->contentModel();
171}
172
173QHelpIndexModel *HelpEngineWrapper::indexModel() const
174{
176 return d->m_helpEngine->indexModel();
177}
178
179QHelpContentWidget *HelpEngineWrapper::contentWidget()
180{
182 return d->m_helpEngine->contentWidget();
183}
184
185QHelpIndexWidget *HelpEngineWrapper::indexWidget()
186{
188 return d->m_helpEngine->indexWidget();
189}
190
192{
194 return d->m_helpEngine->registeredDocumentations();
195}
196
197QString HelpEngineWrapper::documentationFileName(const QString &namespaceName) const
198{
200 return d->m_helpEngine->documentationFileName(namespaceName);
201}
202
204{
206 return d->m_helpEngine->collectionFile();
207}
208
209bool HelpEngineWrapper::registerDocumentation(const QString &docFile)
210{
212 d->checkDocFilesWatched();
213 if (!d->m_helpEngine->registerDocumentation(docFile))
214 return false;
215 d->m_qchWatcher->addPath(docFile);
216 d->checkDocFilesWatched();
217 return true;
218}
219
220bool HelpEngineWrapper::unregisterDocumentation(const QString &namespaceName)
221{
223 d->checkDocFilesWatched();
224 const QString &file = d->m_helpEngine->documentationFileName(namespaceName);
225 if (!d->m_helpEngine->unregisterDocumentation(namespaceName))
226 return false;
227 d->m_qchWatcher->removePath(file);
228 d->checkDocFilesWatched();
229 return true;
230}
231
233{
235 return d->m_helpEngine->setupData();
236}
237
238QUrl HelpEngineWrapper::findFile(const QUrl &url) const
239{
241 return d->m_helpEngine->findFile(url);
242}
243
244QByteArray HelpEngineWrapper::fileData(const QUrl &url) const
245{
247 return d->m_helpEngine->fileData(url);
248}
249
251{
253 return d->m_helpEngine->documentsForIdentifier(id);
254}
255
257{
259 return d->m_helpEngine->error();
260}
261
262QHelpFilterEngine *HelpEngineWrapper::filterEngine() const
263{
264 return d->m_helpEngine->filterEngine();
265}
266
267const QStringList HelpEngineWrapper::qtDocInfo(const QString &component) const
268{
270 return d->m_helpEngine->customValue(VersionKey.arg(component)).toString().
271 split(CollectionConfiguration::ListSeparator);
272}
273
274void HelpEngineWrapper::setQtDocInfo(const QString &component,
275 const QStringList &doc)
276{
278 d->m_helpEngine->setCustomValue(VersionKey.arg(component),
279 doc.join(CollectionConfiguration::ListSeparator));
280}
281
283{
285 return CollectionConfiguration::lastShownPages(*d->m_helpEngine);
286}
287
288void HelpEngineWrapper::setLastShownPages(const QStringList &lastShownPages)
289{
291 CollectionConfiguration::setLastShownPages(*d->m_helpEngine, lastShownPages);
292}
293
295{
297 return CollectionConfiguration::lastZoomFactors(*d->m_helpEngine);
298}
299
300void HelpEngineWrapper::setLastZoomFactors(const QStringList &lastZoomFactors)
301{
303 CollectionConfiguration::setLastZoomFactors(*d->m_helpEngine, lastZoomFactors);
304}
305
307{
309 return CollectionConfiguration::cacheDir(*d->m_helpEngine);
310}
311
317
318void HelpEngineWrapper::setCacheDir(const QString &cacheDir,
319 bool relativeToCollection)
320{
322 CollectionConfiguration::setCacheDir(*d->m_helpEngine, cacheDir,
323 relativeToCollection);
324}
325
331
338
344
350
356
358{
361}
362
368
370{
373}
374
380
387
389{
391 return CollectionConfiguration::aboutMenuTexts(*d->m_helpEngine);
392}
393
394void HelpEngineWrapper::setAboutMenuTexts(const QByteArray &texts)
395{
397 CollectionConfiguration::setAboutMenuTexts(*d->m_helpEngine, texts);
398}
399
401{
403 return CollectionConfiguration::aboutIcon(*d->m_helpEngine);
404}
405
406void HelpEngineWrapper::setAboutIcon(const QByteArray &icon)
407{
409 CollectionConfiguration::setAboutIcon(*d->m_helpEngine, icon);
410}
411
413{
415 return CollectionConfiguration::aboutImages(*d->m_helpEngine);
416}
417
418void HelpEngineWrapper::setAboutImages(const QByteArray &images)
419{
421 CollectionConfiguration::setAboutImages(*d->m_helpEngine, images);
422}
423
425{
427 return CollectionConfiguration::aboutTexts(*d->m_helpEngine);
428}
429
430void HelpEngineWrapper::setAboutTexts(const QByteArray &texts)
431{
433 CollectionConfiguration::setAboutTexts(*d->m_helpEngine, texts);
434}
435
437{
439 return CollectionConfiguration::windowTitle(*d->m_helpEngine);
440}
441
442void HelpEngineWrapper::setWindowTitle(const QString &windowTitle)
443{
445 CollectionConfiguration::setWindowTitle(*d->m_helpEngine, windowTitle);
446}
447
449{
451 return CollectionConfiguration::applicationIcon(*d->m_helpEngine);
452}
453
454void HelpEngineWrapper::setApplicationIcon(const QByteArray &icon)
455{
457 CollectionConfiguration::setApplicationIcon(*d->m_helpEngine, icon);
458}
459
461{
463 return d->m_helpEngine->customValue(MainWindowKey).toByteArray();
464}
465
466void HelpEngineWrapper::setMainWindow(const QByteArray &mainWindow)
467{
469 d->m_helpEngine->setCustomValue(MainWindowKey, mainWindow);
470}
471
473{
475 return d->m_helpEngine->customValue(MainWindowGeometryKey).toByteArray();
476}
477
478void HelpEngineWrapper::setMainWindowGeometry(const QByteArray &geometry)
479{
481 d->m_helpEngine->setCustomValue(MainWindowGeometryKey, geometry);
482}
483
485{
487 return d->m_helpEngine->customValue(BookmarksKey).toByteArray();
488}
489
490void HelpEngineWrapper::setBookmarks(const QByteArray &bookmarks)
491{
493 d->m_helpEngine->setCustomValue(BookmarksKey, bookmarks);
494}
495
497{
499 return CollectionConfiguration::lastTabPage(*d->m_helpEngine);
500}
501
503{
505 CollectionConfiguration::setLastTabPage(*d->m_helpEngine, lastPage);
506}
507
509{
511 return d->m_helpEngine->customValue(StartOptionKey, ShowLastPages).toInt();
512}
513
515{
517 d->m_helpEngine->setCustomValue(StartOptionKey, option);
518}
519
521{
523 const QString &homePage
524 = d->m_helpEngine->customValue(HomePageKey).toString();
525 if (!homePage.isEmpty())
526 return homePage;
527 return defaultHomePage();
528}
529
530void HelpEngineWrapper::setHomePage(const QString &page)
531{
533 d->m_helpEngine->setCustomValue(HomePageKey, page);
534
535}
536
538{
540 return CollectionConfiguration::defaultHomePage(*d->m_helpEngine);
541}
542
543void HelpEngineWrapper::setDefaultHomePage(const QString &page)
544{
546 CollectionConfiguration::setDefaultHomePage(*d->m_helpEngine, page);
547}
548
550{
552 return d->m_helpEngine->customValue(UseAppFontKey).isValid();
553}
554
556{
558 return d->m_helpEngine->customValue(UseAppFontKey).toBool();
559}
560
561void HelpEngineWrapper::setUseAppFont(bool useAppFont)
562{
564 d->m_helpEngine->setCustomValue(UseAppFontKey, useAppFont);
565}
566
568{
570 return d->m_helpEngine->customValue(UseBrowserFontKey, false).toBool();
571}
572
573void HelpEngineWrapper::setUseBrowserFont(bool useBrowserFont)
574{
576 d->m_helpEngine->setCustomValue(UseBrowserFontKey, useBrowserFont);
577}
578
580{
582 return qvariant_cast<QFont>(d->m_helpEngine->customValue(AppFontKey));
583}
584
585void HelpEngineWrapper::setAppFont(const QFont &font)
586{
588 d->m_helpEngine->setCustomValue(AppFontKey, font);
589}
590
592{
594 return static_cast<QFontDatabase::WritingSystem>(
595 d->m_helpEngine->customValue(AppWritingSystemKey).toInt());
596}
597
598void HelpEngineWrapper::setAppWritingSystem(QFontDatabase::WritingSystem system)
599{
601 d->m_helpEngine->setCustomValue(AppWritingSystemKey, system);
602}
603
605{
607 return qvariant_cast<QFont>(d->m_helpEngine->customValue(BrowserFontKey));
608}
609
610void HelpEngineWrapper::setBrowserFont(const QFont &font)
611{
613 d->m_helpEngine->setCustomValue(BrowserFontKey, font);
614}
615
617{
619 return static_cast<QFontDatabase::WritingSystem>(
620 d->m_helpEngine->customValue(BrowserWritingSystemKey).toInt());
621}
622
623void HelpEngineWrapper::setBrowserWritingSystem(QFontDatabase::WritingSystem system)
624{
626 d->m_helpEngine->setCustomValue(BrowserWritingSystemKey, system);
627}
628
630{
632 return d->m_helpEngine->customValue(ShowTabsKey, false).toBool();
633}
634
636{
638 d->m_helpEngine->setCustomValue(ShowTabsKey, show);
639}
640
646
648{
650 return d->m_helpEngine->customValue(TopicChooserGeometryKey).toByteArray();
651}
652
653void HelpEngineWrapper::setTopicChooserGeometry(const QByteArray &geometry)
654{
656 d->m_helpEngine->setCustomValue(TopicChooserGeometryKey, geometry);
657}
658
659QHelpEngineCore *HelpEngineWrapper::helpEngine() const
660{
661 return d->m_helpEngine;
662}
663
664
665// -- TimeoutForwarder
666
667TimeoutForwarder::TimeoutForwarder(const QString &fileName)
668 : m_fileName(fileName)
669{
671}
672
673void TimeoutForwarder::forward()
674{
676 HelpEngineWrapper::instance().d->qchFileChanged(m_fileName, true);
677}
678
679// -- HelpEngineWrapperPrivate
680
681HelpEngineWrapperPrivate::HelpEngineWrapperPrivate(const QString &collectionFile)
682 : m_helpEngine(new QHelpEngine(collectionFile, this)),
683 m_qchWatcher(new QFileSystemWatcher(this))
684{
686 m_helpEngine->setReadOnly(false);
687 m_helpEngine->setUsesFilterEngine(true);
688 removeStaleDocumentation();
689 initFileSystemWatchers();
690}
691
692/*
693 * A qch file holds exactly one namespace. If a file was regenerated for another
694 * version, the registered namespace no longer matches the file's own one.
695 * Files that can't be read (e.g. missing) are left registered.
696 */
697void HelpEngineWrapperPrivate::removeStaleDocumentation()
698{
700 const auto &docs = m_helpEngine->registeredDocumentations();
701 for (const QString &ns : docs) {
702 const QString fileNs = QHelpEngineCore::namespaceName(
703 m_helpEngine->documentationFileName(ns));
704 if (!fileNs.isEmpty() && fileNs != ns)
705 m_helpEngine->unregisterDocumentation(ns);
706 }
707}
708
709void HelpEngineWrapperPrivate::initFileSystemWatchers()
710{
712 const auto &docs = m_helpEngine->registeredDocumentations();
713 for (const QString &ns : docs)
714 m_qchWatcher->addPath(m_helpEngine->documentationFileName(ns));
715
716 connect(m_qchWatcher, &QFileSystemWatcher::fileChanged, this,
717 QOverload<const QString &>::of(&HelpEngineWrapperPrivate::qchFileChanged));
718 checkDocFilesWatched();
719}
720
721void HelpEngineWrapperPrivate::qchFileChanged(const QString &fileName)
722{
724 qchFileChanged(fileName, false);
725}
726
727void HelpEngineWrapperPrivate::checkDocFilesWatched()
728{
730 const int watchedFilesCount = m_qchWatcher->files().size();
731 const int docFilesCount = m_helpEngine->registeredDocumentations().size();
732 if (watchedFilesCount != docFilesCount) {
733 qWarning("Strange: Have %d docs, but %d are being watched",
734 docFilesCount, watchedFilesCount);
735 }
736}
737
738void HelpEngineWrapperPrivate::qchFileChanged(const QString &fileName,
739 bool fromTimeout)
740{
742
743 /*
744 * We don't use QHelpEngineCore::namespaceName(fileName), because the file
745 * may not exist anymore or contain a different namespace.
746 */
747 QString ns;
748 const auto &docs = m_helpEngine->registeredDocumentations();
749 for (const QString &curNs : docs) {
750 if (m_helpEngine->documentationFileName(curNs) == fileName) {
751 ns = curNs;
752 break;
753 }
754 }
755
756 /*
757 * We can't do an assertion here, because QFileSystemWatcher may send the
758 * signal more than once.
759 */
760 if (ns.isEmpty()) {
761 m_recentQchUpdates.erase(fileName);
762 return;
763 }
764
765 /*
766 * Since the QFileSystemWatcher typically sends the signal more than once,
767 * we repeatedly delay our reaction a bit until we think the last signal
768 * was sent.
769 */
770
771 const auto &it = m_recentQchUpdates.find(fileName);
772 const QDateTime now = QDateTime::currentDateTimeUtc();
773
774 // Case 1: This is the first recent signal for the file.
775 if (it == m_recentQchUpdates.end()) {
776 auto forwarder = std::make_unique<TimeoutForwarder>(fileName);
777 QTimer::singleShot(UpdateGracePeriod, forwarder.get(),
778 &TimeoutForwarder::forward);
779 m_recentQchUpdates.emplace(fileName,
780 RecentSignal{std::move(now), std::move(forwarder)});
781 return;
782 }
783
784 auto &[key, entry] = *it;
785
786 // Case 2: The last signal for this file has not expired yet.
787 if (entry.timestamp > now.addMSecs(-UpdateGracePeriod)) {
788 if (!fromTimeout)
789 entry.timestamp = now;
790 else
791 QTimer::singleShot(UpdateGracePeriod, entry.forwarder.get(),
792 &TimeoutForwarder::forward);
793 return;
794 }
795
796 // Case 3: The last signal for this file has expired.
797 if (m_helpEngine->unregisterDocumentation(ns)) {
798 if (!QFileInfo(fileName).exists()
799 || !m_helpEngine->registerDocumentation(fileName)) {
800 m_qchWatcher->removePath(fileName);
801 emit documentationRemoved(ns);
802 } else {
803 emit documentationUpdated(ns);
804 }
805 m_helpEngine->setupData();
806 }
807 m_recentQchUpdates.erase(it);
808}
809
810QT_END_NAMESPACE
811
812#include "helpenginewrapper.moc"
static bool filterFunctionalityEnabled(const QHelpEngineCore &helpEngine)
static void setLastTabPage(QHelpEngineCore &helpEngine, int lastPage)
static bool addressBarVisible(const QHelpEngineCore &helpEngine)
static bool addressBarEnabled(const QHelpEngineCore &helpEngine)
static void setAddressBarVisible(QHelpEngineCore &helpEngine, bool visible)
static void setDocumentationManagerEnabled(QHelpEngineCore &helpEngine, bool enabled)
static bool documentationManagerEnabled(const QHelpEngineCore &helpEngine)
static void setAddressBarEnabled(QHelpEngineCore &helpEngine, bool enabled)
static int lastTabPage(const QHelpEngineCore &helpEngine)
static bool cacheDirIsRelativeToCollection(const QHelpEngineCore &helpEngine)
static void setFilterToolbarVisible(QHelpEngineCore &helpEngine, bool visible)
static void setFilterFunctionalityEnabled(QHelpEngineCore &helpEngine, bool enabled)
static bool filterToolbarVisible(const QHelpEngineCore &helpEngine)
static bool fullTextSearchFallbackEnabled(const QHelpEngineCore &helpEngine)
void documentationUpdated(const QString &namespaceName)
void setHomePage(const QString &page)
QHelpEngineCore * helpEngine() const
QHelpFilterEngine * filterEngine() const
bool registerDocumentation(const QString &docFile)
const QString defaultHomePage() const
void setStartOption(int option)
QHelpSearchEngine * searchEngine() const
const QByteArray bookmarks() const
const QStringList lastShownPages() const
void setDefaultHomePage(const QString &page)
static void removeInstance()
const QString homePage() const
bool fullTextSearchFallbackEnabled() const
void setAddressBarEnabled(bool enabled)
QHelpIndexWidget * indexWidget()
bool cacheDirIsRelativeToCollection() const
const QString windowTitle() const
void setLastZoomFactors(const QStringList &lastZoomFactors)
void setFilterFunctionalityEnabled(bool enabled)
void setShowTabs(bool show)
const QStringList qtDocInfo(const QString &component) const
void setBookmarks(const QByteArray &bookmarks)
const QByteArray mainWindow() const
static HelpEngineWrapper & instance()
const QByteArray mainWindowGeometry() const
void setBrowserFont(const QFont &font)
const QByteArray topicChooserGeometry() const
bool addressBarEnabled() const
const QFont browserFont() const
void setAboutMenuTexts(const QByteArray &texts)
void setFilterToolbarVisible(bool visible)
const QByteArray aboutMenuTexts() const
const QString collectionFile() const
void setAppWritingSystem(QFontDatabase::WritingSystem system)
QByteArray fileData(const QUrl &url) const
void setBrowserWritingSystem(QFontDatabase::WritingSystem system)
void setAppFont(const QFont &font)
bool unregisterDocumentation(const QString &namespaceName)
bool addressBarVisible() const
void setAboutIcon(const QByteArray &icon)
void setUseBrowserFont(bool useBrowserFont)
void setCacheDir(const QString &cacheDir, bool relativeToCollection)
bool documentationManagerEnabled() const
QFontDatabase::WritingSystem browserWritingSystem() const
void setApplicationIcon(const QByteArray &icon)
const QStringList registeredDocumentations() const
QHelpContentWidget * contentWidget()
const QByteArray aboutTexts() const
QHelpIndexModel * indexModel() const
void setAboutImages(const QByteArray &images)
void setTopicChooserGeometry(const QByteArray &geometry)
bool filterFunctionalityEnabled() const
void setMainWindowGeometry(const QByteArray &geometry)
void setAboutTexts(const QByteArray &texts)
void setAddressBarVisible(bool visible)
void setLastTabPage(int lastPage)
const QString cacheDir() const
QUrl findFile(const QUrl &url) const
const QStringList lastZoomFactors() const
const QByteArray applicationIcon() const
const QByteArray aboutImages() const
QList< QHelpLink > documentsForIdentifier(const QString &id) const
QFontDatabase::WritingSystem appWritingSystem() const
void setQtDocInfo(const QString &component, const QStringList &doc)
void setDocumentationManagerEnabled(bool enabled)
void setWindowTitle(const QString &windowTitle)
bool filterToolbarVisible() const
const QByteArray aboutIcon() const
void setUseAppFont(bool useAppFont)
QHelpContentModel * contentModel() const
void setLastShownPages(const QStringList &lastShownPages)
void setMainWindow(const QByteArray &mainWindow)
QString documentationFileName(const QString &namespaceName) const
const QFont appFont() const
@ ShowLastPages
#define TRACE_OBJ
Definition tracer.h:34