diff options
author | Jarek Kobus <jaroslaw.kobus@qt.io> | 2018-07-12 16:38:30 +0200 |
---|---|---|
committer | Jarek Kobus <jaroslaw.kobus@qt.io> | 2018-07-26 05:55:57 +0000 |
commit | 30a75f7f0d540b5fd312b3cb2cf850e4e177c68b (patch) | |
tree | 1bfa56e2abdce37412158ec9548eb833df1a9462 /src/assistant | |
parent | caf3b6c291d3659d9fbc083ccf26fa178a3d38dc (diff) |
Merge qcollectiongenerator into qhelpgenerator tool
Change-Id: I3c961d7c13ce4f9a3aa36dd0554ec5184fbc5953
Reviewed-by: Kai Koehne <kai.koehne@qt.io>
Diffstat (limited to 'src/assistant')
-rw-r--r-- | src/assistant/assistant.pro | 5 | ||||
-rw-r--r-- | src/assistant/assistant/doc/snippets/doc_src_assistant-manual.qdoc | 2 | ||||
-rw-r--r-- | src/assistant/assistant/doc/src/assistant-manual.qdoc | 4 | ||||
-rw-r--r-- | src/assistant/help/Qt5HelpConfigExtras.cmake.in | 15 | ||||
-rw-r--r-- | src/assistant/help/doc/snippets/doc_src_qthelp.qdoc | 2 | ||||
-rw-r--r-- | src/assistant/help/doc/src/qthelp.qdoc | 37 | ||||
-rw-r--r-- | src/assistant/qcollectiongenerator/main.cpp | 610 | ||||
-rw-r--r-- | src/assistant/qcollectiongenerator/qcollectiongenerator.pro | 11 | ||||
-rw-r--r-- | src/assistant/qhelpgenerator/collectionconfigreader.cpp | 258 | ||||
-rw-r--r-- | src/assistant/qhelpgenerator/collectionconfigreader.h | 117 | ||||
-rw-r--r-- | src/assistant/qhelpgenerator/main.cpp | 319 | ||||
-rw-r--r-- | src/assistant/qhelpgenerator/qhelpgenerator.pro | 8 |
12 files changed, 681 insertions, 707 deletions
diff --git a/src/assistant/assistant.pro b/src/assistant/assistant.pro index 122a93b73..ec6377db5 100644 --- a/src/assistant/assistant.pro +++ b/src/assistant/assistant.pro @@ -3,15 +3,12 @@ TEMPLATE = subdirs SUBDIRS += \ help \ assistant \ - qhelpgenerator \ - qcollectiongenerator + qhelpgenerator assistant.depends = help qhelpgenerator.depends = help -qcollectiongenerator.depends = help qtNomakeTools( \ assistant \ qhelpgenerator \ - qcollectiongenerator \ ) diff --git a/src/assistant/assistant/doc/snippets/doc_src_assistant-manual.qdoc b/src/assistant/assistant/doc/snippets/doc_src_assistant-manual.qdoc index 6356b208a..feae78784 100644 --- a/src/assistant/assistant/doc/snippets/doc_src_assistant-manual.qdoc +++ b/src/assistant/assistant/doc/snippets/doc_src_assistant-manual.qdoc @@ -154,5 +154,5 @@ assistant -collectionFile mycollection.qhc //! [9] //! [10] -qcollectiongenerator mycollection.qhcp -o mycollection.qhc +qhelpgenerator mycollection.qhcp -o mycollection.qhc //! [10] diff --git a/src/assistant/assistant/doc/src/assistant-manual.qdoc b/src/assistant/assistant/doc/src/assistant-manual.qdoc index cbd6ccde4..9badfc260 100644 --- a/src/assistant/assistant/doc/src/assistant-manual.qdoc +++ b/src/assistant/assistant/doc/src/assistant-manual.qdoc @@ -189,7 +189,7 @@ \section2 Creating a Custom Help Collection File The help collection file (*.qhc) used by \QA is created when running the - \c qcollectiongenerator tool on a help collection project file (*.qhcp). + \c qhelpgenerator tool on a help collection project file (*.qhcp). The project file format is XML and it supports the following tags: \table @@ -279,7 +279,7 @@ \snippet doc_src_assistant-manual.qdoc 1 - To create the binary collection file, run the \c qcollectiongenerator tool: + To create the binary collection file, run the \c qhelpgenerator tool: \snippet doc_src_assistant-manual.qdoc 10 diff --git a/src/assistant/help/Qt5HelpConfigExtras.cmake.in b/src/assistant/help/Qt5HelpConfigExtras.cmake.in index 3b97923a9..b8ce04427 100644 --- a/src/assistant/help/Qt5HelpConfigExtras.cmake.in +++ b/src/assistant/help/Qt5HelpConfigExtras.cmake.in @@ -1,19 +1,4 @@ -if (NOT TARGET Qt5::qcollectiongenerator) - add_executable(Qt5::qcollectiongenerator IMPORTED) - -!!IF isEmpty(CMAKE_BIN_DIR_IS_ABSOLUTE) - set(imported_location \"${_qt5Help_install_prefix}/$${CMAKE_BIN_DIR}qcollectiongenerator$$CMAKE_BIN_SUFFIX\") -!!ELSE - set(imported_location \"$${CMAKE_BIN_DIR}qcollectiongenerator$$CMAKE_BIN_SUFFIX\") -!!ENDIF - _qt5_Help_check_file_exists(${imported_location}) - - set_target_properties(Qt5::qcollectiongenerator PROPERTIES - IMPORTED_LOCATION ${imported_location} - ) -endif() - if (NOT TARGET Qt5::qhelpgenerator) add_executable(Qt5::qhelpgenerator IMPORTED) diff --git a/src/assistant/help/doc/snippets/doc_src_qthelp.qdoc b/src/assistant/help/doc/snippets/doc_src_qthelp.qdoc index 303119f85..648598079 100644 --- a/src/assistant/help/doc/snippets/doc_src_qthelp.qdoc +++ b/src/assistant/help/doc/snippets/doc_src_qthelp.qdoc @@ -71,7 +71,7 @@ qhelpgenerator doc.qhp -o doc.qch //! [4] -qcollectiongenerator mycollection.qhcp -o mycollection.qhc +qhelpgenerator mycollection.qhcp -o mycollection.qhc //! [4] diff --git a/src/assistant/help/doc/src/qthelp.qdoc b/src/assistant/help/doc/src/qthelp.qdoc index 69afe5b2a..7b096882c 100644 --- a/src/assistant/help/doc/src/qthelp.qdoc +++ b/src/assistant/help/doc/src/qthelp.qdoc @@ -103,33 +103,32 @@ \row \li \l {Qt Help Project} \li .qhp - \li The input file for the help generator consisting of the table - of contents, indices, and references to the actual documentation - files (*.html). It also defines a unique namespace for the - documentation. + \li Contains the table of contents, indices, and references to the + actual documentation files (*.html). It also defines a unique + namespace for the documentation. This file is passed to the help + generator for creating a compressed help file. \row \li Qt Compressed Help \li .qch - \li The output file of the help generator. This binary file contains - all the information specified in the help project file along with - all the compressed documentation files. + \li Contains all the information specified in the help project file + along with all the compressed documentation files. \row \li \l {Qt Help Collection Project} \li .qhcp - \li The input file for the help collection generator. It contains - references to the compressed help files that should be included in - the collection; it also may contain other information for - customizing Qt Assistant. + \li An XML file that contains references to the compressed help + files that should be included in the help collection. In + addition, it may contain information for customizing Qt + Assistant. This file can be passed to the help generator for + creating a help collection file. \row \li Qt Help Collection \li .qhc - \li The output of the help collection generator. This is the file - QHelpEngine operates on. It contains references to any number of - compressed help files as well as additional information, such as - custom filters. + \li The help collection file that QHelpEngine operates on. It can + contain references to any number of compressed help files as + well as additional information, such as custom filters. \endtable \section1 Generating Qt Help @@ -165,11 +164,9 @@ \snippet doc_src_qthelp.qdoc 4 - Instead of running two tools, one for generating the compressed - help and another for generating the collection file, it is also - possible to just run the qcollectiongenerator tool with a - slightly modified project file instructing the generator to - create the compressed help first. + To generate both the compressed help and the collection file in one go, + modify the help collection project file so that it instructs the help + generator to create the compressed help first: \snippet doc_src_qthelp.qdoc 5 diff --git a/src/assistant/qcollectiongenerator/main.cpp b/src/assistant/qcollectiongenerator/main.cpp deleted file mode 100644 index 4b2074599..000000000 --- a/src/assistant/qcollectiongenerator/main.cpp +++ /dev/null @@ -1,610 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Assistant of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "../shared/collectionconfiguration.h" -#include "../shared/helpgenerator.h" - -#include <private/qhelpprojectdata_p.h> - -#include <QtCore/QDataStream> -#include <QtCore/QDir> -#include <QtCore/QMap> -#include <QtCore/QFileInfo> -#include <QtCore/QDateTime> -#include <QtCore/QBuffer> -#include <QtCore/QTranslator> -#include <QtCore/QLocale> -#include <QtCore/QLibraryInfo> -#include <QtHelp/QHelpEngineCore> -#include <QtCore/QRegExp> -#include <QtCore/QXmlStreamReader> - -#include <QtGui/QGuiApplication> - -QT_USE_NAMESPACE - -class QCG { - Q_DECLARE_TR_FUNCTIONS(QCollectionGenerator) -}; - -class CollectionConfigReader : public QXmlStreamReader -{ -public: - void readData(const QByteArray &contents); - - QString title() const { return m_title; } - QString homePage() const { return m_homePage; } - QString startPage() const { return m_startPage; } - QString applicationIcon() const { return m_applicationIcon; } - QString currentFilter() const { return m_currentFilter; } - bool enableFilterFunctionality() const - { return m_enableFilterFunctionality; } - bool hideFilterFunctionality() const - { return m_hideFilterFunctionality; } - bool enableAddressBar() const { return m_enableAddressBar; } - bool hideAddressBar() const { return m_hideAddressBar; } - bool enableDocumentationManager() const - { return m_enableDocumentationManager; } - - QMap<QString, QString> aboutMenuTexts() const - { return m_aboutMenuTexts; } - QString aboutIcon() const { return m_aboutIcon; } - QMap<QString, QString> aboutTextFiles() const - { return m_aboutTextFiles; } - - QMap<QString, QString> filesToGenerate() const - { return m_filesToGenerate; } - - QStringList filesToRegister() const { return m_filesToRegister; } - - QString cacheDirectory() const { return m_cacheDirectory; } - bool cacheDirRelativeToCollection() const { return m_cacheDirRelativeToCollection; } - - bool fullTextSearchFallbackEnabled() const { - return m_enableFullTextSearchFallback; - } - -private: - void raiseErrorWithLine(); - void readConfig(); - void readAssistantSettings(); - void readMenuTexts(); - void readAboutDialog(); - void readDocFiles(); - void readGenerate(); - void readFiles(); - void readRegister(); - - QString m_title; - QString m_homePage; - QString m_startPage; - QString m_applicationIcon; - QString m_currentFilter; - bool m_enableFilterFunctionality; - bool m_hideFilterFunctionality; - bool m_enableAddressBar; - bool m_hideAddressBar; - bool m_enableDocumentationManager; - QMap<QString, QString> m_aboutMenuTexts; - QString m_aboutIcon; - QMap<QString, QString> m_aboutTextFiles; - QMap<QString, QString> m_filesToGenerate; - QStringList m_filesToRegister; - QString m_cacheDirectory; - bool m_cacheDirRelativeToCollection; - bool m_enableFullTextSearchFallback; -}; - -void CollectionConfigReader::raiseErrorWithLine() -{ - raiseError(QCG::tr("Unknown token at line %1.").arg(lineNumber())); -} - -void CollectionConfigReader::readData(const QByteArray &contents) -{ - m_enableFilterFunctionality = true; - m_hideFilterFunctionality = true; - m_enableAddressBar = true; - m_hideAddressBar = true; - m_enableDocumentationManager = true; - m_enableFullTextSearchFallback = false; - - addData(contents); - while (!atEnd()) { - readNext(); - if (isStartElement()) { - if (name() == QLatin1String("QHelpCollectionProject") - && attributes().value(QLatin1String("version")) == QLatin1String("1.0")) - readConfig(); - else - raiseError(QCG::tr("Unknown token at line %1. " - "Expected \"QtHelpCollectionProject\".") - .arg(lineNumber())); - } - } -} - -void CollectionConfigReader::readConfig() -{ - bool ok = false; - while (!atEnd()) { - readNext(); - if (isStartElement()) { - if (name() == QLatin1String("assistant")) - readAssistantSettings(); - else if (name() == QLatin1String("docFiles")) - readDocFiles(); - else - raiseErrorWithLine(); - } else if (isEndElement() && name() == QLatin1String("QHelpCollectionProject")) { - ok = true; - } - } - if (!ok && !hasError()) - raiseError(QCG::tr("Missing end tags.")); -} - -void CollectionConfigReader::readAssistantSettings() -{ - while (!atEnd()) { - readNext(); - if (isStartElement()) { - if (name() == QLatin1String("title")) { - m_title = readElementText(); - } else if (name() == QLatin1String("homePage")) { - m_homePage = readElementText(); - } else if (name() == QLatin1String("startPage")) { - m_startPage = readElementText(); - } else if (name() == QLatin1String("currentFilter")) { - m_currentFilter = readElementText(); - } else if (name() == QLatin1String("applicationIcon")) { - m_applicationIcon = readElementText(); - } else if (name() == QLatin1String("enableFilterFunctionality")) { - if (attributes().value(QLatin1String("visible")) == QLatin1String("true")) - m_hideFilterFunctionality = false; - if (readElementText() == QLatin1String("false")) - m_enableFilterFunctionality = false; - } else if (name() == QLatin1String("enableDocumentationManager")) { - if (readElementText() == QLatin1String("false")) - m_enableDocumentationManager = false; - } else if (name() == QLatin1String("enableAddressBar")) { - if (attributes().value(QLatin1String("visible")) == QLatin1String("true")) - m_hideAddressBar = false; - if (readElementText() == QLatin1String("false")) - m_enableAddressBar = false; - } else if (name() == QLatin1String("aboutMenuText")) { - readMenuTexts(); - } else if (name() == QLatin1String("aboutDialog")) { - readAboutDialog(); - } else if (name() == "cacheDirectory") { - m_cacheDirRelativeToCollection = - attributes().value(QLatin1String("base")) - == QLatin1String("collection"); - m_cacheDirectory = readElementText(); - } else if (name() == QLatin1String("enableFullTextSearchFallback")) { - if (readElementText() == QLatin1String("true")) - m_enableFullTextSearchFallback = true; - } else { - raiseErrorWithLine(); - } - } else if (isEndElement() && name() == QLatin1String("assistant")) { - break; - } - } -} - -void CollectionConfigReader::readMenuTexts() -{ - while (!atEnd()) - { - readNext(); - if (isStartElement()) { - if (name() == QLatin1String("text")) { - QString lang = attributes().value(QLatin1String("language")).toString(); - if (lang.isEmpty()) - lang = QLatin1String("default"); - m_aboutMenuTexts.insert(lang, readElementText()); - } else { - raiseErrorWithLine(); - } - } else if (isEndElement() && name() == QLatin1String("aboutMenuText")) { - break; - } - } -} - -void CollectionConfigReader::readAboutDialog() -{ - while (!atEnd()) - { - readNext(); - if (isStartElement()) { - if (name() == QLatin1String("file")) { - QString lang = attributes().value(QLatin1String("language")).toString(); - if (lang.isEmpty()) - lang = QLatin1String("default"); - m_aboutTextFiles.insert(lang, readElementText()); - } else if (name() == QLatin1String("icon")) { - m_aboutIcon = readElementText(); - } else { - raiseErrorWithLine(); - } - } else if (isEndElement() && name() == QLatin1String("aboutDialog")) { - break; - } - } -} - -void CollectionConfigReader::readDocFiles() -{ - while (!atEnd()) { - readNext(); - if (isStartElement()) { - if (name() == QLatin1String("generate")) { - readGenerate(); - } else if (name() == QLatin1String("register")) { - readRegister(); - } else { - raiseErrorWithLine(); - } - } else if (isEndElement() && name() == QLatin1String("docFiles")) { - break; - } - } -} - -void CollectionConfigReader::readGenerate() -{ - while (!atEnd()) { - readNext(); - if (isStartElement()) { - if (name() == QLatin1String("file")) - readFiles(); - else - raiseErrorWithLine(); - } else if (isEndElement() && name() == QLatin1String("generate")) { - break; - } - } -} - -void CollectionConfigReader::readFiles() -{ - QString input; - QString output; - while (!atEnd()) { - readNext(); - if (isStartElement()) { - if (name() == QLatin1String("input")) - input = readElementText(); - else if (name() == QLatin1String("output")) - output = readElementText(); - else - raiseErrorWithLine(); - } else if (isEndElement() && name() == QLatin1String("file")) { - break; - } - } - if (input.isEmpty() || output.isEmpty()) { - raiseError(QCG::tr("Missing input or output file for help file generation.")); - return; - } - m_filesToGenerate.insert(input, output); -} - -void CollectionConfigReader::readRegister() -{ - while (!atEnd()) { - readNext(); - if (isStartElement()) { - if (name() == QLatin1String("file")) - m_filesToRegister.append(readElementText()); - else - raiseErrorWithLine(); - } else if (isEndElement() && name() == QLatin1String("register")) { - break; - } - } -} - -namespace { - QString absoluteFileName(const QString &basePath, const QString &fileName) - { - return QFileInfo(fileName).isAbsolute() ? - fileName : basePath + QDir::separator() + fileName; - } -} - -int main(int argc, char *argv[]) -{ - QString error; - QString arg; - QString collectionFile; - QString configFile; - QString basePath; - bool showHelp = false; - bool showVersion = false; - - // don't require a window manager even though we're a QGuiApplication - qputenv("QT_QPA_PLATFORM", QByteArrayLiteral("minimal")); - QGuiApplication app(argc, argv); - -#ifndef Q_OS_WIN32 - QTranslator translator; - QTranslator qtTranslator; - QTranslator qt_helpTranslator; - QString sysLocale = QLocale::system().name(); - QString resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath); - if (translator.load(QLatin1String("assistant_") + sysLocale, resourceDir) - && qtTranslator.load(QLatin1String("qt_") + sysLocale, resourceDir) - && qt_helpTranslator.load(QLatin1String("qt_help_") + sysLocale, resourceDir)) { - app.installTranslator(&translator); - app.installTranslator(&qtTranslator); - app.installTranslator(&qt_helpTranslator); - } -#endif // Q_OS_WIN32 - - for (int i=1; i<argc; ++i) { - arg = QString::fromLocal8Bit(argv[i]); - if (arg == QLatin1String("-o")) { - if (++i < argc) { - QFileInfo fi(QString::fromLocal8Bit(argv[i])); - collectionFile = fi.absoluteFilePath(); - } else { - error = QCG::tr("Missing output file name."); - } - } else if (arg == QLatin1String("-h")) { - showHelp = true; - } else if (arg == QLatin1String("-v")) { - showVersion = true; - } else { - QFileInfo fi(arg); - configFile = fi.absoluteFilePath(); - basePath = fi.absolutePath(); - } - } - - if (showVersion) { - fputs(qPrintable(QCG::tr("Qt Collection Generator version 1.0 (Qt %1)\n") - .arg(QT_VERSION_STR)), stdout); - return 0; - } - - if (configFile.isEmpty() && !showHelp) - error = QCG::tr("Missing collection config file."); - - QString help = QCG::tr("\nUsage:\n\n" - "qcollectiongenerator <collection-config-file> [options]\n\n" - " -o <collection-file> Generates a collection file\n" - " called <collection-file>. If\n" - " this option is not specified\n" - " a default name will be used.\n" - " -v Displays the version of\n" - " qcollectiongenerator.\n\n"); - - if (showHelp) { - fputs(qPrintable(help), stdout); - return 0; - }else if (!error.isEmpty()) { - fprintf(stderr, "%s\n\n%s", qPrintable(error), qPrintable(help)); - return -1; - } - - QFile file(configFile); - if (!file.open(QIODevice::ReadOnly)) { - fputs(qPrintable(QCG::tr("Could not open %1.\n").arg(configFile)), stderr); - return -1; - } - - if (collectionFile.isEmpty()) { - QFileInfo fi(configFile); - collectionFile = basePath + QDir::separator() - + fi.baseName() + QLatin1String(".qhc"); - } - - fputs(qPrintable(QCG::tr("Reading collection config file...\n")), stdout); - CollectionConfigReader config; - config.readData(file.readAll()); - if (config.hasError()) { - fputs(qPrintable(QCG::tr("Collection config file error: %1\n") - .arg(config.errorString())), stderr); - return -1; - } - - const QMap<QString, QString> &filesToGenerate = config.filesToGenerate(); - for (auto it = filesToGenerate.cbegin(), end = filesToGenerate.cend(); it != end; ++it) { - fputs(qPrintable(QCG::tr("Generating help for %1...\n").arg(it.key())), stdout); - QHelpProjectData helpData; - if (!helpData.readData(absoluteFileName(basePath, it.key()))) { - fprintf(stderr, "%s\n", qPrintable(helpData.errorMessage())); - return -1; - } - - HelpGenerator helpGenerator; - if (!helpGenerator.generate(&helpData, absoluteFileName(basePath, it.value()))) { - fprintf(stderr, "%s\n", qPrintable(helpGenerator.error())); - return -1; - } - } - - fputs(qPrintable(QCG::tr("Creating collection file...\n")), stdout); - - QFileInfo colFi(collectionFile); - if (colFi.exists()) { - if (!colFi.dir().remove(colFi.fileName())) { - fputs(qPrintable(QCG::tr("The file %1 cannot be overwritten.\n") - .arg(collectionFile)), stderr); - return -1; - } - } - - QHelpEngineCore helpEngine(collectionFile); - if (!helpEngine.setupData()) { - fprintf(stderr, "%s\n", qPrintable(helpEngine.error())); - return -1; - } - - for (const QString &file : config.filesToRegister()) { - if (!helpEngine.registerDocumentation(absoluteFileName(basePath, file))) { - fprintf(stderr, "%s\n", qPrintable(helpEngine.error())); - return -1; - } - } - if (!config.filesToRegister().isEmpty()) { - if (Q_UNLIKELY(qEnvironmentVariableIsSet("SOURCE_DATE_EPOCH"))) { - QDateTime dt; - dt.setSecsSinceEpoch(qEnvironmentVariableIntValue("SOURCE_DATE_EPOCH")); - CollectionConfiguration::updateLastRegisterTime(helpEngine, dt); - } else { - CollectionConfiguration::updateLastRegisterTime(helpEngine); - } - } - - if (!config.title().isEmpty()) - CollectionConfiguration::setWindowTitle(helpEngine, config.title()); - - if (!config.homePage().isEmpty()) { - CollectionConfiguration::setDefaultHomePage(helpEngine, - config.homePage()); - } - - if (!config.startPage().isEmpty()) { - CollectionConfiguration::setLastShownPages(helpEngine, - QStringList(config.startPage())); - } - - if (!config.currentFilter().isEmpty()) { - helpEngine.setCurrentFilter(config.currentFilter()); - } - - if (!config.cacheDirectory().isEmpty()) { - CollectionConfiguration::setCacheDir(helpEngine, config.cacheDirectory(), - config.cacheDirRelativeToCollection()); - } - - CollectionConfiguration::setFilterFunctionalityEnabled(helpEngine, - config.enableFilterFunctionality()); - CollectionConfiguration::setFilterToolbarVisible(helpEngine, - !config.hideFilterFunctionality()); - CollectionConfiguration::setDocumentationManagerEnabled(helpEngine, - config.enableDocumentationManager()); - CollectionConfiguration::setAddressBarEnabled(helpEngine, - config.enableAddressBar()); - CollectionConfiguration::setAddressBarVisible(helpEngine, - !config.hideAddressBar()); - uint time = QDateTime::currentMSecsSinceEpoch() / 1000; - if (Q_UNLIKELY(qEnvironmentVariableIsSet("SOURCE_DATE_EPOCH"))) - time = qEnvironmentVariableIntValue("SOURCE_DATE_EPOCH"); - CollectionConfiguration::setCreationTime(helpEngine, time); - CollectionConfiguration::setFullTextSearchFallbackEnabled(helpEngine, - config.fullTextSearchFallbackEnabled()); - - if (!config.applicationIcon().isEmpty()) { - QFile icon(absoluteFileName(basePath, config.applicationIcon())); - if (!icon.open(QIODevice::ReadOnly)) { - fputs(qPrintable(QCG::tr("Cannot open %1.\n").arg(icon.fileName())), stderr); - return -1; - } - CollectionConfiguration::setApplicationIcon(helpEngine, icon.readAll()); - } - - if (config.aboutMenuTexts().count()) { - QByteArray ba; - QDataStream s(&ba, QIODevice::WriteOnly); - const QMap<QString, QString> &aboutMenuTexts = config.aboutMenuTexts(); - for (auto it = aboutMenuTexts.cbegin(), end = aboutMenuTexts.cend(); it != end; ++it) - s << it.key() << it.value(); - CollectionConfiguration::setAboutMenuTexts(helpEngine, ba); - } - - if (!config.aboutIcon().isEmpty()) { - QFile icon(absoluteFileName(basePath, config.aboutIcon())); - if (!icon.open(QIODevice::ReadOnly)) { - fputs(qPrintable(QCG::tr("Cannot open %1.\n").arg(icon.fileName())), stderr); - return -1; - } - CollectionConfiguration::setAboutIcon(helpEngine, icon.readAll()); - } - - if (config.aboutTextFiles().count()) { - QByteArray ba; - QDataStream s(&ba, QIODevice::WriteOnly); - QMap<QString, QByteArray> imgData; - - QRegExp srcRegExp(QLatin1String("src=(\"(.+)\"|([^\"\\s]+)).*>")); - srcRegExp.setMinimal(true); - QRegExp imgRegExp(QLatin1String("(<img[^>]+>)")); - imgRegExp.setMinimal(true); - - const QMap<QString, QString> &aboutMenuTexts = config.aboutTextFiles(); - for (auto it = aboutMenuTexts.cbegin(), end = aboutMenuTexts.cend(); it != end; ++it) { - s << it.key(); - QFileInfo fi(absoluteFileName(basePath, it.value())); - QFile f(fi.absoluteFilePath()); - if (!f.open(QIODevice::ReadOnly)) { - fputs(qPrintable(QCG::tr("Cannot open %1.\n").arg(f.fileName())), stderr); - return -1; - } - QByteArray data = f.readAll(); - s << data; - - QString contents = QString::fromUtf8(data); - int pos = 0; - while ((pos = imgRegExp.indexIn(contents, pos)) != -1) { - QString imgTag = imgRegExp.cap(1); - pos += imgRegExp.matchedLength(); - - if (srcRegExp.indexIn(imgTag, 0) != -1) { - QString src = srcRegExp.cap(2); - if (src.isEmpty()) - src = srcRegExp.cap(3); - - QFile img(fi.absolutePath() + QDir::separator() + src); - if (img.open(QIODevice::ReadOnly)) { - if (!imgData.contains(src)) - imgData.insert(src, img.readAll()); - } else { - fputs(qPrintable(QCG::tr("Cannot open referenced image file %1.\n") - .arg(img.fileName())), stderr); - } - } - } - } - CollectionConfiguration::setAboutTexts(helpEngine, ba); - if (imgData.count()) { - QByteArray imageData; - QBuffer buffer(&imageData); - buffer.open(QIODevice::WriteOnly); - QDataStream out(&buffer); - out << imgData; - CollectionConfiguration::setAboutImages(helpEngine, imageData); - } - } - - return 0; -} diff --git a/src/assistant/qcollectiongenerator/qcollectiongenerator.pro b/src/assistant/qcollectiongenerator/qcollectiongenerator.pro deleted file mode 100644 index cf9b9a257..000000000 --- a/src/assistant/qcollectiongenerator/qcollectiongenerator.pro +++ /dev/null @@ -1,11 +0,0 @@ -QT += network help-private -TARGET = qcollectiongenerator -SOURCES += ../shared/helpgenerator.cpp \ - main.cpp \ - ../shared/collectionconfiguration.cpp -HEADERS += ../shared/helpgenerator.h \ - ../shared/collectionconfiguration.h -QTPLUGIN.platforms = qminimal - -QMAKE_TARGET_DESCRIPTION = "Qt Help Collection File Generator" -load(qt_tool) diff --git a/src/assistant/qhelpgenerator/collectionconfigreader.cpp b/src/assistant/qhelpgenerator/collectionconfigreader.cpp new file mode 100644 index 000000000..155430c9c --- /dev/null +++ b/src/assistant/qhelpgenerator/collectionconfigreader.cpp @@ -0,0 +1,258 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "collectionconfigreader.h" + +#include <QtGui/QGuiApplication> + +class QCG { + Q_DECLARE_TR_FUNCTIONS(QCollectionGenerator) +}; + +void CollectionConfigReader::raiseErrorWithLine() +{ + raiseError(QCG::tr("Unknown token at line %1.").arg(lineNumber())); +} + +void CollectionConfigReader::readData(const QByteArray &contents) +{ + m_enableFilterFunctionality = true; + m_hideFilterFunctionality = true; + m_enableAddressBar = true; + m_hideAddressBar = true; + m_enableDocumentationManager = true; + m_enableFullTextSearchFallback = false; + + addData(contents); + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("QHelpCollectionProject") + && attributes().value(QLatin1String("version")) == QLatin1String("1.0")) + readConfig(); + else + raiseError(QCG::tr("Unknown token at line %1. " + "Expected \"QtHelpCollectionProject\".") + .arg(lineNumber())); + } + } +} + +void CollectionConfigReader::readConfig() +{ + bool ok = false; + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("assistant")) + readAssistantSettings(); + else if (name() == QLatin1String("docFiles")) + readDocFiles(); + else + raiseErrorWithLine(); + } else if (isEndElement() && name() == QLatin1String("QHelpCollectionProject")) { + ok = true; + } + } + if (!ok && !hasError()) + raiseError(QCG::tr("Missing end tags.")); +} + +void CollectionConfigReader::readAssistantSettings() +{ + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("title")) { + m_title = readElementText(); + } else if (name() == QLatin1String("homePage")) { + m_homePage = readElementText(); + } else if (name() == QLatin1String("startPage")) { + m_startPage = readElementText(); + } else if (name() == QLatin1String("currentFilter")) { + m_currentFilter = readElementText(); + } else if (name() == QLatin1String("applicationIcon")) { + m_applicationIcon = readElementText(); + } else if (name() == QLatin1String("enableFilterFunctionality")) { + if (attributes().value(QLatin1String("visible")) == QLatin1String("true")) + m_hideFilterFunctionality = false; + if (readElementText() == QLatin1String("false")) + m_enableFilterFunctionality = false; + } else if (name() == QLatin1String("enableDocumentationManager")) { + if (readElementText() == QLatin1String("false")) + m_enableDocumentationManager = false; + } else if (name() == QLatin1String("enableAddressBar")) { + if (attributes().value(QLatin1String("visible")) == QLatin1String("true")) + m_hideAddressBar = false; + if (readElementText() == QLatin1String("false")) + m_enableAddressBar = false; + } else if (name() == QLatin1String("aboutMenuText")) { + readMenuTexts(); + } else if (name() == QLatin1String("aboutDialog")) { + readAboutDialog(); + } else if (name() == "cacheDirectory") { + m_cacheDirRelativeToCollection = + attributes().value(QLatin1String("base")) + == QLatin1String("collection"); + m_cacheDirectory = readElementText(); + } else if (name() == QLatin1String("enableFullTextSearchFallback")) { + if (readElementText() == QLatin1String("true")) + m_enableFullTextSearchFallback = true; + } else { + raiseErrorWithLine(); + } + } else if (isEndElement() && name() == QLatin1String("assistant")) { + break; + } + } +} + +void CollectionConfigReader::readMenuTexts() +{ + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("text")) { + QString lang = attributes().value(QLatin1String("language")).toString(); + if (lang.isEmpty()) + lang = QLatin1String("default"); + m_aboutMenuTexts.insert(lang, readElementText()); + } else { + raiseErrorWithLine(); + } + } else if (isEndElement() && name() == QLatin1String("aboutMenuText")) { + break; + } + } +} + +void CollectionConfigReader::readAboutDialog() +{ + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("file")) { + QString lang = attributes().value(QLatin1String("language")).toString(); + if (lang.isEmpty()) + lang = QLatin1String("default"); + m_aboutTextFiles.insert(lang, readElementText()); + } else if (name() == QLatin1String("icon")) { + m_aboutIcon = readElementText(); + } else { + raiseErrorWithLine(); + } + } else if (isEndElement() && name() == QLatin1String("aboutDialog")) { + break; + } + } +} + +void CollectionConfigReader::readDocFiles() +{ + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("generate")) { + readGenerate(); + } else if (name() == QLatin1String("register")) { + readRegister(); + } else { + raiseErrorWithLine(); + } + } else if (isEndElement() && name() == QLatin1String("docFiles")) { + break; + } + } +} + +void CollectionConfigReader::readGenerate() +{ + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("file")) + readFiles(); + else + raiseErrorWithLine(); + } else if (isEndElement() && name() == QLatin1String("generate")) { + break; + } + } +} + +void CollectionConfigReader::readFiles() +{ + QString input; + QString output; + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("input")) + input = readElementText(); + else if (name() == QLatin1String("output")) + output = readElementText(); + else + raiseErrorWithLine(); + } else if (isEndElement() && name() == QLatin1String("file")) { + break; + } + } + if (input.isEmpty() || output.isEmpty()) { + raiseError(QCG::tr("Missing input or output file for help file generation.")); + return; + } + m_filesToGenerate.insert(input, output); +} + +void CollectionConfigReader::readRegister() +{ + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("file")) + m_filesToRegister.append(readElementText()); + else + raiseErrorWithLine(); + } else if (isEndElement() && name() == QLatin1String("register")) { + break; + } + } +} + + diff --git a/src/assistant/qhelpgenerator/collectionconfigreader.h b/src/assistant/qhelpgenerator/collectionconfigreader.h new file mode 100644 index 000000000..eaf332b6b --- /dev/null +++ b/src/assistant/qhelpgenerator/collectionconfigreader.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef COLLECTIONCONFIGREADER_H +#define COLLECTIONCONFIGREADER_H + +#include <QtCore/QMap> +#include <QtCore/QObject> +#include <QtCore/QXmlStreamReader> + +QT_USE_NAMESPACE + +class CollectionConfigReader : public QXmlStreamReader +{ +public: + void readData(const QByteArray &contents); + + QString title() const { return m_title; } + QString homePage() const { return m_homePage; } + QString startPage() const { return m_startPage; } + QString applicationIcon() const { return m_applicationIcon; } + QString currentFilter() const { return m_currentFilter; } + bool enableFilterFunctionality() const + { return m_enableFilterFunctionality; } + bool hideFilterFunctionality() const + { return m_hideFilterFunctionality; } + bool enableAddressBar() const { return m_enableAddressBar; } + bool hideAddressBar() const { return m_hideAddressBar; } + bool enableDocumentationManager() const + { return m_enableDocumentationManager; } + + QMap<QString, QString> aboutMenuTexts() const + { return m_aboutMenuTexts; } + QString aboutIcon() const { return m_aboutIcon; } + QMap<QString, QString> aboutTextFiles() const + { return m_aboutTextFiles; } + + QMap<QString, QString> filesToGenerate() const + { return m_filesToGenerate; } + + QStringList filesToRegister() const { return m_filesToRegister; } + + QString cacheDirectory() const { return m_cacheDirectory; } + bool cacheDirRelativeToCollection() const { return m_cacheDirRelativeToCollection; } + + bool fullTextSearchFallbackEnabled() const { + return m_enableFullTextSearchFallback; + } + +private: + void raiseErrorWithLine(); + void readConfig(); + void readAssistantSettings(); + void readMenuTexts(); + void readAboutDialog(); + void readDocFiles(); + void readGenerate(); + void readFiles(); + void readRegister(); + + QMap<QString, QString> m_aboutMenuTexts; + QMap<QString, QString> m_aboutTextFiles; + QMap<QString, QString> m_filesToGenerate; + QStringList m_filesToRegister; + QString m_title; + QString m_homePage; + QString m_startPage; + QString m_applicationIcon; + QString m_currentFilter; + QString m_aboutIcon; + QString m_cacheDirectory; + bool m_enableFilterFunctionality; + bool m_hideFilterFunctionality; + bool m_enableAddressBar; + bool m_hideAddressBar; + bool m_enableDocumentationManager; + bool m_cacheDirRelativeToCollection; + bool m_enableFullTextSearchFallback; +}; + +#endif diff --git a/src/assistant/qhelpgenerator/main.cpp b/src/assistant/qhelpgenerator/main.cpp index a93f4a258..bca4ec248 100644 --- a/src/assistant/qhelpgenerator/main.cpp +++ b/src/assistant/qhelpgenerator/main.cpp @@ -26,14 +26,20 @@ ** ****************************************************************************/ +#include "../shared/collectionconfiguration.h" #include "../shared/helpgenerator.h" +#include "collectionconfigreader.h" +#include <QtCore/QBuffer> +#include <QtCore/QDataStream> #include <QtCore/QDir> #include <QtCore/QFileInfo> -#include <QtGui/QGuiApplication> -#include <QtCore/QTranslator> -#include <QtCore/QLocale> #include <QtCore/QLibraryInfo> +#include <QtCore/QTranslator> + +#include <QtGui/QGuiApplication> + +#include <QtHelp/QHelpEngineCore> #include <private/qhelpprojectdata_p.h> @@ -43,12 +49,207 @@ class QHG { Q_DECLARE_TR_FUNCTIONS(QHelpGenerator) }; +static const char QHP[] = "qhp"; +static const char QCH[] = "qch"; + +static const char QHCP[] = "qhcp"; +static const char QHC[] = "qhc"; + +namespace { + QString absoluteFilePath(const QString &basePath, const QString &fileName) + { + return QDir(basePath).absoluteFilePath(fileName); + } +} + +int generateCollectionFile(const QByteArray &data, const QString &basePath, const QString outputFile) +{ + fputs(qPrintable(QHG::tr("Reading collection config file...\n")), stdout); + CollectionConfigReader config; + config.readData(data); + if (config.hasError()) { + fputs(qPrintable(QHG::tr("Collection config file error: %1\n") + .arg(config.errorString())), stderr); + return -1; + } + + const QMap<QString, QString> &filesToGenerate = config.filesToGenerate(); + for (auto it = filesToGenerate.cbegin(), end = filesToGenerate.cend(); it != end; ++it) { + fputs(qPrintable(QHG::tr("Generating help for %1...\n").arg(it.key())), stdout); + QHelpProjectData helpData; + if (!helpData.readData(absoluteFilePath(basePath, it.key()))) { + fprintf(stderr, "%s\n", qPrintable(helpData.errorMessage())); + return -1; + } + + HelpGenerator helpGenerator; + if (!helpGenerator.generate(&helpData, absoluteFilePath(basePath, it.value()))) { + fprintf(stderr, "%s\n", qPrintable(helpGenerator.error())); + return -1; + } + } + + fputs(qPrintable(QHG::tr("Creating collection file...\n")), stdout); + + QFileInfo colFi(outputFile); + if (colFi.exists()) { + if (!colFi.dir().remove(colFi.fileName())) { + fputs(qPrintable(QHG::tr("The file %1 cannot be overwritten.\n") + .arg(outputFile)), stderr); + return -1; + } + } + + QHelpEngineCore helpEngine(outputFile); + if (!helpEngine.setupData()) { + fprintf(stderr, "%s\n", qPrintable(helpEngine.error())); + return -1; + } + + for (const QString &file : config.filesToRegister()) { + if (!helpEngine.registerDocumentation(absoluteFilePath(basePath, file))) { + fprintf(stderr, "%s\n", qPrintable(helpEngine.error())); + return -1; + } + } + if (!config.filesToRegister().isEmpty()) { + if (Q_UNLIKELY(qEnvironmentVariableIsSet("SOURCE_DATE_EPOCH"))) { + QDateTime dt; + dt.setSecsSinceEpoch(qEnvironmentVariableIntValue("SOURCE_DATE_EPOCH")); + CollectionConfiguration::updateLastRegisterTime(helpEngine, dt); + } else { + CollectionConfiguration::updateLastRegisterTime(helpEngine); + } + } + + if (!config.title().isEmpty()) + CollectionConfiguration::setWindowTitle(helpEngine, config.title()); + + if (!config.homePage().isEmpty()) { + CollectionConfiguration::setDefaultHomePage(helpEngine, + config.homePage()); + } + + if (!config.startPage().isEmpty()) { + CollectionConfiguration::setLastShownPages(helpEngine, + QStringList(config.startPage())); + } + + if (!config.currentFilter().isEmpty()) { + helpEngine.setCurrentFilter(config.currentFilter()); + } + + if (!config.cacheDirectory().isEmpty()) { + CollectionConfiguration::setCacheDir(helpEngine, config.cacheDirectory(), + config.cacheDirRelativeToCollection()); + } + + CollectionConfiguration::setFilterFunctionalityEnabled(helpEngine, + config.enableFilterFunctionality()); + CollectionConfiguration::setFilterToolbarVisible(helpEngine, + !config.hideFilterFunctionality()); + CollectionConfiguration::setDocumentationManagerEnabled(helpEngine, + config.enableDocumentationManager()); + CollectionConfiguration::setAddressBarEnabled(helpEngine, + config.enableAddressBar()); + CollectionConfiguration::setAddressBarVisible(helpEngine, + !config.hideAddressBar()); + uint time = QDateTime::currentMSecsSinceEpoch() / 1000; + if (Q_UNLIKELY(qEnvironmentVariableIsSet("SOURCE_DATE_EPOCH"))) + time = qEnvironmentVariableIntValue("SOURCE_DATE_EPOCH"); + CollectionConfiguration::setCreationTime(helpEngine, time); + CollectionConfiguration::setFullTextSearchFallbackEnabled(helpEngine, + config.fullTextSearchFallbackEnabled()); + + if (!config.applicationIcon().isEmpty()) { + QFile icon(absoluteFilePath(basePath, config.applicationIcon())); + if (!icon.open(QIODevice::ReadOnly)) { + fputs(qPrintable(QHG::tr("Cannot open %1.\n").arg(icon.fileName())), stderr); + return -1; + } + CollectionConfiguration::setApplicationIcon(helpEngine, icon.readAll()); + } + + if (config.aboutMenuTexts().count()) { + QByteArray ba; + QDataStream s(&ba, QIODevice::WriteOnly); + const QMap<QString, QString> &aboutMenuTexts = config.aboutMenuTexts(); + for (auto it = aboutMenuTexts.cbegin(), end = aboutMenuTexts.cend(); it != end; ++it) + s << it.key() << it.value(); + CollectionConfiguration::setAboutMenuTexts(helpEngine, ba); + } + + if (!config.aboutIcon().isEmpty()) { + QFile icon(absoluteFilePath(basePath, config.aboutIcon())); + if (!icon.open(QIODevice::ReadOnly)) { + fputs(qPrintable(QHG::tr("Cannot open %1.\n").arg(icon.fileName())), stderr); + return -1; + } + CollectionConfiguration::setAboutIcon(helpEngine, icon.readAll()); + } + + if (config.aboutTextFiles().count()) { + QByteArray ba; + QDataStream s(&ba, QIODevice::WriteOnly); + QMap<QString, QByteArray> imgData; + + QRegExp srcRegExp(QLatin1String("src=(\"(.+)\"|([^\"\\s]+)).*>")); + srcRegExp.setMinimal(true); + QRegExp imgRegExp(QLatin1String("(<img[^>]+>)")); + imgRegExp.setMinimal(true); + + const QMap<QString, QString> &aboutMenuTexts = config.aboutTextFiles(); + for (auto it = aboutMenuTexts.cbegin(), end = aboutMenuTexts.cend(); it != end; ++it) { + s << it.key(); + QFileInfo fi(absoluteFilePath(basePath, it.value())); + QFile f(fi.absoluteFilePath()); + if (!f.open(QIODevice::ReadOnly)) { + fputs(qPrintable(QHG::tr("Cannot open %1.\n").arg(f.fileName())), stderr); + return -1; + } + QByteArray data = f.readAll(); + s << data; + + QString contents = QString::fromUtf8(data); + int pos = 0; + while ((pos = imgRegExp.indexIn(contents, pos)) != -1) { + QString imgTag = imgRegExp.cap(1); + pos += imgRegExp.matchedLength(); + + if (srcRegExp.indexIn(imgTag, 0) != -1) { + QString src = srcRegExp.cap(2); + if (src.isEmpty()) + src = srcRegExp.cap(3); + + QFile img(fi.absolutePath() + QDir::separator() + src); + if (img.open(QIODevice::ReadOnly)) { + if (!imgData.contains(src)) + imgData.insert(src, img.readAll()); + } else { + fputs(qPrintable(QHG::tr("Cannot open referenced image file %1.\n") + .arg(img.fileName())), stderr); + } + } + } + } + CollectionConfiguration::setAboutTexts(helpEngine, ba); + if (imgData.count()) { + QByteArray imageData; + QBuffer buffer(&imageData); + buffer.open(QIODevice::WriteOnly); + QDataStream out(&buffer); + out << imgData; + CollectionConfiguration::setAboutImages(helpEngine, imageData); + } + } + return 0; +} + int main(int argc, char *argv[]) { QString error; - QString arg; - QString compressedFile; - QString projectFile; + QString outputFile; + QString inputFile; QString basePath; bool showHelp = false; bool showVersion = false; @@ -75,11 +276,11 @@ int main(int argc, char *argv[]) #endif // Q_OS_WIN32 for (int i = 1; i < argc; ++i) { - arg = QString::fromLocal8Bit(argv[i]); + const QString arg = QString::fromLocal8Bit(argv[i]); if (arg == QLatin1String("-o")) { if (++i < argc) { QFileInfo fi(QString::fromLocal8Bit(argv[i])); - compressedFile = fi.absoluteFilePath(); + outputFile = fi.absoluteFilePath(); } else { error = QHG::tr("Missing output file name."); } @@ -92,8 +293,8 @@ int main(int argc, char *argv[]) } else if (arg == QLatin1String("-s")) { silent = true; } else { - QFileInfo fi(arg); - projectFile = fi.absoluteFilePath(); + const QFileInfo fi(arg); + inputFile = fi.absoluteFilePath(); basePath = fi.absolutePath(); } } @@ -104,15 +305,40 @@ int main(int argc, char *argv[]) return 0; } - if (projectFile.isEmpty() && !showHelp) - error = QHG::tr("Missing Qt help project file."); + enum InputType { + InputQhp, + InputQhcp, + InputUnknown + }; + + InputType inputType = InputUnknown; + + if (!showHelp) { + if (inputFile.isEmpty()) { + error = QHG::tr("Missing input file name."); + } else { + const QFileInfo fi(inputFile); + if (fi.suffix() == QHP) + inputType = InputQhp; + else if (fi.suffix() == QHCP) + inputType = InputQhcp; + + if (inputType == InputUnknown) + error = QHG::tr("Unknown input file type."); + } + } - QString help = QHG::tr("\nUsage:\n\n" - "qhelpgenerator <help-project-file> [options]\n\n" - " -o <compressed-file> Generates a Qt compressed help\n" - " file called <compressed-file>.\n" + const QString help = QHG::tr("\nUsage:\n\n" + "qhelpgenerator <file> [options]\n\n" + " -o <output-file> Generates a Qt compressed help\n" + " called <output-file> (*.qch) for the\n" + " Qt help project <file> (*.qhp).\n" + " Generates a Qt help collection\n" + " called <output-file> (*.qhc) for the\n" + " Qt help collection project <file> (*.qhcp).\n" " If this option is not specified\n" - " a default name will be used.\n" + " a default name will be used\n" + " (*.qch for *.qhp and *.qhc for *.qhcp).\n" " -c Checks whether all links in HTML files\n" " point to files in this help project.\n" " -s Suppresses status messages.\n" @@ -122,26 +348,30 @@ int main(int argc, char *argv[]) if (showHelp) { fputs(qPrintable(help), stdout); return 0; - }else if (!error.isEmpty()) { + } else if (!error.isEmpty()) { fprintf(stderr, "%s\n\n%s", qPrintable(error), qPrintable(help)); return -1; } - QFile file(projectFile); + // detect input file type (qhp or qhcp) + + QFile file(inputFile); if (!file.open(QIODevice::ReadOnly)) { - fputs(qPrintable(QHG::tr("Could not open %1.\n").arg(projectFile)), stderr); + fputs(qPrintable(QHG::tr("Could not open %1.\n").arg(inputFile)), stderr); return -1; } - if (compressedFile.isEmpty()) { - if (!checkLinks) { - QFileInfo fi(projectFile); - compressedFile = basePath + QDir::separator() - + fi.baseName() + QLatin1String(".qch"); + const QString outputExtension = inputType == InputQhp ? QCH : QHC; + + if (outputFile.isEmpty()) { + if (inputType == InputQhcp || !checkLinks) { + QFileInfo fi(inputFile); + outputFile = basePath + QDir::separator() + + fi.baseName() + QLatin1Char('.') + outputExtension; } } else { // check if the output dir exists -- create if it doesn't - QFileInfo fi(compressedFile); + QFileInfo fi(outputFile); QDir parentDir = fi.dir(); if (!parentDir.exists()) { if (!parentDir.mkpath(QLatin1String("."))) { @@ -151,22 +381,29 @@ int main(int argc, char *argv[]) } } - QHelpProjectData *helpData = new QHelpProjectData(); - if (!helpData->readData(projectFile)) { - fprintf(stderr, "%s\n", qPrintable(helpData->errorMessage())); - return -1; - } + if (inputType == InputQhp) { + QHelpProjectData *helpData = new QHelpProjectData(); + if (!helpData->readData(inputFile)) { + fprintf(stderr, "%s\n", qPrintable(helpData->errorMessage())); + return -1; + } + + HelpGenerator generator(silent); + bool success = true; + if (checkLinks) + success = generator.checkLinks(*helpData); + if (success && !outputFile.isEmpty()) + success = generator.generate(helpData, outputFile); + delete helpData; + if (!success) { + fprintf(stderr, "%s\n", qPrintable(generator.error())); + return -1; + } + } else { + const QByteArray data = file.readAll(); + return generateCollectionFile(data, basePath, outputFile); - HelpGenerator generator(silent); - bool success = true; - if (checkLinks) - success = generator.checkLinks(*helpData); - if (success && !compressedFile.isEmpty()) - success = generator.generate(helpData, compressedFile); - delete helpData; - if (!success) { - fprintf(stderr, "%s\n", qPrintable(generator.error())); - return -1; } + return 0; } diff --git a/src/assistant/qhelpgenerator/qhelpgenerator.pro b/src/assistant/qhelpgenerator/qhelpgenerator.pro index d4e84a74f..0e7b08b48 100644 --- a/src/assistant/qhelpgenerator/qhelpgenerator.pro +++ b/src/assistant/qhelpgenerator/qhelpgenerator.pro @@ -2,10 +2,14 @@ QT += network help-private QTPLUGIN.platforms = qminimal -SOURCES += ../shared/helpgenerator.cpp \ +SOURCES += ../shared/collectionconfiguration.cpp \ + ../shared/helpgenerator.cpp \ + collectionconfigreader.cpp \ main.cpp -HEADERS += ../shared/helpgenerator.h +HEADERS += ../shared/collectionconfiguration.h \ + ../shared/helpgenerator.h \ + collectionconfigreader.h QMAKE_TARGET_DESCRIPTION = "Qt Compressed Help File Generator" load(qt_tool) |