From 415b44ffb6ffcdeb4ad5b7cdd6d9d9e17ab3e47f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 3 May 2010 12:34:27 +0200 Subject: Initial checkin --- doxygen2qthelp.cpp | 407 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 407 insertions(+) create mode 100644 doxygen2qthelp.cpp (limited to 'doxygen2qthelp.cpp') diff --git a/doxygen2qthelp.cpp b/doxygen2qthelp.cpp new file mode 100644 index 0000000..ae5a5be --- /dev/null +++ b/doxygen2qthelp.cpp @@ -0,0 +1,407 @@ +/**************************************************************************** + ** + ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: Nokia Corporation (qt-info@nokia.com) + ** + ** This file is part of the doxygen2qthelp project on Trolltech Labs. + ** + ** This file may be used under the terms of the GNU General Public + ** License version 2.0 or 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of + ** this file. Please review the following information to ensure GNU + ** General Public Licensing requirements will be met: + ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** If you are unsure which license is appropriate for your use, please + ** contact the sales department at qt-sales@nokia.com. + ** + ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + ** + ****************************************************************************/ + +#include "config.h" +#include "htmlhelpdatainterface_p.h" +#include "qhelpgenerator_p.h" +#include "qthelpprojectwriter_p.h" + +#include +#include +#include +#include +#include +#include +#include + +#if (QT_VERSION <= 0x040400) +# error Please compile doxygen2qthelp against a Qt release _after_ 4.4.0, e.g. a recent snapshot +#endif + +QT_BEGIN_NAMESPACE + +const char* const FILE_MISSING_FORMAT = "Error: File '%s' does not exist.\n"; + +enum Action +{ + ACTION_USAGE, + ACTION_RUN, + ACTION_QUIT, + ACTION_VERSION +}; + +QString virtualFolder; +QString nameSpace; +QString outputFileName; +QString inputFileName; +bool verbose = false; +bool forceOverwrite = false; +bool helpProjectMode = false; +bool error = false; + +void printUsage() +{ + printf( + "Usage: doxygen2qthelp OPTIONS []\n" + " doxygen2qthelp --config=\n" + "\n" + "Parameters Description\n" + " Read input from \n" + " (InputFile=)\n" + "\n" + " Write output to \n" + " (OutputFile=)\n" + "\n" + " --config= Read config from \n" + "\n" + " --folder= Set virtual folder [required]\n" + " (VirtualFolder=)\n" + "\n" + " --force Overwrite existing files\n" + " (ForceOverwrite=true)\n" + "\n" + " --help, -h Print help and exit\n" + "\n" + " --namespace= Set namespace to [required]\n" + " (Namespace=)\n" + "\n" + " --qch Output as Qt Compressed Help file (*.qch) [default]\n" + " (QhpMode=false)\n" + "\n" + " --qhp Output as Qt Help Project (*.qhp)\n" + " (QhpMode=true)\n" + "\n" + " --verbose, -v Report in more detail\n" + " (Verbose=true)\n" + "\n" + " --version, -V Print version information and exit\n" + "\n" + ); +} + +void printVersion() +{ + printf( + "doxygen2qthelp " VERSION " of Qt " QT_VERSION_STR " by Trolltech ASA " + "(compiled " __TIME__ ", " __DATE__ ")\n" + ); +} + +void printSettings() +{ + printf( + "Settings\n" + " Input filename ....... %s\n" + " Output filename ...... %s\n" + "\n" + " QtHelpProject mode ... %s\n" + " Force overwrite ...... %s\n" + "\n" + " Namespace ............ %s\n" + " Virtual folder ....... %s\n" + "\n", + qPrintable(inputFileName), + qPrintable(outputFileName), + helpProjectMode ? "yes" : "no", + forceOverwrite ? "yes" : "no", + qPrintable(nameSpace), + qPrintable(virtualFolder) + ); +} + +bool checkNamespace() +{ + const QString uri(QLatin1String("http://") + nameSpace + + QLatin1String("/")); + const QUrl url = QUrl::fromEncoded(uri.toAscii()); + if (!url.isValid()) { + printf("Error: Namespace does not conform to the rules " + "for the host part of a URI.\n"); + return false; + } + return true; +} + +bool checkVirtualFolder() +{ + const char * const VIRTUAL_FOLDER_ERROR = "Error: Virtual folder does not " + "conform to the rules for a path segment of a URI.\n"; + if (virtualFolder.contains('/') || virtualFolder.contains('?') + || virtualFolder.contains('#')) { + printf(VIRTUAL_FOLDER_ERROR); + return false; + } + + const QString uri(QLatin1String("http://example.org/") + virtualFolder + + QLatin1String("/")); + const QUrl url = QUrl::fromEncoded(uri.toAscii()); + if (!url.isValid()) { + printf(VIRTUAL_FOLDER_ERROR); + return false; + } + return true; +} + +bool checkFiles() +{ + if (inputFileName == outputFileName) { + printf("Error: Input and output filename identical\n"); + return false; + } + + if (!QFile(inputFileName).exists()) { + printf(FILE_MISSING_FORMAT, qPrintable(inputFileName)); + return false; + } + + if (!forceOverwrite && QFile(outputFileName).exists()) { + printf("Error: File '%s' exists. Use --force to overwrite.\n", + qPrintable(outputFileName)); + return false; + } + return true; +} + +void guessOutputFilename() +{ + if (!outputFileName.isEmpty()) + return; + + const QString newSuffix(helpProjectMode ? ".qhp" : ".qch"); + if (inputFileName.endsWith(QLatin1String(".hhp"))) { + outputFileName = inputFileName.left(inputFileName.count() - 4); + } else { + outputFileName = inputFileName; + } + outputFileName += newSuffix; +} + +bool run() +{ + guessOutputFilename(); + Q_ASSERT(!inputFileName.isEmpty()); + Q_ASSERT(!outputFileName.isEmpty()); + + if (verbose) + printSettings(); + + if (!checkNamespace() || !checkVirtualFolder() || !checkFiles()) + return false; + + HtmlHelpDataInterface helpData(inputFileName, nameSpace, virtualFolder); + if (helpProjectMode) { + // Create .qhp + QtHelpProjectWriter writer; + if (!writer.writeFile(&helpData, outputFileName)) { + printf("Error: Could not write to file '%s'.\n", + qPrintable(outputFileName)); + return false; + } + } else { + // Create .qch + QHelpGenerator generator; + if (!generator.generate(&helpData, outputFileName)) { + printf("Error: %s\n", qPrintable(generator.error())); + return false; + } + } + + printf("Done.\n"); + return true; +} + +void setIfSpecified(const QSettings &iniReader, const QString &key, + QString &output) +{ + const QString res = iniReader.value(key).toString(); + if (!res.isEmpty()) + output = res; +} + +void setIfSpecified(const QSettings &iniReader, const QString &key, + bool &output) +{ + const QVariant res = iniReader.value(key); + if (!res.toString().isEmpty()) + output = res.toBool(); +} + +bool readConfigFile(const QString &fileName) +{ + if (!QFile(fileName).exists()) { + printf(FILE_MISSING_FORMAT, qPrintable(fileName)); + return false; + } + + QSettings iniReader(fileName, QSettings::IniFormat); + setIfSpecified(iniReader, QLatin1String("ForceOverwrite"), forceOverwrite); + setIfSpecified(iniReader, QLatin1String("InputFile"), inputFileName); + setIfSpecified(iniReader, QLatin1String("Namespace"), nameSpace); + setIfSpecified(iniReader, QLatin1String("OutputFile"), outputFileName); + setIfSpecified(iniReader, QLatin1String("QhpMode"), helpProjectMode); + setIfSpecified(iniReader, QLatin1String("Verbose"), verbose); + setIfSpecified(iniReader, QLatin1String("VirtualFolder"), virtualFolder); + return true; +} + +Action parseArgs() +{ + const char * const ILLEGAL_OPTION_FORMAT = "Error: Illegal option '%s'\n\n"; + const QStringList args = QCoreApplication::arguments(); + + bool fileMode = false; + for (int i = 1; i < args.count(); i++) { + const QString &curArg = args.at(i); + if (fileMode || (curArg[0] != '-')) { + // Filenames only + switch (args.count() - i) { + case 2: // second last + inputFileName = curArg; + break; + + case 1: // last + if (inputFileName.isEmpty()) { + inputFileName = curArg; + } else { + outputFileName = curArg; + } + break; + + default: + if (!fileMode) + printf(ILLEGAL_OPTION_FORMAT, qPrintable(curArg)); + + error = true; + return ACTION_USAGE; + } + } else { + // Options or filenames + QString opt; + if (curArg[1] == '-') { + // Long option + opt = curArg.mid(2); + if (opt.isEmpty()) { + fileMode = true; + } else if (opt.startsWith(QLatin1String("config="))) { + if (!readConfigFile(opt.mid(6 + 1))) { + return ACTION_QUIT; + } + } else if (opt.startsWith("folder=")) { + virtualFolder = opt.mid(6 + 1); + } else if (opt == QLatin1String("force")) { + forceOverwrite = true; + } else if (opt == QLatin1String("help")) { + return ACTION_USAGE; + } else if (opt.startsWith("namespace=")) { + nameSpace = opt.mid(9 + 1); + } else if (opt == QLatin1String("qch")) { + helpProjectMode = false; + } else if (opt == QLatin1String("qhp")) { + helpProjectMode = true; + } else if (opt == QLatin1String("verbose")) { + verbose = true; + } else if (opt == QLatin1String("version")) { + return ACTION_VERSION; + } else { + printf(ILLEGAL_OPTION_FORMAT, qPrintable(curArg)); + error = true; + return ACTION_USAGE; + } + } else { + // Short option + opt = curArg.mid(1); + if (opt.count() != 1) { + printf(ILLEGAL_OPTION_FORMAT, qPrintable(curArg)); + error = true; + return ACTION_USAGE; + } + + switch (opt.at(0).toAscii()) { + case 'h': + return ACTION_USAGE; + + case 'v': + verbose = true; + break; + + case 'V': + return ACTION_VERSION; + + default: + printf(ILLEGAL_OPTION_FORMAT, qPrintable(curArg)); + error = true; + return ACTION_USAGE; + } + } + } + } + + if (inputFileName.isEmpty()) { + printf("Error: No input filename specified\n\n"); + error = true; + return ACTION_USAGE; + } + + if (nameSpace.isEmpty()) { + printf("Error: Namespace must not be empty.\n\n"); + error = true; + return ACTION_USAGE; + } + + if (virtualFolder.isEmpty()) { + printf("Error: Virtual folder must not be empty.\n\n"); + error = true; + return ACTION_USAGE; + } + + return ACTION_RUN; +} + +QT_END_NAMESPACE + +int main(int argc, char ** argv) +{ + QCoreApplication app(argc, argv); + const Action action = parseArgs(); + + switch (action) { + case ACTION_RUN: + error = ! run(); + break; + + case ACTION_VERSION: + printVersion(); + break; + + case ACTION_QUIT: + break; + + case ACTION_USAGE: // fall through + default: + printUsage(); + break; + + } + + return error ? 1 : 0; +} -- cgit v1.2.3