43 fputs(qPrintable(QHG::tr(
"Reading collection config file...\n")), stdout);
44 CollectionConfigReader config;
45 config.readData(data);
46 if (config.hasError()) {
47 fputs(qPrintable(QHG::tr(
"Collection config file error: %1\n")
48 .arg(config.errorString())), stderr);
52 const QMap<QString, QString> &filesToGenerate = config.filesToGenerate();
53 for (
auto it = filesToGenerate.cbegin(), end = filesToGenerate.cend(); it != end; ++it) {
54 fputs(qPrintable(QHG::tr(
"Generating help for %1...\n").arg(it.key())), stdout);
56 if (!helpData.readData(absoluteFilePath(basePath, it.key()))) {
57 fprintf(stderr,
"%s\n", qPrintable(helpData.errorMessage()));
62 if (!helpGenerator.generate(&helpData, absoluteFilePath(basePath, it.value()))) {
63 fprintf(stderr,
"%s\n", qPrintable(helpGenerator.error()));
68 fputs(qPrintable(QHG::tr(
"Creating collection file...\n")), stdout);
70 QFileInfo colFi(outputFile);
72 if (!colFi.dir().remove(colFi.fileName())) {
73 fputs(qPrintable(QHG::tr(
"The file %1 cannot be overwritten.\n")
74 .arg(outputFile)), stderr);
79 QHelpEngineCore helpEngine(outputFile);
80 helpEngine.setReadOnly(
false);
81 if (!helpEngine.setupData()) {
82 fprintf(stderr,
"%s\n", qPrintable(helpEngine.error()));
86 for (
const QString &file : config.filesToRegister()) {
87 if (!helpEngine.registerDocumentation(absoluteFilePath(basePath, file))) {
88 fprintf(stderr,
"%s\n", qPrintable(helpEngine.error()));
92 if (!config.filesToRegister().isEmpty()) {
93 if (Q_UNLIKELY(qEnvironmentVariableIsSet(
"SOURCE_DATE_EPOCH"))) {
95 dt.setTimeZone(QTimeZone::UTC);
96 dt.setSecsSinceEpoch(qEnvironmentVariableIntValue(
"SOURCE_DATE_EPOCH"));
103 if (!config.title().isEmpty())
104 CollectionConfiguration::setWindowTitle(helpEngine, config.title());
106 if (!config.homePage().isEmpty()) {
107 CollectionConfiguration::setDefaultHomePage(helpEngine,
111 if (!config.startPage().isEmpty()) {
112 CollectionConfiguration::setLastShownPages(helpEngine,
113 QStringList(config.startPage()));
116 if (!config.currentFilter().isEmpty()) {
117 helpEngine.setCurrentFilter(config.currentFilter());
120 if (!config.cacheDirectory().isEmpty()) {
121 CollectionConfiguration::setCacheDir(helpEngine, config.cacheDirectory(),
122 config.cacheDirRelativeToCollection());
126 config.enableFilterFunctionality()
);
128 !config.hideFilterFunctionality()
);
130 config.enableDocumentationManager()
);
132 config.enableAddressBar()
);
134 !config.hideAddressBar()
);
135 uint time = QDateTime::currentMSecsSinceEpoch() / 1000;
136 if (Q_UNLIKELY(qEnvironmentVariableIsSet(
"SOURCE_DATE_EPOCH")))
137 time = qEnvironmentVariableIntValue(
"SOURCE_DATE_EPOCH");
138 CollectionConfiguration::setCreationTime(helpEngine, time);
140 config.fullTextSearchFallbackEnabled()
);
142 if (!config.applicationIcon().isEmpty()) {
143 QFile icon(absoluteFilePath(basePath, config.applicationIcon()));
144 if (!icon.open(QIODevice::ReadOnly)) {
145 fputs(qPrintable(QHG::tr(
"Cannot open %1.\n").arg(icon.fileName())), stderr);
148 CollectionConfiguration::setApplicationIcon(helpEngine, icon.readAll());
151 if (config.aboutMenuTexts().size()) {
153 QDataStream s(&ba, QIODevice::WriteOnly);
154 const QMap<QString, QString> &aboutMenuTexts = config.aboutMenuTexts();
155 for (
auto it = aboutMenuTexts.cbegin(), end = aboutMenuTexts.cend(); it != end; ++it)
156 s << it.key() << it.value();
157 CollectionConfiguration::setAboutMenuTexts(helpEngine, ba);
160 if (!config.aboutIcon().isEmpty()) {
161 QFile icon(absoluteFilePath(basePath, config.aboutIcon()));
162 if (!icon.open(QIODevice::ReadOnly)) {
163 fputs(qPrintable(QHG::tr(
"Cannot open %1.\n").arg(icon.fileName())), stderr);
166 CollectionConfiguration::setAboutIcon(helpEngine, icon.readAll());
169 if (config.aboutTextFiles().size()) {
171 QDataStream s(&ba, QIODevice::WriteOnly);
172 QMap<QString, QByteArray> imgData;
174 QRegularExpression srcRegExp(QLatin1String(
"src=(\"(.+)\"|([^\"\\s]+)).*>"), QRegularExpression::InvertedGreedinessOption);
175 QRegularExpression imgRegExp(QLatin1String(
"(<img[^>]+>)"), QRegularExpression::InvertedGreedinessOption);
177 const QMap<QString, QString> &aboutMenuTexts = config.aboutTextFiles();
178 for (
auto it = aboutMenuTexts.cbegin(), end = aboutMenuTexts.cend(); it != end; ++it) {
180 QFileInfo fi(absoluteFilePath(basePath, it.value()));
181 QFile f(fi.absoluteFilePath());
182 if (!f.open(QIODevice::ReadOnly)) {
183 fputs(qPrintable(QHG::tr(
"Cannot open %1.\n").arg(f.fileName())), stderr);
186 QByteArray data = f.readAll();
189 QString contents = QString::fromUtf8(data);
191 QRegularExpressionMatch match;
192 while ((match = imgRegExp.match(contents, pos)).hasMatch()) {
193 QString imgTag = match.captured(1);
194 pos = match.capturedEnd();
196 if ((match = srcRegExp.match(imgTag)).hasMatch()) {
197 QString src = match.captured(2);
199 src = match.captured(3);
201 QFile img(fi.absolutePath() + QDir::separator() + src);
202 if (img.open(QIODevice::ReadOnly)) {
203 if (!imgData.contains(src))
204 imgData.insert(src, img.readAll());
206 fputs(qPrintable(QHG::tr(
"Cannot open referenced image file %1.\n")
207 .arg(img.fileName())), stderr);
212 CollectionConfiguration::setAboutTexts(helpEngine, ba);
213 if (imgData.size()) {
214 QByteArray imageData;
215 QBuffer buffer(&imageData);
216 buffer.open(QIODevice::WriteOnly);
217 QDataStream out(&buffer);
219 CollectionConfiguration::setAboutImages(helpEngine, imageData);
225int main(
int argc,
char *argv[])
231 bool showHelp =
false;
232 bool showVersion =
false;
233 bool checkLinks =
false;
237 qputenv(
"QT_QPA_PLATFORM", QByteArrayLiteral(
"minimal"));
239 QGuiApplication app(argc, argv);
241 QTranslator translator;
242 QTranslator qtTranslator;
243 QTranslator qt_helpTranslator;
244 QString sysLocale = QLocale::system().name();
245 QString resourceDir = QLibraryInfo::path(QLibraryInfo::TranslationsPath);
246 if (translator.load(QLatin1String(
"assistant_") + sysLocale, resourceDir)
247 && qtTranslator.load(QLatin1String(
"qt_") + sysLocale, resourceDir)
248 && qt_helpTranslator.load(QLatin1String(
"qt_help_") + sysLocale, resourceDir)) {
249 app.installTranslator(&translator);
250 app.installTranslator(&qtTranslator);
251 app.installTranslator(&qt_helpTranslator);
255 for (
int i = 1; i < argc; ++i) {
256 const QString arg = QString::fromLocal8Bit(argv[i]);
257 if (arg == QLatin1String(
"-o")) {
259 QFileInfo fi(QString::fromLocal8Bit(argv[i]));
260 outputFile = fi.absoluteFilePath();
262 error = QHG::tr(
"Missing output file name.");
264 }
else if (arg == QLatin1String(
"-v")) {
266 }
else if (arg == QLatin1String(
"-h")) {
268 }
else if (arg == QLatin1String(
"-c")) {
270 }
else if (arg == QLatin1String(
"-s")) {
273 const QFileInfo fi(arg);
274 inputFile = fi.absoluteFilePath();
275 basePath = fi.absolutePath();
280 fputs(qPrintable(QHG::tr(
"Qt Help Generator version 1.0 (Qt %1)\n")
281 .arg(QT_VERSION_STR)), stdout);
291 InputType inputType = InputUnknown;
294 if (inputFile.isEmpty()) {
295 error = QHG::tr(
"Missing input file name.");
297 const QFileInfo fi(inputFile);
298 if (fi.suffix() ==
QHP)
299 inputType = InputQhp;
300 else if (fi.suffix() ==
QHCP)
301 inputType = InputQhcp;
303 if (inputType == InputUnknown)
304 error = QHG::tr(
"Unknown input file type.");
308 const QString help = QHG::tr(
"\nUsage:\n\n"
309 "qhelpgenerator <file> [options]\n\n"
310 " -o <output-file> Generates a Qt compressed help\n"
311 " called <output-file> (*.qch) for the\n"
312 " Qt help project <file> (*.qhp).\n"
313 " Generates a Qt help collection\n"
314 " called <output-file> (*.qhc) for the\n"
315 " Qt help collection project <file> (*.qhcp).\n"
316 " If this option is not specified\n"
317 " a default name will be used\n"
318 " (*.qch for *.qhp and *.qhc for *.qhcp).\n"
319 " -c Checks whether all links in HTML files\n"
320 " point to files in this help project.\n"
321 " -s Suppresses status messages.\n"
322 " -v Displays the version of \n"
323 " qhelpgenerator.\n\n");
326 fputs(qPrintable(help), stdout);
328 }
else if (!error.isEmpty()) {
329 fprintf(stderr,
"%s\n\n%s", qPrintable(error), qPrintable(help));
335 QFile file(inputFile);
336 if (!file.open(QIODevice::ReadOnly)) {
337 fputs(qPrintable(QHG::tr(
"Could not open %1.\n").arg(inputFile)), stderr);
341 const QString outputExtension = inputType == InputQhp ? QCH : QHC;
343 if (outputFile.isEmpty()) {
344 if (inputType == InputQhcp || !checkLinks) {
345 QFileInfo fi(inputFile);
346 outputFile = basePath + QDir::separator()
347 + fi.baseName() + QLatin1Char(
'.') + outputExtension;
351 QFileInfo fi(outputFile);
352 QDir parentDir = fi.dir();
353 if (!parentDir.exists()) {
354 if (!parentDir.mkpath(QLatin1String(
"."))) {
355 fputs(qPrintable(QHG::tr(
"Could not create output directory: %1\n")
356 .arg(parentDir.path())), stderr);
361 if (inputType == InputQhp) {
363 if (!helpData->readData(inputFile)) {
364 fprintf(stderr,
"%s\n", qPrintable(helpData->errorMessage()));
372 if (success && !outputFile.isEmpty())
373 success = generator.generate(helpData, outputFile);
376 fprintf(stderr,
"%s\n", qPrintable(generator.error()));
380 const QByteArray data = file.readAll();
381 return generateCollectionFile(data, basePath, outputFile);