diff options
author | Friedemann Kleint <Friedemann.Kleint@nokia.com> | 2010-09-03 14:27:13 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@nokia.com> | 2010-09-03 14:27:13 +0200 |
commit | 14f009da0509011e15a84cc90a948d82471e11c5 (patch) | |
tree | 38c9869cbbd319818186e094f04b6d1cbb852c40 /src/plugins/projectexplorer | |
parent | 8d169786f4c8ee63b654ac3f931b395b91726731 (diff) | |
download | qt-creator-14f009da0509011e15a84cc90a948d82471e11c5.tar.gz |
Custom wizards: Enhance generator script
following suggestions. Introduce argument syntax in XML allowing for
fine-grained control of handling (omitting empty values, use
temporary files).
Diffstat (limited to 'src/plugins/projectexplorer')
5 files changed, 255 insertions, 97 deletions
diff --git a/src/plugins/projectexplorer/customwizard/customwizard.cpp b/src/plugins/projectexplorer/customwizard/customwizard.cpp index 2a84d2ed57..7ab2a611be 100644 --- a/src/plugins/projectexplorer/customwizard/customwizard.cpp +++ b/src/plugins/projectexplorer/customwizard/customwizard.cpp @@ -225,7 +225,9 @@ bool CustomWizard::writeFiles(const Core::GeneratedFiles &files, QString *errorM } } // Run the custom script to actually generate the files. - if (!Internal::runCustomWizardGeneratorScript(ctx->targetPath, d->m_parameters->filesGeneratorScriptFullPath(), + if (!Internal::runCustomWizardGeneratorScript(ctx->targetPath, + d->m_parameters->filesGeneratorScript, + d->m_parameters->filesGeneratorScriptArguments, ctx->replacements, errorMessage)) return false; // Paranoia: Check on the files generated by the script: @@ -233,7 +235,7 @@ bool CustomWizard::writeFiles(const Core::GeneratedFiles &files, QString *errorM if (generatedFile.attributes() & Core::GeneratedFile::CustomGeneratorAttribute) if (!QFileInfo(generatedFile.path()).isFile()) { *errorMessage = QString::fromLatin1("%1 failed to generate %2"). - arg(d->m_parameters->filesGeneratorScript, generatedFile.path()); + arg(d->m_parameters->filesGeneratorScript.back(), generatedFile.path()); return false; } return true; @@ -253,7 +255,8 @@ Core::GeneratedFiles CustomWizard::generateWizardFiles(QString *errorMessage) co // If generator script is non-empty, do a dry run to get it's files. if (!d->m_parameters->filesGeneratorScript.isEmpty()) { rc += Internal::dryRunCustomWizardGeneratorScript(ctx->targetPath, - d->m_parameters->filesGeneratorScriptFullPath(), + d->m_parameters->filesGeneratorScript, + d->m_parameters->filesGeneratorScriptArguments, ctx->replacements, errorMessage); if (rc.isEmpty()) return rc; diff --git a/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp b/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp index eab3f86165..f3d8fe9591 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp +++ b/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp @@ -29,18 +29,24 @@ #include "customwizardparameters.h" #include "customwizardpreprocessor.h" +#include "customwizardscriptgenerator.h" #include <coreplugin/mimedatabase.h> #include <coreplugin/icore.h> #include <cpptools/cpptoolsconstants.h> +#include <utils/qtcassert.h> + #include <QtCore/QDebug> #include <QtCore/QCoreApplication> #include <QtCore/QLocale> #include <QtCore/QFile> +#include <QtCore/QDir> #include <QtCore/QFileInfo> #include <QtCore/QXmlStreamReader> #include <QtCore/QXmlStreamAttribute> +#include <QtCore/QTemporaryFile> + #include <QtGui/QIcon> enum { debug = 0 }; @@ -64,6 +70,13 @@ static const char comboEntriesElementC[] = "comboentries"; static const char comboEntryElementC[] = "comboentry"; static const char comboEntryTextElementC[] = "comboentrytext"; +static const char generatorScriptElementC[] = "generatorscript"; +static const char generatorScriptBinaryAttributeC[] = "binary"; +static const char generatorScriptArgumentElementC[] = "argument"; +static const char generatorScriptArgumentValueAttributeC[] = "value"; +static const char generatorScriptArgumentOmitEmptyAttributeC[] = "omit-empty"; +static const char generatorScriptArgumentWriteFileAttributeC[] = "write-file"; + static const char fieldDescriptionElementC[] = "fielddescription"; static const char fieldNameAttributeC[] = "name"; static const char fieldMandatoryAttributeC[] = "mandatory"; @@ -87,6 +100,8 @@ enum ParseState { ParseWithinComboEntryText, ParseWithinFiles, ParseWithinFile, + ParseWithinScript, + ParseWithinScriptArguments, ParseError }; @@ -136,6 +151,7 @@ void CustomWizardParameters::clear() files.clear(); fields.clear(); filesGeneratorScript.clear(); + filesGeneratorScriptArguments.clear(); firstPageId = -1; } @@ -276,6 +292,8 @@ static ParseState nextOpeningState(ParseState in, const QStringRef &name) return ParseWithinFields; if (name == QLatin1String(filesElementC)) return ParseWithinFiles; + if (name == QLatin1String(generatorScriptElementC)) + return ParseWithinScript; break; case ParseWithinFields: if (name == QLatin1String(fieldElementC)) @@ -303,10 +321,15 @@ static ParseState nextOpeningState(ParseState in, const QStringRef &name) if (name == QLatin1String(fileElementC)) return ParseWithinFile; break; + case ParseWithinScript: + if (name == QLatin1String(generatorScriptArgumentElementC)) + return ParseWithinScriptArguments; + break; case ParseWithinFieldDescription: // No subelements case ParseWithinComboEntryText: case ParseWithinFile: case ParseError: + case ParseWithinScriptArguments: break; } return ParseError; @@ -358,6 +381,14 @@ static ParseState nextClosingState(ParseState in, const QStringRef &name) if (name == QLatin1String(comboEntryTextElementC)) return ParseWithinComboEntry; break; + case ParseWithinScript: + if (name == QLatin1String(generatorScriptElementC)) + return ParseWithinWizard; + break; + case ParseWithinScriptArguments: + if (name == QLatin1String(generatorScriptArgumentElementC)) + return ParseWithinScript; + break; case ParseError: break; } @@ -427,6 +458,11 @@ static inline QString localeLanguage() return name; } +GeneratorScriptArgument::GeneratorScriptArgument(const QString &v) : + value(v), flags(0) +{ +} + // Main parsing routine CustomWizardParameters::ParseResult CustomWizardParameters::parse(QIODevice &device, @@ -499,7 +535,6 @@ CustomWizardParameters::ParseResult } break; case ParseWithinFiles: - filesGeneratorScript = attributeValue(reader, filesGeneratorScriptAttributeC); break; case ParseWithinFile: { // file attribute CustomWizardFile file; @@ -516,6 +551,26 @@ CustomWizardParameters::ParseResult } } break; + case ParseWithinScript: + filesGeneratorScript = fixGeneratorScript(configFileFullPath, attributeValue(reader, generatorScriptBinaryAttributeC)); + if (filesGeneratorScript.isEmpty()) { + *errorMessage = QString::fromLatin1("No binary specified for generator script."); + return ParseFailed; + } + break; + case ParseWithinScriptArguments: { + GeneratorScriptArgument argument(attributeValue(reader, generatorScriptArgumentValueAttributeC)); + if (argument.value.isEmpty()) { + *errorMessage = QString::fromLatin1("No value specified for generator script argument."); + return ParseFailed; + } + if (booleanAttributeValue(reader, generatorScriptArgumentOmitEmptyAttributeC, false)) + argument.flags |= GeneratorScriptArgument::OmitEmpty; + if (booleanAttributeValue(reader, generatorScriptArgumentWriteFileAttributeC, false)) + argument.flags |= GeneratorScriptArgument::WriteFile; + filesGeneratorScriptArguments.push_back(argument); + } + break; default: break; } @@ -559,23 +614,26 @@ CustomWizardParameters::ParseResult return parse(configFile, configFileFullPath, bp, errorMessage); } -QString CustomWizardParameters::filesGeneratorScriptFullPath() const -{ - if (filesGeneratorScript.isEmpty()) - return QString(); - QString rc = directory; - rc += QLatin1Char('/'); - rc += filesGeneratorScript; - return rc; -} - QString CustomWizardParameters::toString() const { QString rc; QTextStream str(&rc); str << "Directory: " << directory << " Klass: '" << klass << "'\n"; - if (!filesGeneratorScript.isEmpty()) - str << "Script: '" << filesGeneratorScript << "'\n"; + if (!filesGeneratorScriptArguments.isEmpty()) { + str << "Script:"; + foreach(const QString &a, filesGeneratorScript) + str << " '" << a << '\''; + str << "\nArguments: "; + foreach(const GeneratorScriptArgument &a, filesGeneratorScriptArguments) { + str << " '" << a.value << '\''; + if (a.flags & GeneratorScriptArgument::OmitEmpty) + str << " [omit empty]"; + if (a.flags & GeneratorScriptArgument::WriteFile) + str << " [write file]"; + str << ','; + } + str << '\n'; + } foreach(const CustomWizardFile &f, files) { str << " File source: " << f.source << " Target: " << f.target; if (f.openEditor) @@ -603,8 +661,16 @@ QString CustomWizardParameters::toString() const // ------------ CustomWizardContext -void CustomWizardContext::replaceFields(const FieldReplacementMap &fm, QString *s) +static inline QString passThrough(const QString &in) { return in; } + +// Do field replacements applying modifiers and string transformation +// for the value +template <class ValueStringTransformation> +bool replaceFieldHelper(ValueStringTransformation transform, + const CustomWizardContext::FieldReplacementMap &fm, + QString *s) { + bool nonEmptyReplacements = false; if (debug) { qDebug().nospace() << "CustomWizardContext::replaceFields with " << fm << *s; @@ -633,7 +699,7 @@ void CustomWizardContext::replaceFields(const FieldReplacementMap &fm, QString * modifier = fieldSpec.at(fieldSpecSize - 1).toLatin1(); fieldSpec.truncate(fieldSpecSize - 2); } - const FieldReplacementMap::const_iterator it = fm.constFind(fieldSpec); + const CustomWizardContext::FieldReplacementMap::const_iterator it = fm.constFind(fieldSpec); if (it == fm.constEnd()) { pos = nextPos; // Not found, skip continue; @@ -655,9 +721,64 @@ void CustomWizardContext::replaceFields(const FieldReplacementMap &fm, QString * default: break; } - s->replace(pos, nextPos - pos, replacement); + if (!replacement.isEmpty()) + nonEmptyReplacements = true; + // Apply transformation to empty values as well. + s->replace(pos, nextPos - pos, transform(replacement)); + nonEmptyReplacements = true; pos += replacement.size(); } + return nonEmptyReplacements; +} + +bool CustomWizardContext::replaceFields(const FieldReplacementMap &fm, QString *s) +{ + return replaceFieldHelper(passThrough, fm, s); +} + +// Transformation to be passed to replaceFieldHelper(). Writes the +// value to a text file and returns the file name to be inserted +// instead of the expanded field in the parsed template, +// used for the arguments of a generator script. +class TemporaryFileTransform { +public: + typedef CustomWizardContext::TemporaryFilePtr TemporaryFilePtr; + typedef CustomWizardContext::TemporaryFilePtrList TemporaryFilePtrList; + + explicit TemporaryFileTransform(TemporaryFilePtrList *f); + + QString operator()(const QString &) const; + +private: + TemporaryFilePtrList *m_files; + QString m_pattern; +}; + +TemporaryFileTransform::TemporaryFileTransform(TemporaryFilePtrList *f) : + m_files(f), m_pattern(QDir::tempPath()) +{ + if (!m_pattern.endsWith(QLatin1Char('/'))) + m_pattern += QLatin1Char('/'); + m_pattern += QLatin1String("qtcreatorXXXXXX.txt"); +} + +QString TemporaryFileTransform::operator()(const QString &value) const +{ + TemporaryFilePtr temporaryFile(new QTemporaryFile(m_pattern)); + QTC_ASSERT(temporaryFile->open(), return QString(); ) + + temporaryFile->write(value.toLocal8Bit()); + const QString name = temporaryFile->fileName(); + temporaryFile->flush(); + temporaryFile->close(); + m_files->push_back(temporaryFile); + return name; +} + +bool CustomWizardContext::replaceFields(const FieldReplacementMap &fm, QString *s, + TemporaryFilePtrList *files) +{ + return replaceFieldHelper(TemporaryFileTransform(files), fm, s); } void CustomWizardContext::reset() diff --git a/src/plugins/projectexplorer/customwizard/customwizardparameters.h b/src/plugins/projectexplorer/customwizard/customwizardparameters.h index 64f601d5f7..5c757e2b83 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardparameters.h +++ b/src/plugins/projectexplorer/customwizard/customwizardparameters.h @@ -32,12 +32,14 @@ #include <coreplugin/basefilewizard.h> -#include <QtCore/QList> +#include <QtCore/QStringList> #include <QtCore/QMap> +#include <QtCore/QSharedPointer> QT_BEGIN_NAMESPACE class QIODevice; class QDebug; +class QTemporaryFile; QT_END_NAMESPACE namespace ProjectExplorer { @@ -68,6 +70,23 @@ struct CustomWizardFile { bool openProject; }; +// Argument to the generator script containing placeholders to +// be replaced by field values or file names +// as in '--class-name=%ClassName%' or '--description=%Description%'. +struct GeneratorScriptArgument { + enum Flags { + // Omit this arguments if all field placeholders expanded to empty strings. + OmitEmpty = 0x1, + // Do use the actual field value, but write it to a temporary + // text file and inserts its file name (suitable for multiline texts). + WriteFile = 0x2 }; + + explicit GeneratorScriptArgument(const QString &value = QString()); + + QString value; + unsigned flags; +}; + struct CustomWizardParameters { public: @@ -81,12 +100,12 @@ public: Core::BaseFileWizardParameters *bp, QString *errorMessage); QString toString() const; - QString filesGeneratorScriptFullPath() const; - QString directory; QString klass; QList<CustomWizardFile> files; - QString filesGeneratorScript; + QStringList filesGeneratorScript; // Complete binary, such as 'cmd /c myscript.pl'. + QList<GeneratorScriptArgument> filesGeneratorScriptArguments; + QString fieldPageTitle; QList<CustomWizardField> fields; int firstPageId; @@ -102,14 +121,24 @@ public: struct CustomWizardContext { typedef QMap<QString, QString> FieldReplacementMap; + typedef QSharedPointer<QTemporaryFile> TemporaryFilePtr; + typedef QList<TemporaryFilePtr> TemporaryFilePtrList; void reset(); // Replace field values delimited by '%' with special modifiers: // %Field% -> simple replacement // %Field:l% -> lower case replacement, 'u' upper case, - // 'c' capitalize first letter. - static void replaceFields(const FieldReplacementMap &fm, QString *s); + // 'c' capitalize first letter. Return value indicates whether non-empty + // replacements where encountered + static bool replaceFields(const FieldReplacementMap &fm, QString *s); + + // Special replaceFields() overload used for the arguments of a generator + // script: Write the expanded field values out to temporary files and + // inserts file names instead of the expanded fields in string 's'. + static bool replaceFields(const FieldReplacementMap &fm, QString *s, + TemporaryFilePtrList *files); + static QString processFile(const FieldReplacementMap &fm, QString in); FieldReplacementMap baseReplacements; diff --git a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp index 4fb95c5d42..5b6c2bef19 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp +++ b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp @@ -29,7 +29,9 @@ #include "customwizardscriptgenerator.h" #include "customwizard.h" -#include "customwizardparameters.h" // XML attributes +#include "customwizardparameters.h" + +#include <utils/qtcassert.h> #include <QtCore/QProcess> #include <QtCore/QDir> @@ -41,84 +43,74 @@ namespace ProjectExplorer { namespace Internal { -typedef QSharedPointer<QTemporaryFile> TemporaryFilePtr; - -// Format pattern for temporary files -static inline QString tempFilePattern() -{ - QString tempPattern = QDir::tempPath(); - if (!tempPattern.endsWith(QLatin1Char('/'))) - tempPattern += QLatin1Char('/'); - tempPattern += QLatin1String("qtcreatorXXXXXX.txt"); - return tempPattern; -} - -// Create a temporary file with content -static inline TemporaryFilePtr writeTemporaryFile(const QString &content) +// Parse helper: Determine the correct binary to run: +// Expand to full wizard path if it is relative and located +// in the wizard directory, else assume it can be found in path. +// On Windows, run non-exe files with 'cmd /c'. +QStringList fixGeneratorScript(const QString &configFile, QString binary) { - TemporaryFilePtr temporaryFile(new QTemporaryFile(tempFilePattern())); - if (!temporaryFile->open()) - return TemporaryFilePtr(); - temporaryFile->write(content.toLocal8Bit()); - temporaryFile->close(); - return temporaryFile; + if (binary.isEmpty()) + return QStringList(); + // Expand to full path if it is relative and in the wizard + // directory, else assume it can be found in path. + QFileInfo binaryInfo(binary); + if (!binaryInfo.isAbsolute()) { + QString fullPath = QFileInfo(configFile).absolutePath(); + fullPath += QLatin1Char('/'); + fullPath += binary; + const QFileInfo fullPathInfo(fullPath); + if (fullPathInfo.isFile()) { + binary = fullPathInfo.absoluteFilePath(); + binaryInfo = fullPathInfo; + } + } // not absolute + QStringList rc(binary); +#ifdef Q_OS_WIN // Windows: Cannot run scripts by QProcess, do 'cmd /c' + const QString extension = binaryInfo.suffix(); + if (!extension.isEmpty() && extension.compare(QLatin1String("exe"), Qt::CaseInsensitive) != 0) { + rc.push_front(QLatin1String("/C")); + rc.push_front(QString::fromLocal8Bit(qgetenv("COMSPEC"))); + if (rc.front().isEmpty()) + rc.front() = QLatin1String("cmd.exe"); + } +#endif + return rc; } // Helper for running the optional generation script. static bool runGenerationScriptHelper(const QString &workingDirectory, - QString binary, bool dryRun, + const QStringList &script, + const QList<GeneratorScriptArgument> &argumentsIn, + bool dryRun, const QMap<QString, QString> &fieldMap, QString *stdOut /* = 0 */, QString *errorMessage) { typedef QSharedPointer<QTemporaryFile> TemporaryFilePtr; typedef QList<TemporaryFilePtr> TemporaryFilePtrList; - typedef QMap<QString, QString>::const_iterator FieldConstIterator; QProcess process; + const QString binary = script.front(); QStringList arguments; - // Check on the process - const QFileInfo binaryInfo(binary); - if (!binaryInfo.isFile()) { - *errorMessage = QString::fromLatin1("The Generator script %1 does not exist").arg(binary); - return false; - } -#ifdef Q_OS_WIN // Windows: Cannot run scripts by QProcess, do 'cmd /c' - const QString extension = binaryInfo.suffix(); - if (!extension.isEmpty() && extension.compare(QLatin1String("exe"), Qt::CaseInsensitive) != 0) { - arguments.push_back(QLatin1String("/C")); - arguments.push_back(binary); - binary = QString::fromLocal8Bit(qgetenv("COMSPEC")); - if (binary.isEmpty()) - binary = QLatin1String("cmd.exe"); - } -#endif // Q_OS_WIN - // Arguments + const int binarySize = script.size(); + for (int i = 1; i < binarySize; i++) + arguments.push_back(script.at(i)); + + // Arguments: Prepend 'dryrun' and do field replacement if (dryRun) - arguments << QLatin1String("--dry-run"); - // Turn the field replacement map into a list of arguments "key=value". - // Pass on free-format-texts as a temporary files indicated by a colon - // separator "key:filename" - TemporaryFilePtrList temporaryFiles; + arguments.push_back(QLatin1String("--dry-run")); - const FieldConstIterator cend = fieldMap.constEnd(); - for (FieldConstIterator it = fieldMap.constBegin(); it != cend; ++it) { - const QString &value = it.value(); - // Is a temporary file required? - const bool passAsTemporaryFile = value.contains(QLatin1Char('\n')); - if (passAsTemporaryFile) { - // Create a file and pass on as "key:filename" - TemporaryFilePtr temporaryFile = writeTemporaryFile(value); - if (temporaryFile.isNull()) { - *errorMessage = QString::fromLatin1("Cannot create temporary file"); - return false; - } - temporaryFiles.push_back(temporaryFile); - arguments << (it.key() + QLatin1Char(':') + QDir::toNativeSeparators(temporaryFile->fileName())); - } else { - // Normal value "key=value" - arguments << (it.key() + QLatin1Char('=') + value); - } + // Arguments: Prepend 'dryrun'. Do field replacement to actual + // argument value to expand via temporary file if specified + CustomWizardContext::TemporaryFilePtrList temporaryFiles; + foreach (const GeneratorScriptArgument &argument, argumentsIn) { + QString value = argument.value; + const bool nonEmptyReplacements + = argument.flags & GeneratorScriptArgument::WriteFile ? + CustomWizardContext::replaceFields(fieldMap, &value, &temporaryFiles) : + CustomWizardContext::replaceFields(fieldMap, &value); + if (nonEmptyReplacements || !(argument.flags & GeneratorScriptArgument::OmitEmpty)) + arguments.push_back(value); } process.setWorkingDirectory(workingDirectory); if (CustomWizard::verbose()) @@ -157,13 +149,14 @@ static bool // Do a dry run of the generation script to get a list of files Core::GeneratedFiles dryRunCustomWizardGeneratorScript(const QString &targetPath, - const QString &script, + const QStringList &script, + const QList<GeneratorScriptArgument> &arguments, const QMap<QString, QString> &fieldMap, QString *errorMessage) { // Run in temporary directory as the target path may not exist yet. QString stdOut; - if (!runGenerationScriptHelper(QDir::tempPath(), script, true, + if (!runGenerationScriptHelper(QDir::tempPath(), script, arguments, true, fieldMap, &stdOut, errorMessage)) return Core::GeneratedFiles(); Core::GeneratedFiles files; @@ -199,10 +192,14 @@ Core::GeneratedFiles return files; } -bool runCustomWizardGeneratorScript(const QString &targetPath, const QString &script, - const QMap<QString, QString> &fieldMap, QString *errorMessage) +bool runCustomWizardGeneratorScript(const QString &targetPath, + const QStringList &script, + const QList<GeneratorScriptArgument> &arguments, + const QMap<QString, QString> &fieldMap, + QString *errorMessage) { - return runGenerationScriptHelper(targetPath, script, false, fieldMap, + return runGenerationScriptHelper(targetPath, script, arguments, + false, fieldMap, 0, errorMessage); } diff --git a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.h b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.h index d47168b3f9..6010a97e1b 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.h +++ b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.h @@ -31,8 +31,7 @@ #define CUSTOMWIZARDSCRIPTGENERATOR_H #include <QtCore/QMap> -#include <QtCore/QList> -#include <QtCore/QString> +#include <QtCore/QStringList> namespace Core { class GeneratedFile; @@ -41,6 +40,8 @@ class GeneratedFile; namespace ProjectExplorer { namespace Internal { +struct GeneratorScriptArgument; + /* Custom wizard script generator functions. In addition to the <file> elements * that define template files in which macros are replaced, it is possible to have * a custom wizard call a generation script (specified in the "generatorscript" @@ -64,14 +65,21 @@ namespace Internal { * should create those, too. */ +// Parse the script arguments apart and expand the binary. +QStringList fixGeneratorScript(const QString &configFile, QString attributeIn); + // Step 1) Do a dry run of the generation script to get a list of files on stdout QList<Core::GeneratedFile> - dryRunCustomWizardGeneratorScript(const QString &targetPath, const QString &script, + dryRunCustomWizardGeneratorScript(const QString &targetPath, + const QStringList &script, + const QList<GeneratorScriptArgument> &arguments, const QMap<QString, QString> &fieldMap, QString *errorMessage); // Step 2) Generate files -bool runCustomWizardGeneratorScript(const QString &targetPath, const QString &script, +bool runCustomWizardGeneratorScript(const QString &targetPath, + const QStringList &script, + const QList<GeneratorScriptArgument> &arguments, const QMap<QString, QString> &fieldMap, QString *errorMessage); |