Введение
В предыдущей статье мы разобрали архитектуру в целом — теперь пройдём полный практический путь от пустой директории до готового, протестированного .qch-файла, который можно открыть в Qt Assistant. В статье построим минимальную, но полностью работающую справку для гипотетического приложения, включая правильную настройку путей и проверку результата.
Концепция
Процесс сборки .qch состоит из трёх шагов: подготовка HTML-контента (обычные статические HTML-файлы, без специфичных для Qt тегов — это просто веб-страницы), описание структуры в .qhp-файле (TOC, индекс, список файлов — как в предыдущей статье), и компиляция через консольный инструмент qhelpgenerator, поставляемый вместе с Qt SDK. Результат — единый файл .qch, который полностью самодостаточен и может быть открыт независимо, без доступа к исходным HTML-файлам, поскольку весь контент уже встроен внутрь скомпилированного файла.
Пример кода: Создание .qch-файла с нуля
<!-- docs/source/index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>MyApp — Справка</title>
<link rel="stylesheet" href="../style.css">
</head>
<body>
<h1>Добро пожаловать в справку MyApp</h1>
<p>Эта справка поможет вам начать работу с приложением.</p>
<ul>
<li><a href="getting_started.html">Начало работы</a></li>
<li><a href="api_reference.html">Справочник API</a></li>
</ul>
</body>
</html>
<!-- docs/source/getting_started.html -->
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Начало работы</title></head>
<body>
<h1>Начало работы</h1>
<h2 id="install">Установка</h2>
<p>Скачайте установщик с официального сайта и запустите его.</p>
<h2 id="first-launch">Первый запуск</h2>
<p>При первом запуске будет предложено настроить базовые параметры.</p>
</body>
</html>
<!-- docs/myapp.qhp -->
<?xml version="1.0" encoding="UTF-8"?>
<QtHelpProject version="1.0">
<namespace>com.mycompany.myapp.1.0</namespace>
<virtualFolder>doc</virtualFolder>
<customFilter name="MyApp 1.0">
<filterAttribute>myapp</filterAttribute>
<filterAttribute>1.0</filterAttribute>
</customFilter>
<filterSection>
<filterAttribute>myapp</filterAttribute>
<filterAttribute>1.0</filterAttribute>
<toc>
<section title="MyApp — Справка" ref="source/index.html">
<section title="Начало работы" ref="source/getting_started.html">
<section title="Установка" ref="source/getting_started.html#install" />
<section title="Первый запуск" ref="source/getting_started.html#first-launch" />
</section>
</section>
</toc>
<keywords>
<keyword name="установка" ref="source/getting_started.html#install" />
<keyword name="первый запуск" ref="source/getting_started.html#first-launch" />
</keywords>
<files>
<file>source/index.html</file>
<file>source/getting_started.html</file>
<file>style.css</file>
</files>
</filterSection>
</QtHelpProject>
# Сборка и проверка результата
cd docs
qhelpgenerator myapp.qhp -o myapp.qch
# Быстрая проверка содержимого скомпилированного файла без приложения
assistant -collectionFile myapp.qhc # либо открыть .qch напрямую через Assistant
Пояснения к коду
<customFilter> и парные <filterAttribute> внутри <filterSection> — механизм фильтрации контента: если в одном .qhp-проекте описано несколько наборов страниц для разных версий или конфигураций продукта, фильтры позволяют скомпилировать или отобрать для отображения только нужное подмножество; для простого случая (как в примере) фильтр просто помечает весь контент единым набором атрибутов.
Привязка к конкретным заголовкам внутри страницы через id (<h2 id="install">) и ссылка на них в .qhp через #install в ref позволяет TOC и индексу указывать не просто на страницу целиком, а на конкретный раздел внутри неё — открытие такой ссылки в справочном браузере сразу прокручивает страницу к нужному месту, что особенно важно для длинных страниц с множеством подразделов.
Подводные камни
- Относительные пути в HTML, не совпадающие с реальной структурой после компиляции. Ссылки между HTML-страницами (
href="getting_started.html") должны быть относительными путями, соответствующими структуре, описанной в .qhp — абсолютные пути или пути, выходящие за пределы директории проекта справки, не будут корректно разрешены внутри скомпилированного .qch. - Отсутствие проверки на пустые или «битые» якоря (
#install). Если HTML-файл не содержит элемента с указаннымid, ссылка не выдаст ошибку при компиляции .qhp, но при открытии в браузере справки просто не произойдёт прокрутки к ожидаемому месту — этот класс ошибок обнаруживается только при ручном тестировании каждой ссылки. - Запуск
qhelpgeneratorбез указания-oили с неверным относительным путём к выходному файлу может привести к созданию .qch в неожиданном месте файловой системы — особенно при автоматизации сборки через CI или CMake, где рабочая директория может отличаться от ожидаемой при ручном запуске из терминала. - Несинхронизированное обновление .qch после изменения HTML-исходников. Поскольку .qch — это скомпилированный, самодостаточный артефакт, изменение исходных HTML-файлов не отражается в уже работающем приложении автоматически — нужен явный шаг пересборки .qch и его повторного развёртывания вместе с приложением, который легко забыть включить в общий пайплайн сборки релиза.