44 fputs(qPrintable(QHG::tr(
"Reading collection config file...\n")), stdout);
45 CollectionConfigReader config;
46 config.readData(data);
47 if (config.hasError()) {
48 fputs(qPrintable(QHG::tr(
"Collection config file error: %1\n")
49 .arg(config.errorString())), stderr);
53 const QMap<QString, QString> &filesToGenerate = config.filesToGenerate();
54 for (
auto it = filesToGenerate.cbegin(), end = filesToGenerate.cend(); it != end; ++it) {
55 fputs(qPrintable(QHG::tr(
"Generating help for %1...\n").arg(it.key())), stdout);
57 if (!helpData.readData(absoluteFilePath(basePath, it.key()))) {
58 fprintf(stderr,
"%s\n", qPrintable(helpData.errorMessage()));
63 if (!helpGenerator.generate(&helpData, absoluteFilePath(basePath, it.value()))) {
64 fprintf(stderr,
"%s\n", qPrintable(helpGenerator.error()));
69 fputs(qPrintable(QHG::tr(
"Creating collection file...\n")), stdout);
71 QFileInfo colFi(outputFile);
73 if (!colFi.dir().remove(colFi.fileName())) {
74 fputs(qPrintable(QHG::tr(
"The file %1 cannot be overwritten.\n")
75 .arg(outputFile)), stderr);
80 QHelpEngineCore helpEngine(outputFile);
81 helpEngine.setReadOnly(
false);
82 if (!helpEngine.setupData()) {
83 fprintf(stderr,
"%s\n", qPrintable(helpEngine.error()));
87 for (
const QString &file : config.filesToRegister()) {
88 if (!helpEngine.registerDocumentation(absoluteFilePath(basePath, file))) {
89 fprintf(stderr,
"%s\n", qPrintable(helpEngine.error()));
93 if (!config.filesToRegister().isEmpty()) {
94 if (Q_UNLIKELY(qEnvironmentVariableIsSet(
"SOURCE_DATE_EPOCH"))) {
96 dt.setTimeZone(QTimeZone::UTC);
97 dt.setSecsSinceEpoch(qEnvironmentVariableIntValue(
"SOURCE_DATE_EPOCH"));
104 if (!config.title().isEmpty())
105 CollectionConfiguration::setWindowTitle(helpEngine, config.title());
107 if (!config.homePage().isEmpty()) {
108 CollectionConfiguration::setDefaultHomePage(helpEngine,
112 if (!config.startPage().isEmpty()) {
113 CollectionConfiguration::setLastShownPages(helpEngine,
114 QStringList(config.startPage()));
117 if (!config.currentFilter().isEmpty()) {
118 helpEngine.setCurrentFilter(config.currentFilter());
121 if (!config.cacheDirectory().isEmpty()) {
122 CollectionConfiguration::setCacheDir(helpEngine, config.cacheDirectory(),
123 config.cacheDirRelativeToCollection());
127 config.enableFilterFunctionality()
);
129 !config.hideFilterFunctionality()
);
131 config.enableDocumentationManager()
);
133 config.enableAddressBar()
);
135 !config.hideAddressBar()
);
136 uint time = QDateTime::currentMSecsSinceEpoch() / 1000;
137 if (Q_UNLIKELY(qEnvironmentVariableIsSet(
"SOURCE_DATE_EPOCH")))
138 time = qEnvironmentVariableIntValue(
"SOURCE_DATE_EPOCH");
139 CollectionConfiguration::setCreationTime(helpEngine, time);
141 config.fullTextSearchFallbackEnabled()
);
143 if (!config.applicationIcon().isEmpty()) {
144 QFile icon(absoluteFilePath(basePath, config.applicationIcon()));
145 if (!icon.open(QIODevice::ReadOnly)) {
146 fputs(qPrintable(QHG::tr(
"Cannot open %1.\n").arg(icon.fileName())), stderr);
149 CollectionConfiguration::setApplicationIcon(helpEngine, icon.readAll());
152 if (config.aboutMenuTexts().size()) {
154 QDataStream s(&ba, QIODevice::WriteOnly);
155 const QMap<QString, QString> &aboutMenuTexts = config.aboutMenuTexts();
156 for (
auto it = aboutMenuTexts.cbegin(), end = aboutMenuTexts.cend(); it != end; ++it)
157 s << it.key() << it.value();
158 CollectionConfiguration::setAboutMenuTexts(helpEngine, ba);
161 if (!config.aboutIcon().isEmpty()) {
162 QFile icon(absoluteFilePath(basePath, config.aboutIcon()));
163 if (!icon.open(QIODevice::ReadOnly)) {
164 fputs(qPrintable(QHG::tr(
"Cannot open %1.\n").arg(icon.fileName())), stderr);
167 CollectionConfiguration::setAboutIcon(helpEngine, icon.readAll());
170 if (config.aboutTextFiles().size()) {
172 QDataStream s(&ba, QIODevice::WriteOnly);
173 QMap<QString, QByteArray> imgData;
175 QRegularExpression srcRegExp(QLatin1String(
"src=(\"(.+)\"|([^\"\\s]+)).*>"), QRegularExpression::InvertedGreedinessOption);
176 QRegularExpression imgRegExp(QLatin1String(
"(<img[^>]+>)"), QRegularExpression::InvertedGreedinessOption);
178 const QMap<QString, QString> &aboutMenuTexts = config.aboutTextFiles();
179 for (
auto it = aboutMenuTexts.cbegin(), end = aboutMenuTexts.cend(); it != end; ++it) {
181 QFileInfo fi(absoluteFilePath(basePath, it.value()));
182 QFile f(fi.absoluteFilePath());
183 if (!f.open(QIODevice::ReadOnly)) {
184 fputs(qPrintable(QHG::tr(
"Cannot open %1.\n").arg(f.fileName())), stderr);
187 QByteArray data = f.readAll();
190 QString contents = QString::fromUtf8(data);
192 QRegularExpressionMatch match;
193 while ((match = imgRegExp.match(contents, pos)).hasMatch()) {
194 QString imgTag = match.captured(1);
195 pos = match.capturedEnd();
197 if ((match = srcRegExp.match(imgTag)).hasMatch()) {
198 QString src = match.captured(2);
200 src = match.captured(3);
202 QFile img(fi.absolutePath() + QDir::separator() + src);
203 if (img.open(QIODevice::ReadOnly)) {
204 if (!imgData.contains(src))
205 imgData.insert(src, img.readAll());
207 fputs(qPrintable(QHG::tr(
"Cannot open referenced image file %1.\n")
208 .arg(img.fileName())), stderr);
213 CollectionConfiguration::setAboutTexts(helpEngine, ba);
214 if (imgData.size()) {
215 QByteArray imageData;
216 QBuffer buffer(&imageData);
217 buffer.open(QIODevice::WriteOnly);
218 QDataStream out(&buffer);
220 CollectionConfiguration::setAboutImages(helpEngine, imageData);
226int main(
int argc,
char *argv[])
232 bool showHelp =
false;
233 bool showVersion =
false;
234 bool checkLinks =
false;
238 qputenv(
"QT_QPA_PLATFORM", QByteArrayLiteral(
"minimal"));
240 QGuiApplication app(argc, argv);
242 QTranslator translator;
243 QTranslator qtTranslator;
244 QTranslator qt_helpTranslator;
245 QString sysLocale = QLocale::system().name();
246 QString resourceDir = QLibraryInfo::paths(QLibraryInfo::TranslationsPath).value(0);
247 if (translator.load(QLatin1String(
"assistant_") + sysLocale, resourceDir)
248 && qtTranslator.load(QLatin1String(
"qt_") + sysLocale, resourceDir)
249 && qt_helpTranslator.load(QLatin1String(
"qt_help_") + sysLocale, resourceDir)) {
250 app.installTranslator(&translator);
251 app.installTranslator(&qtTranslator);
252 app.installTranslator(&qt_helpTranslator);
256 for (
int i = 1; i < argc; ++i) {
257 const QString arg = QString::fromLocal8Bit(argv[i]);
258 if (arg == QLatin1String(
"-o")) {
260 QFileInfo fi(QString::fromLocal8Bit(argv[i]));
261 outputFile = fi.absoluteFilePath();
263 error = QHG::tr(
"Missing output file name.");
265 }
else if (arg == QLatin1String(
"-v")) {
267 }
else if (arg == QLatin1String(
"-h")) {
269 }
else if (arg == QLatin1String(
"-c")) {
271 }
else if (arg == QLatin1String(
"-s")) {
274 const QFileInfo fi(arg);
275 inputFile = fi.absoluteFilePath();
276 basePath = fi.absolutePath();
281 fputs(qPrintable(QHG::tr(
"Qt Help Generator version 1.0 (Qt %1)\n")
282 .arg(QT_VERSION_STR)), stdout);
292 InputType inputType = InputUnknown;
295 if (inputFile.isEmpty()) {
296 error = QHG::tr(
"Missing input file name.");
298 const QFileInfo fi(inputFile);
299 if (fi.suffix() ==
QHP)
300 inputType = InputQhp;
301 else if (fi.suffix() ==
QHCP)
302 inputType = InputQhcp;
304 if (inputType == InputUnknown)
305 error = QHG::tr(
"Unknown input file type.");
309 const QString help = QHG::tr(
"\nUsage:\n\n"
310 "qhelpgenerator <file> [options]\n\n"
311 " -o <output-file> Generates a Qt compressed help\n"
312 " called <output-file> (*.qch) for the\n"
313 " Qt help project <file> (*.qhp).\n"
314 " Generates a Qt help collection\n"
315 " called <output-file> (*.qhc) for the\n"
316 " Qt help collection project <file> (*.qhcp).\n"
317 " If this option is not specified\n"
318 " a default name will be used\n"
319 " (*.qch for *.qhp and *.qhc for *.qhcp).\n"
320 " -c Checks whether all links in HTML files\n"
321 " point to files in this help project.\n"
322 " -s Suppresses status messages.\n"
323 " -v Displays the version of \n"
324 " qhelpgenerator.\n\n");
327 fputs(qPrintable(help), stdout);
329 }
else if (!error.isEmpty()) {
330 fprintf(stderr,
"%s\n\n%s", qPrintable(error), qPrintable(help));
336 QFile file(inputFile);
337 if (!file.open(QIODevice::ReadOnly)) {
338 fputs(qPrintable(QHG::tr(
"Could not open %1.\n").arg(inputFile)), stderr);
342 const QString outputExtension = inputType == InputQhp ?
QCH :
QHC;
344 if (outputFile.isEmpty()) {
345 if (inputType == InputQhcp || !checkLinks) {
346 QFileInfo fi(inputFile);
347 outputFile = basePath + QDir::separator()
348 + fi.baseName() + QLatin1Char(
'.') + outputExtension;
352 QFileInfo fi(outputFile);
353 QDir parentDir = fi.dir();
354 if (!parentDir.exists()) {
355 if (!parentDir.mkpath(QLatin1String(
"."))) {
356 fputs(qPrintable(QHG::tr(
"Could not create output directory: %1\n")
357 .arg(parentDir.path())), stderr);
362 if (inputType == InputQhp) {
364 if (!helpData->readData(inputFile)) {
365 fprintf(stderr,
"%s\n", qPrintable(helpData->errorMessage()));
373 if (success && !outputFile.isEmpty())
374 success = generator.generate(helpData, outputFile);
377 fprintf(stderr,
"%s\n", qPrintable(generator.error()));
381 const QByteArray data = file.readAll();
382 return generateCollectionFile(data, basePath, outputFile);