forked from qt-creator/qt-creator
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).
This commit is contained in:
@@ -34,45 +34,59 @@ use Getopt::Long;
|
|||||||
use IO::File;
|
use IO::File;
|
||||||
|
|
||||||
my $optDryRun = 0;
|
my $optDryRun = 0;
|
||||||
my $fieldClassName = 'MyClass';
|
my $optHelp = 0;
|
||||||
my $standardFieldProjectName = 'MyProject';
|
my $optClassName = 'MyClass';
|
||||||
my $standardFieldCppHeaderSuffix = 'h';
|
my $optProjectName = 'MyProject';
|
||||||
my $standardFieldCppSourceSuffix = 'cpp';
|
my $optCppHeaderSuffix = 'h';
|
||||||
|
my $optCppSourceSuffix = 'cpp';
|
||||||
|
my $optDescription = '';
|
||||||
|
|
||||||
|
# -- Read in a file and return its lines
|
||||||
|
sub readFile
|
||||||
|
{
|
||||||
|
my ($fileName) = @_;
|
||||||
|
my @rc = ();
|
||||||
|
my $fh = new IO::File('<' . $fileName) or die ('Unable to open for reading ' . $fileName . ' :' . $!);
|
||||||
|
while (my $line = <$fh>) {
|
||||||
|
chomp($line);
|
||||||
|
push (@rc, $line);
|
||||||
|
}
|
||||||
|
$fh->close();
|
||||||
|
return @rc;
|
||||||
|
}
|
||||||
|
|
||||||
my $USAGE=<<EOF;
|
my $USAGE=<<EOF;
|
||||||
Usage: generate.pl [--dry-run] <parameter-mappings>
|
Usage: generate.pl [--help] | [--dry-run]
|
||||||
|
[--class-name=<class name>]
|
||||||
|
[--project-name=<project name>]
|
||||||
|
[--header-suffix=<header suffix>]
|
||||||
|
[--source-suffix=<source suffix>]
|
||||||
|
[--description=<description-file>]
|
||||||
|
|
||||||
Custom wizard project generation example script.
|
Custom wizard project generation example script.
|
||||||
|
|
||||||
Known parameters: ClassName=<value>
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
if (!GetOptions("dry-run" => \$optDryRun)) {
|
my $argCount = scalar(@ARGV);
|
||||||
|
if ($argCount == 0
|
||||||
|
|| !GetOptions("help" => \$optHelp,
|
||||||
|
"dry-run" => \$optDryRun,
|
||||||
|
"class-name:s" => \$optClassName,
|
||||||
|
"project-name:s" => \$optProjectName,
|
||||||
|
"header-suffix:s" => \$optCppHeaderSuffix,
|
||||||
|
"source-suffix:s" => \$optCppSourceSuffix,
|
||||||
|
"description:s" => \$optDescription)
|
||||||
|
|| $optHelp != 0) {
|
||||||
print $USAGE;
|
print $USAGE;
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scalar(@ARGV) == 0) {
|
|
||||||
print $USAGE;
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
# -- Parse the 'field=value' pairs
|
|
||||||
foreach my $arg (@ARGV) {
|
|
||||||
my ($key, $value) = split('=', $arg);
|
|
||||||
$fieldClassName = $value if ($key eq 'ClassName');
|
|
||||||
# -- Standard fields defined by the custom project wizard
|
|
||||||
$standardFieldProjectName = $value if ($key eq 'ProjectName');
|
|
||||||
$standardFieldCppHeaderSuffix = $value if ($key eq 'CppHeaderSuffix');
|
|
||||||
$standardFieldCppSourceSuffix = $value if ($key eq 'CppSourceSuffix');
|
|
||||||
}
|
|
||||||
|
|
||||||
# -- Determine file names
|
# -- Determine file names
|
||||||
my $baseFileName = lc($fieldClassName);
|
my $baseFileName = lc($optClassName);
|
||||||
my $sourceFileName = $baseFileName . '.' . $standardFieldCppSourceSuffix;
|
my $sourceFileName = $baseFileName . '.' . $optCppSourceSuffix;
|
||||||
my $headerFileName = $baseFileName . '.' . $standardFieldCppHeaderSuffix;
|
my $headerFileName = $baseFileName . '.' . $optCppHeaderSuffix;
|
||||||
my $mainSourceFileName = 'main.' . $standardFieldCppSourceSuffix;
|
my $mainSourceFileName = 'main.' . $optCppSourceSuffix;
|
||||||
my $projectFileName = lc($standardFieldProjectName) . '.pro';
|
my $projectFileName = lc($optProjectName) . '.pro';
|
||||||
|
|
||||||
if ($optDryRun) {
|
if ($optDryRun) {
|
||||||
# -- Step 1) Dry run: Print file names along with attributes
|
# -- Step 1) Dry run: Print file names along with attributes
|
||||||
@@ -85,23 +99,29 @@ if ($optDryRun) {
|
|||||||
print 'Generating ', $headerFileName, ' ', $sourceFileName, ' ',
|
print 'Generating ', $headerFileName, ' ', $sourceFileName, ' ',
|
||||||
$mainSourceFileName, ' ', $projectFileName, "\n";
|
$mainSourceFileName, ' ', $projectFileName, "\n";
|
||||||
my $headerFile = new IO::File('>' . $headerFileName) or die ('Unable to open ' . $headerFileName . ' :' . $!);
|
my $headerFile = new IO::File('>' . $headerFileName) or die ('Unable to open ' . $headerFileName . ' :' . $!);
|
||||||
print $headerFile '#ifndef ', uc($fieldClassName), "_H\n#define ", uc($fieldClassName), "_H\n\n",
|
print $headerFile '#ifndef ', uc($optClassName), "_H\n#define ", uc($optClassName), "_H\n\n",
|
||||||
'class ', $fieldClassName, "{\npublic:\n ", $fieldClassName, "();\n\n};\n\n#endif\n";
|
'class ', $optClassName, "{\npublic:\n ", $optClassName, "();\n\n};\n\n#endif\n";
|
||||||
$headerFile->close();
|
$headerFile->close();
|
||||||
|
|
||||||
my $sourceFile = new IO::File('>' . $sourceFileName) or die ('Unable to open ' . $sourceFileName . ' :' . $!);
|
my $sourceFile = new IO::File('>' . $sourceFileName) or die ('Unable to open ' . $sourceFileName . ' :' . $!);
|
||||||
print $sourceFile '#include "', $headerFileName ,"\"\n\n",
|
print $sourceFile '#include "', $headerFileName ,"\"\n\n",
|
||||||
$fieldClassName,'::', $fieldClassName, "()\n{\n}\n";
|
$optClassName,'::', $optClassName, "()\n{\n}\n";
|
||||||
$sourceFile->close();
|
$sourceFile->close();
|
||||||
|
|
||||||
my $mainSourceFile = new IO::File('>' . $mainSourceFileName) or die ('Unable to open ' . $mainSourceFileName . ' :' . $!);
|
my $mainSourceFile = new IO::File('>' . $mainSourceFileName) or die ('Unable to open ' . $mainSourceFileName . ' :' . $!);
|
||||||
print $mainSourceFile '#include "', $headerFileName ,"\"\n\n",
|
print $mainSourceFile '#include "', $headerFileName ,"\"\n\n";
|
||||||
"int main(int argc, char *argv[])\n{\n ", $fieldClassName,' ', lc($fieldClassName),
|
# -- Write out description comments
|
||||||
|
if ($optDescription ne '') {
|
||||||
|
foreach my $description (readFile($optDescription)) {
|
||||||
|
print $mainSourceFile '// ', $description, "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print $mainSourceFile "int main(int argc, char *argv[])\n{\n ", $optClassName,' ', lc($optClassName),
|
||||||
";\n return 0;\n}\n";
|
";\n return 0;\n}\n";
|
||||||
$mainSourceFile->close();
|
$mainSourceFile->close();
|
||||||
|
|
||||||
my $projectFile = new IO::File('>' . $projectFileName) or die ('Unable to open ' . $projectFileName . ' :' . $!);
|
my $projectFile = new IO::File('>' . $projectFileName) or die ('Unable to open ' . $projectFileName . ' :' . $!);
|
||||||
print $projectFile "TEMPLATE = app\nQT -= core\nCONFIG += console\nTARGET = ", $standardFieldProjectName,
|
print $projectFile "TEMPLATE = app\nQT -= core\nCONFIG += console\nTARGET = ", $optProjectName,
|
||||||
"\nSOURCES += ", $sourceFileName, ' ',$headerFileName, ' ', $mainSourceFileName,
|
"\nSOURCES += ", $sourceFileName, ' ',$headerFileName, ' ', $mainSourceFileName,
|
||||||
"\nHEADERS += ", $headerFileName,"\n";
|
"\nHEADERS += ", $headerFileName,"\n";
|
||||||
$projectFile->close();
|
$projectFile->close();
|
||||||
|
|||||||
@@ -34,8 +34,6 @@ Custom class wizard example configuration file. -->
|
|||||||
<description>Creates a simple project using a generator script</description>
|
<description>Creates a simple project using a generator script</description>
|
||||||
<displayname>Simple Script-Generated Project</displayname>;
|
<displayname>Simple Script-Generated Project</displayname>;
|
||||||
<displaycategory>Custom Projects</displaycategory>
|
<displaycategory>Custom Projects</displaycategory>
|
||||||
<!-- Specify the generator script -->
|
|
||||||
<files generatorscript="generate.pl"/>
|
|
||||||
<!-- Create parameter wizard page -->
|
<!-- Create parameter wizard page -->
|
||||||
<fieldpagetitle>Simple Script-Generated Project Parameters</fieldpagetitle>
|
<fieldpagetitle>Simple Script-Generated Project Parameters</fieldpagetitle>
|
||||||
<fields>
|
<fields>
|
||||||
@@ -43,5 +41,19 @@ Custom class wizard example configuration file. -->
|
|||||||
<fieldcontrol class="QLineEdit" validator="^[a-zA-Z0-9_]+$" defaulttext="MyClass" />
|
<fieldcontrol class="QLineEdit" validator="^[a-zA-Z0-9_]+$" defaulttext="MyClass" />
|
||||||
<fielddescription>Class name:</fielddescription>
|
<fielddescription>Class name:</fielddescription>
|
||||||
</field>
|
</field>
|
||||||
|
<!-- Description will be inserted as a multi-line C++-comment -->
|
||||||
|
<field name="Description">
|
||||||
|
<fieldcontrol class="QTextEdit" defaulttext="Enter description" />
|
||||||
|
<fielddescription>Description:</fielddescription>
|
||||||
|
</field>
|
||||||
</fields>
|
</fields>
|
||||||
|
<!-- Specify the generator script -->
|
||||||
|
<generatorscript binary="generate.pl">
|
||||||
|
<argument value="--class-name=%ClassName%"/>
|
||||||
|
<argument value="--project-name=%ProjectName%"/>
|
||||||
|
<argument value="--header-suffix=%CppHeaderSuffix%" omit-empty="true"/>
|
||||||
|
<argument value="--source-suffix=%CppSourceSuffix%" omit-empty="true"/>
|
||||||
|
<!-- Multi-line description passed as temporary file unless empty -->
|
||||||
|
<argument value="--description=%Description%" omit-empty="true" write-file="true"/>
|
||||||
|
</generatorscript>
|
||||||
</wizard>
|
</wizard>
|
||||||
|
|||||||
@@ -225,7 +225,9 @@ bool CustomWizard::writeFiles(const Core::GeneratedFiles &files, QString *errorM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Run the custom script to actually generate the files.
|
// 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))
|
ctx->replacements, errorMessage))
|
||||||
return false;
|
return false;
|
||||||
// Paranoia: Check on the files generated by the script:
|
// 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 (generatedFile.attributes() & Core::GeneratedFile::CustomGeneratorAttribute)
|
||||||
if (!QFileInfo(generatedFile.path()).isFile()) {
|
if (!QFileInfo(generatedFile.path()).isFile()) {
|
||||||
*errorMessage = QString::fromLatin1("%1 failed to generate %2").
|
*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 false;
|
||||||
}
|
}
|
||||||
return true;
|
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 generator script is non-empty, do a dry run to get it's files.
|
||||||
if (!d->m_parameters->filesGeneratorScript.isEmpty()) {
|
if (!d->m_parameters->filesGeneratorScript.isEmpty()) {
|
||||||
rc += Internal::dryRunCustomWizardGeneratorScript(ctx->targetPath,
|
rc += Internal::dryRunCustomWizardGeneratorScript(ctx->targetPath,
|
||||||
d->m_parameters->filesGeneratorScriptFullPath(),
|
d->m_parameters->filesGeneratorScript,
|
||||||
|
d->m_parameters->filesGeneratorScriptArguments,
|
||||||
ctx->replacements, errorMessage);
|
ctx->replacements, errorMessage);
|
||||||
if (rc.isEmpty())
|
if (rc.isEmpty())
|
||||||
return rc;
|
return rc;
|
||||||
|
|||||||
@@ -29,18 +29,24 @@
|
|||||||
|
|
||||||
#include "customwizardparameters.h"
|
#include "customwizardparameters.h"
|
||||||
#include "customwizardpreprocessor.h"
|
#include "customwizardpreprocessor.h"
|
||||||
|
#include "customwizardscriptgenerator.h"
|
||||||
|
|
||||||
#include <coreplugin/mimedatabase.h>
|
#include <coreplugin/mimedatabase.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <cpptools/cpptoolsconstants.h>
|
#include <cpptools/cpptoolsconstants.h>
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QCoreApplication>
|
#include <QtCore/QCoreApplication>
|
||||||
#include <QtCore/QLocale>
|
#include <QtCore/QLocale>
|
||||||
#include <QtCore/QFile>
|
#include <QtCore/QFile>
|
||||||
|
#include <QtCore/QDir>
|
||||||
#include <QtCore/QFileInfo>
|
#include <QtCore/QFileInfo>
|
||||||
#include <QtCore/QXmlStreamReader>
|
#include <QtCore/QXmlStreamReader>
|
||||||
#include <QtCore/QXmlStreamAttribute>
|
#include <QtCore/QXmlStreamAttribute>
|
||||||
|
#include <QtCore/QTemporaryFile>
|
||||||
|
|
||||||
#include <QtGui/QIcon>
|
#include <QtGui/QIcon>
|
||||||
|
|
||||||
enum { debug = 0 };
|
enum { debug = 0 };
|
||||||
@@ -64,6 +70,13 @@ static const char comboEntriesElementC[] = "comboentries";
|
|||||||
static const char comboEntryElementC[] = "comboentry";
|
static const char comboEntryElementC[] = "comboentry";
|
||||||
static const char comboEntryTextElementC[] = "comboentrytext";
|
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 fieldDescriptionElementC[] = "fielddescription";
|
||||||
static const char fieldNameAttributeC[] = "name";
|
static const char fieldNameAttributeC[] = "name";
|
||||||
static const char fieldMandatoryAttributeC[] = "mandatory";
|
static const char fieldMandatoryAttributeC[] = "mandatory";
|
||||||
@@ -87,6 +100,8 @@ enum ParseState {
|
|||||||
ParseWithinComboEntryText,
|
ParseWithinComboEntryText,
|
||||||
ParseWithinFiles,
|
ParseWithinFiles,
|
||||||
ParseWithinFile,
|
ParseWithinFile,
|
||||||
|
ParseWithinScript,
|
||||||
|
ParseWithinScriptArguments,
|
||||||
ParseError
|
ParseError
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -136,6 +151,7 @@ void CustomWizardParameters::clear()
|
|||||||
files.clear();
|
files.clear();
|
||||||
fields.clear();
|
fields.clear();
|
||||||
filesGeneratorScript.clear();
|
filesGeneratorScript.clear();
|
||||||
|
filesGeneratorScriptArguments.clear();
|
||||||
firstPageId = -1;
|
firstPageId = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,6 +292,8 @@ static ParseState nextOpeningState(ParseState in, const QStringRef &name)
|
|||||||
return ParseWithinFields;
|
return ParseWithinFields;
|
||||||
if (name == QLatin1String(filesElementC))
|
if (name == QLatin1String(filesElementC))
|
||||||
return ParseWithinFiles;
|
return ParseWithinFiles;
|
||||||
|
if (name == QLatin1String(generatorScriptElementC))
|
||||||
|
return ParseWithinScript;
|
||||||
break;
|
break;
|
||||||
case ParseWithinFields:
|
case ParseWithinFields:
|
||||||
if (name == QLatin1String(fieldElementC))
|
if (name == QLatin1String(fieldElementC))
|
||||||
@@ -303,10 +321,15 @@ static ParseState nextOpeningState(ParseState in, const QStringRef &name)
|
|||||||
if (name == QLatin1String(fileElementC))
|
if (name == QLatin1String(fileElementC))
|
||||||
return ParseWithinFile;
|
return ParseWithinFile;
|
||||||
break;
|
break;
|
||||||
|
case ParseWithinScript:
|
||||||
|
if (name == QLatin1String(generatorScriptArgumentElementC))
|
||||||
|
return ParseWithinScriptArguments;
|
||||||
|
break;
|
||||||
case ParseWithinFieldDescription: // No subelements
|
case ParseWithinFieldDescription: // No subelements
|
||||||
case ParseWithinComboEntryText:
|
case ParseWithinComboEntryText:
|
||||||
case ParseWithinFile:
|
case ParseWithinFile:
|
||||||
case ParseError:
|
case ParseError:
|
||||||
|
case ParseWithinScriptArguments:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return ParseError;
|
return ParseError;
|
||||||
@@ -358,6 +381,14 @@ static ParseState nextClosingState(ParseState in, const QStringRef &name)
|
|||||||
if (name == QLatin1String(comboEntryTextElementC))
|
if (name == QLatin1String(comboEntryTextElementC))
|
||||||
return ParseWithinComboEntry;
|
return ParseWithinComboEntry;
|
||||||
break;
|
break;
|
||||||
|
case ParseWithinScript:
|
||||||
|
if (name == QLatin1String(generatorScriptElementC))
|
||||||
|
return ParseWithinWizard;
|
||||||
|
break;
|
||||||
|
case ParseWithinScriptArguments:
|
||||||
|
if (name == QLatin1String(generatorScriptArgumentElementC))
|
||||||
|
return ParseWithinScript;
|
||||||
|
break;
|
||||||
case ParseError:
|
case ParseError:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -427,6 +458,11 @@ static inline QString localeLanguage()
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GeneratorScriptArgument::GeneratorScriptArgument(const QString &v) :
|
||||||
|
value(v), flags(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Main parsing routine
|
// Main parsing routine
|
||||||
CustomWizardParameters::ParseResult
|
CustomWizardParameters::ParseResult
|
||||||
CustomWizardParameters::parse(QIODevice &device,
|
CustomWizardParameters::parse(QIODevice &device,
|
||||||
@@ -499,7 +535,6 @@ CustomWizardParameters::ParseResult
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ParseWithinFiles:
|
case ParseWithinFiles:
|
||||||
filesGeneratorScript = attributeValue(reader, filesGeneratorScriptAttributeC);
|
|
||||||
break;
|
break;
|
||||||
case ParseWithinFile: { // file attribute
|
case ParseWithinFile: { // file attribute
|
||||||
CustomWizardFile file;
|
CustomWizardFile file;
|
||||||
@@ -516,6 +551,26 @@ CustomWizardParameters::ParseResult
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -559,23 +614,26 @@ CustomWizardParameters::ParseResult
|
|||||||
return parse(configFile, configFileFullPath, bp, errorMessage);
|
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 CustomWizardParameters::toString() const
|
||||||
{
|
{
|
||||||
QString rc;
|
QString rc;
|
||||||
QTextStream str(&rc);
|
QTextStream str(&rc);
|
||||||
str << "Directory: " << directory << " Klass: '" << klass << "'\n";
|
str << "Directory: " << directory << " Klass: '" << klass << "'\n";
|
||||||
if (!filesGeneratorScript.isEmpty())
|
if (!filesGeneratorScriptArguments.isEmpty()) {
|
||||||
str << "Script: '" << filesGeneratorScript << "'\n";
|
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) {
|
foreach(const CustomWizardFile &f, files) {
|
||||||
str << " File source: " << f.source << " Target: " << f.target;
|
str << " File source: " << f.source << " Target: " << f.target;
|
||||||
if (f.openEditor)
|
if (f.openEditor)
|
||||||
@@ -603,8 +661,16 @@ QString CustomWizardParameters::toString() const
|
|||||||
|
|
||||||
// ------------ CustomWizardContext
|
// ------------ 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) {
|
if (debug) {
|
||||||
qDebug().nospace() << "CustomWizardContext::replaceFields with " <<
|
qDebug().nospace() << "CustomWizardContext::replaceFields with " <<
|
||||||
fm << *s;
|
fm << *s;
|
||||||
@@ -633,7 +699,7 @@ void CustomWizardContext::replaceFields(const FieldReplacementMap &fm, QString *
|
|||||||
modifier = fieldSpec.at(fieldSpecSize - 1).toLatin1();
|
modifier = fieldSpec.at(fieldSpecSize - 1).toLatin1();
|
||||||
fieldSpec.truncate(fieldSpecSize - 2);
|
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()) {
|
if (it == fm.constEnd()) {
|
||||||
pos = nextPos; // Not found, skip
|
pos = nextPos; // Not found, skip
|
||||||
continue;
|
continue;
|
||||||
@@ -655,9 +721,64 @@ void CustomWizardContext::replaceFields(const FieldReplacementMap &fm, QString *
|
|||||||
default:
|
default:
|
||||||
break;
|
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();
|
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()
|
void CustomWizardContext::reset()
|
||||||
|
|||||||
@@ -32,12 +32,14 @@
|
|||||||
|
|
||||||
#include <coreplugin/basefilewizard.h>
|
#include <coreplugin/basefilewizard.h>
|
||||||
|
|
||||||
#include <QtCore/QList>
|
#include <QtCore/QStringList>
|
||||||
#include <QtCore/QMap>
|
#include <QtCore/QMap>
|
||||||
|
#include <QtCore/QSharedPointer>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QIODevice;
|
class QIODevice;
|
||||||
class QDebug;
|
class QDebug;
|
||||||
|
class QTemporaryFile;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
@@ -68,6 +70,23 @@ struct CustomWizardFile {
|
|||||||
bool openProject;
|
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
|
struct CustomWizardParameters
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -81,12 +100,12 @@ public:
|
|||||||
Core::BaseFileWizardParameters *bp, QString *errorMessage);
|
Core::BaseFileWizardParameters *bp, QString *errorMessage);
|
||||||
QString toString() const;
|
QString toString() const;
|
||||||
|
|
||||||
QString filesGeneratorScriptFullPath() const;
|
|
||||||
|
|
||||||
QString directory;
|
QString directory;
|
||||||
QString klass;
|
QString klass;
|
||||||
QList<CustomWizardFile> files;
|
QList<CustomWizardFile> files;
|
||||||
QString filesGeneratorScript;
|
QStringList filesGeneratorScript; // Complete binary, such as 'cmd /c myscript.pl'.
|
||||||
|
QList<GeneratorScriptArgument> filesGeneratorScriptArguments;
|
||||||
|
|
||||||
QString fieldPageTitle;
|
QString fieldPageTitle;
|
||||||
QList<CustomWizardField> fields;
|
QList<CustomWizardField> fields;
|
||||||
int firstPageId;
|
int firstPageId;
|
||||||
@@ -102,14 +121,24 @@ public:
|
|||||||
|
|
||||||
struct CustomWizardContext {
|
struct CustomWizardContext {
|
||||||
typedef QMap<QString, QString> FieldReplacementMap;
|
typedef QMap<QString, QString> FieldReplacementMap;
|
||||||
|
typedef QSharedPointer<QTemporaryFile> TemporaryFilePtr;
|
||||||
|
typedef QList<TemporaryFilePtr> TemporaryFilePtrList;
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
// Replace field values delimited by '%' with special modifiers:
|
// Replace field values delimited by '%' with special modifiers:
|
||||||
// %Field% -> simple replacement
|
// %Field% -> simple replacement
|
||||||
// %Field:l% -> lower case replacement, 'u' upper case,
|
// %Field:l% -> lower case replacement, 'u' upper case,
|
||||||
// 'c' capitalize first letter.
|
// 'c' capitalize first letter. Return value indicates whether non-empty
|
||||||
static void replaceFields(const FieldReplacementMap &fm, QString *s);
|
// 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);
|
static QString processFile(const FieldReplacementMap &fm, QString in);
|
||||||
|
|
||||||
FieldReplacementMap baseReplacements;
|
FieldReplacementMap baseReplacements;
|
||||||
|
|||||||
@@ -29,7 +29,9 @@
|
|||||||
|
|
||||||
#include "customwizardscriptgenerator.h"
|
#include "customwizardscriptgenerator.h"
|
||||||
#include "customwizard.h"
|
#include "customwizard.h"
|
||||||
#include "customwizardparameters.h" // XML attributes
|
#include "customwizardparameters.h"
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QtCore/QProcess>
|
#include <QtCore/QProcess>
|
||||||
#include <QtCore/QDir>
|
#include <QtCore/QDir>
|
||||||
@@ -41,84 +43,74 @@
|
|||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
typedef QSharedPointer<QTemporaryFile> TemporaryFilePtr;
|
// Parse helper: Determine the correct binary to run:
|
||||||
|
// Expand to full wizard path if it is relative and located
|
||||||
// Format pattern for temporary files
|
// in the wizard directory, else assume it can be found in path.
|
||||||
static inline QString tempFilePattern()
|
// On Windows, run non-exe files with 'cmd /c'.
|
||||||
|
QStringList fixGeneratorScript(const QString &configFile, QString binary)
|
||||||
{
|
{
|
||||||
QString tempPattern = QDir::tempPath();
|
if (binary.isEmpty())
|
||||||
if (!tempPattern.endsWith(QLatin1Char('/')))
|
return QStringList();
|
||||||
tempPattern += QLatin1Char('/');
|
// Expand to full path if it is relative and in the wizard
|
||||||
tempPattern += QLatin1String("qtcreatorXXXXXX.txt");
|
// directory, else assume it can be found in path.
|
||||||
return tempPattern;
|
QFileInfo binaryInfo(binary);
|
||||||
}
|
if (!binaryInfo.isAbsolute()) {
|
||||||
|
QString fullPath = QFileInfo(configFile).absolutePath();
|
||||||
// Create a temporary file with content
|
fullPath += QLatin1Char('/');
|
||||||
static inline TemporaryFilePtr writeTemporaryFile(const QString &content)
|
fullPath += binary;
|
||||||
{
|
const QFileInfo fullPathInfo(fullPath);
|
||||||
TemporaryFilePtr temporaryFile(new QTemporaryFile(tempFilePattern()));
|
if (fullPathInfo.isFile()) {
|
||||||
if (!temporaryFile->open())
|
binary = fullPathInfo.absoluteFilePath();
|
||||||
return TemporaryFilePtr();
|
binaryInfo = fullPathInfo;
|
||||||
temporaryFile->write(content.toLocal8Bit());
|
}
|
||||||
temporaryFile->close();
|
} // not absolute
|
||||||
return temporaryFile;
|
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.
|
// Helper for running the optional generation script.
|
||||||
static bool
|
static bool
|
||||||
runGenerationScriptHelper(const QString &workingDirectory,
|
runGenerationScriptHelper(const QString &workingDirectory,
|
||||||
QString binary, bool dryRun,
|
const QStringList &script,
|
||||||
|
const QList<GeneratorScriptArgument> &argumentsIn,
|
||||||
|
bool dryRun,
|
||||||
const QMap<QString, QString> &fieldMap,
|
const QMap<QString, QString> &fieldMap,
|
||||||
QString *stdOut /* = 0 */, QString *errorMessage)
|
QString *stdOut /* = 0 */, QString *errorMessage)
|
||||||
{
|
{
|
||||||
typedef QSharedPointer<QTemporaryFile> TemporaryFilePtr;
|
typedef QSharedPointer<QTemporaryFile> TemporaryFilePtr;
|
||||||
typedef QList<TemporaryFilePtr> TemporaryFilePtrList;
|
typedef QList<TemporaryFilePtr> TemporaryFilePtrList;
|
||||||
typedef QMap<QString, QString>::const_iterator FieldConstIterator;
|
|
||||||
|
|
||||||
QProcess process;
|
QProcess process;
|
||||||
|
const QString binary = script.front();
|
||||||
QStringList arguments;
|
QStringList arguments;
|
||||||
// Check on the process
|
const int binarySize = script.size();
|
||||||
const QFileInfo binaryInfo(binary);
|
for (int i = 1; i < binarySize; i++)
|
||||||
if (!binaryInfo.isFile()) {
|
arguments.push_back(script.at(i));
|
||||||
*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
|
|
||||||
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;
|
|
||||||
|
|
||||||
const FieldConstIterator cend = fieldMap.constEnd();
|
// Arguments: Prepend 'dryrun' and do field replacement
|
||||||
for (FieldConstIterator it = fieldMap.constBegin(); it != cend; ++it) {
|
if (dryRun)
|
||||||
const QString &value = it.value();
|
arguments.push_back(QLatin1String("--dry-run"));
|
||||||
// Is a temporary file required?
|
|
||||||
const bool passAsTemporaryFile = value.contains(QLatin1Char('\n'));
|
// Arguments: Prepend 'dryrun'. Do field replacement to actual
|
||||||
if (passAsTemporaryFile) {
|
// argument value to expand via temporary file if specified
|
||||||
// Create a file and pass on as "key:filename"
|
CustomWizardContext::TemporaryFilePtrList temporaryFiles;
|
||||||
TemporaryFilePtr temporaryFile = writeTemporaryFile(value);
|
foreach (const GeneratorScriptArgument &argument, argumentsIn) {
|
||||||
if (temporaryFile.isNull()) {
|
QString value = argument.value;
|
||||||
*errorMessage = QString::fromLatin1("Cannot create temporary file");
|
const bool nonEmptyReplacements
|
||||||
return false;
|
= argument.flags & GeneratorScriptArgument::WriteFile ?
|
||||||
}
|
CustomWizardContext::replaceFields(fieldMap, &value, &temporaryFiles) :
|
||||||
temporaryFiles.push_back(temporaryFile);
|
CustomWizardContext::replaceFields(fieldMap, &value);
|
||||||
arguments << (it.key() + QLatin1Char(':') + QDir::toNativeSeparators(temporaryFile->fileName()));
|
if (nonEmptyReplacements || !(argument.flags & GeneratorScriptArgument::OmitEmpty))
|
||||||
} else {
|
arguments.push_back(value);
|
||||||
// Normal value "key=value"
|
|
||||||
arguments << (it.key() + QLatin1Char('=') + value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
process.setWorkingDirectory(workingDirectory);
|
process.setWorkingDirectory(workingDirectory);
|
||||||
if (CustomWizard::verbose())
|
if (CustomWizard::verbose())
|
||||||
@@ -157,13 +149,14 @@ static bool
|
|||||||
// Do a dry run of the generation script to get a list of files
|
// Do a dry run of the generation script to get a list of files
|
||||||
Core::GeneratedFiles
|
Core::GeneratedFiles
|
||||||
dryRunCustomWizardGeneratorScript(const QString &targetPath,
|
dryRunCustomWizardGeneratorScript(const QString &targetPath,
|
||||||
const QString &script,
|
const QStringList &script,
|
||||||
|
const QList<GeneratorScriptArgument> &arguments,
|
||||||
const QMap<QString, QString> &fieldMap,
|
const QMap<QString, QString> &fieldMap,
|
||||||
QString *errorMessage)
|
QString *errorMessage)
|
||||||
{
|
{
|
||||||
// Run in temporary directory as the target path may not exist yet.
|
// Run in temporary directory as the target path may not exist yet.
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
if (!runGenerationScriptHelper(QDir::tempPath(), script, true,
|
if (!runGenerationScriptHelper(QDir::tempPath(), script, arguments, true,
|
||||||
fieldMap, &stdOut, errorMessage))
|
fieldMap, &stdOut, errorMessage))
|
||||||
return Core::GeneratedFiles();
|
return Core::GeneratedFiles();
|
||||||
Core::GeneratedFiles files;
|
Core::GeneratedFiles files;
|
||||||
@@ -199,10 +192,14 @@ Core::GeneratedFiles
|
|||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool runCustomWizardGeneratorScript(const QString &targetPath, const QString &script,
|
bool runCustomWizardGeneratorScript(const QString &targetPath,
|
||||||
const QMap<QString, QString> &fieldMap, QString *errorMessage)
|
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);
|
0, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,7 @@
|
|||||||
#define CUSTOMWIZARDSCRIPTGENERATOR_H
|
#define CUSTOMWIZARDSCRIPTGENERATOR_H
|
||||||
|
|
||||||
#include <QtCore/QMap>
|
#include <QtCore/QMap>
|
||||||
#include <QtCore/QList>
|
#include <QtCore/QStringList>
|
||||||
#include <QtCore/QString>
|
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class GeneratedFile;
|
class GeneratedFile;
|
||||||
@@ -41,6 +40,8 @@ class GeneratedFile;
|
|||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
struct GeneratorScriptArgument;
|
||||||
|
|
||||||
/* Custom wizard script generator functions. In addition to the <file> elements
|
/* 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
|
* 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"
|
* a custom wizard call a generation script (specified in the "generatorscript"
|
||||||
@@ -64,14 +65,21 @@ namespace Internal {
|
|||||||
* should create those, too.
|
* 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
|
// Step 1) Do a dry run of the generation script to get a list of files on stdout
|
||||||
QList<Core::GeneratedFile>
|
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,
|
const QMap<QString, QString> &fieldMap,
|
||||||
QString *errorMessage);
|
QString *errorMessage);
|
||||||
|
|
||||||
// Step 2) Generate files
|
// 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,
|
const QMap<QString, QString> &fieldMap,
|
||||||
QString *errorMessage);
|
QString *errorMessage);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user