forked from qt-creator/qt-creator
Custom wizards: Make it possible to use fields in default texts.
Pass around shared context containing basic replacement map. CustomProjectWizard adds %ProjectName% to it obtained from signal BaseProjectWizardDialog::introPageLeft(). Move replacement code into context. Add new modifier 'c' for capitalizing words.
This commit is contained in:
@@ -53,7 +53,8 @@ leave room for the Qt 4 target page.
|
|||||||
<fieldpagetitle xml:lang="de">Hallo Welt Parameter</fieldpagetitle>
|
<fieldpagetitle xml:lang="de">Hallo Welt Parameter</fieldpagetitle>
|
||||||
<fields>
|
<fields>
|
||||||
<field mandatory="true" name="MESSAGE">
|
<field mandatory="true" name="MESSAGE">
|
||||||
<fieldcontrol class="QLineEdit" validator='^[^"]+$' defaulttext="Hello world!" />
|
<fieldcontrol class="QLineEdit" validator='^[^"]+$'
|
||||||
|
defaulttext="Hello world from project '%ProjectName:c%'!" />
|
||||||
<fielddescription>Hello world message:</fielddescription>
|
<fielddescription>Hello world message:</fielddescription>
|
||||||
<fielddescription xml:lang="de">Hallo-Welt-Nachricht:</fielddescription>
|
<fielddescription xml:lang="de">Hallo-Welt-Nachricht:</fielddescription>
|
||||||
</field>
|
</field>
|
||||||
|
|||||||
@@ -41,13 +41,17 @@ namespace ProjectExplorer {
|
|||||||
struct BaseProjectWizardDialogPrivate {
|
struct BaseProjectWizardDialogPrivate {
|
||||||
explicit BaseProjectWizardDialogPrivate(Utils::ProjectIntroPage *page, int id = -1);
|
explicit BaseProjectWizardDialogPrivate(Utils::ProjectIntroPage *page, int id = -1);
|
||||||
|
|
||||||
const int introId;
|
const int desiredIntroPageId;
|
||||||
Utils::ProjectIntroPage *introPage;
|
Utils::ProjectIntroPage *introPage;
|
||||||
|
int introPageId;
|
||||||
|
int lastId;
|
||||||
};
|
};
|
||||||
|
|
||||||
BaseProjectWizardDialogPrivate::BaseProjectWizardDialogPrivate(Utils::ProjectIntroPage *page, int id) :
|
BaseProjectWizardDialogPrivate::BaseProjectWizardDialogPrivate(Utils::ProjectIntroPage *page, int id) :
|
||||||
introId(id),
|
desiredIntroPageId(id),
|
||||||
introPage(page)
|
introPage(page),
|
||||||
|
introPageId(-1),
|
||||||
|
lastId(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,8 +74,14 @@ BaseProjectWizardDialog::BaseProjectWizardDialog(Utils::ProjectIntroPage *introP
|
|||||||
void BaseProjectWizardDialog::init()
|
void BaseProjectWizardDialog::init()
|
||||||
{
|
{
|
||||||
Core::BaseFileWizard::setupWizard(this);
|
Core::BaseFileWizard::setupWizard(this);
|
||||||
addPage(d->introPage);
|
if (d->introPageId == -1) {
|
||||||
|
d->introPageId = addPage(d->introPage);
|
||||||
|
} else {
|
||||||
|
d->introPageId = d->desiredIntroPageId;
|
||||||
|
setPage(d->desiredIntroPageId, d->introPage);
|
||||||
|
}
|
||||||
connect(this, SIGNAL(accepted()), this, SLOT(slotAccepted()));
|
connect(this, SIGNAL(accepted()), this, SLOT(slotAccepted()));
|
||||||
|
connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(slotBaseCurrentIdChanged(int)));
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseProjectWizardDialog::~BaseProjectWizardDialog()
|
BaseProjectWizardDialog::~BaseProjectWizardDialog()
|
||||||
@@ -107,12 +117,21 @@ void BaseProjectWizardDialog::setProjectName(const QString &name)
|
|||||||
void BaseProjectWizardDialog::slotAccepted()
|
void BaseProjectWizardDialog::slotAccepted()
|
||||||
{
|
{
|
||||||
if (d->introPage->useAsDefaultPath()) {
|
if (d->introPage->useAsDefaultPath()) {
|
||||||
|
// Store the path as default path for new projects if desired.
|
||||||
Core::FileManager *fm = Core::ICore::instance()->fileManager();
|
Core::FileManager *fm = Core::ICore::instance()->fileManager();
|
||||||
fm->setProjectsDirectory(path());
|
fm->setProjectsDirectory(path());
|
||||||
fm->setUseProjectsDirectory(true);
|
fm->setUseProjectsDirectory(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseProjectWizardDialog::slotBaseCurrentIdChanged(int id)
|
||||||
|
{
|
||||||
|
if (d->lastId == d->introPageId) {
|
||||||
|
emit introPageLeft(d->introPage->projectName(), d->introPage->path());
|
||||||
|
}
|
||||||
|
d->lastId = id;
|
||||||
|
}
|
||||||
|
|
||||||
Utils::ProjectIntroPage *BaseProjectWizardDialog::introPage() const
|
Utils::ProjectIntroPage *BaseProjectWizardDialog::introPage() const
|
||||||
{
|
{
|
||||||
return d->introPage;
|
return d->introPage;
|
||||||
|
|||||||
@@ -71,11 +71,15 @@ public slots:
|
|||||||
void setPath(const QString &path);
|
void setPath(const QString &path);
|
||||||
void setProjectName(const QString &name);
|
void setProjectName(const QString &name);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void introPageLeft(const QString &projectName, const QString &path);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Utils::ProjectIntroPage *introPage() const;
|
Utils::ProjectIntroPage *introPage() const;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void slotAccepted();
|
void slotAccepted();
|
||||||
|
void slotBaseCurrentIdChanged(int);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
|
|||||||
@@ -35,8 +35,6 @@
|
|||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/messagemanager.h>
|
#include <coreplugin/messagemanager.h>
|
||||||
#include <coreplugin/mimedatabase.h>
|
|
||||||
#include <cpptools/cpptoolsconstants.h>
|
|
||||||
#include <extensionsystem/pluginmanager.h>
|
#include <extensionsystem/pluginmanager.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
@@ -52,7 +50,10 @@ static const char configFileC[] = "wizard.xml";
|
|||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
struct CustomWizardPrivate {
|
struct CustomWizardPrivate {
|
||||||
|
CustomWizardPrivate() : m_context(new Internal::CustomWizardContext) {}
|
||||||
|
|
||||||
QSharedPointer<Internal::CustomWizardParameters> m_parameters;
|
QSharedPointer<Internal::CustomWizardParameters> m_parameters;
|
||||||
|
QSharedPointer<Internal::CustomWizardContext> m_context;
|
||||||
static int verbose;
|
static int verbose;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -105,7 +106,9 @@ void CustomWizard::initWizardDialog(QWizard *wizard, const QString &defaultPath,
|
|||||||
const WizardPageList &extensionPages) const
|
const WizardPageList &extensionPages) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!parameters().isNull(), return);
|
QTC_ASSERT(!parameters().isNull(), return);
|
||||||
Internal::CustomWizardPage *customPage = new Internal::CustomWizardPage(parameters()->fields);
|
|
||||||
|
d->m_context->reset();
|
||||||
|
Internal::CustomWizardPage *customPage = new Internal::CustomWizardPage(d->m_context, parameters()->fields);
|
||||||
customPage->setPath(defaultPath);
|
customPage->setPath(defaultPath);
|
||||||
addWizardPage(wizard, customPage, parameters()->firstPageId);
|
addWizardPage(wizard, customPage, parameters()->firstPageId);
|
||||||
if (!parameters()->fieldPageTitle.isEmpty())
|
if (!parameters()->fieldPageTitle.isEmpty())
|
||||||
@@ -127,57 +130,6 @@ QWizard *CustomWizard::createWizardDialog(QWidget *parent,
|
|||||||
return wizard;
|
return wizard;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace field values delimited by '%' with special modifiers:
|
|
||||||
// %Field% -> simple replacement
|
|
||||||
// %Field:l% -> lower case replacement, 'u' for upper case and so on.
|
|
||||||
static void replaceFields(const CustomProjectWizard::FieldReplacementMap &fm, QString *s)
|
|
||||||
{
|
|
||||||
const QChar delimiter = QLatin1Char('%');
|
|
||||||
const QChar modifierDelimiter = QLatin1Char(':');
|
|
||||||
int pos = 0;
|
|
||||||
while (pos < s->size()) {
|
|
||||||
pos = s->indexOf(delimiter, pos);
|
|
||||||
if (pos < 0)
|
|
||||||
break;
|
|
||||||
int nextPos = s->indexOf(delimiter, pos + 1);
|
|
||||||
if (nextPos == -1)
|
|
||||||
break;
|
|
||||||
nextPos++; // Point past 2nd delimiter
|
|
||||||
if (nextPos == pos + 2) {
|
|
||||||
pos = nextPos; // Skip '%%'
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Evaluate field specification for modifiers
|
|
||||||
// "%field:l%"
|
|
||||||
QString fieldSpec = s->mid(pos + 1, nextPos - pos - 2);
|
|
||||||
const int fieldSpecSize = fieldSpec.size();
|
|
||||||
char modifier = '\0';
|
|
||||||
if (fieldSpecSize >= 3 && fieldSpec.at(fieldSpecSize - 2) == modifierDelimiter) {
|
|
||||||
modifier = fieldSpec.at(fieldSpecSize - 1).toLatin1();
|
|
||||||
fieldSpec.truncate(fieldSpecSize - 2);
|
|
||||||
}
|
|
||||||
const CustomProjectWizard::FieldReplacementMap::const_iterator it = fm.constFind(fieldSpec);
|
|
||||||
if (it == fm.constEnd()) {
|
|
||||||
pos = nextPos; // Not found, skip
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Assign
|
|
||||||
QString replacement = it.value();
|
|
||||||
switch (modifier) {
|
|
||||||
case 'l':
|
|
||||||
replacement = it.value().toLower();
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
replacement = it.value().toUpper();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
s->replace(pos, nextPos - pos, replacement);
|
|
||||||
pos += replacement.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read out files and store contents with field contents replaced.
|
// Read out files and store contents with field contents replaced.
|
||||||
static inline bool createFile(Internal::CustomWizardFile cwFile,
|
static inline bool createFile(Internal::CustomWizardFile cwFile,
|
||||||
const QString &sourceDirectory,
|
const QString &sourceDirectory,
|
||||||
@@ -188,7 +140,8 @@ static inline bool createFile(Internal::CustomWizardFile cwFile,
|
|||||||
{
|
{
|
||||||
const QChar slash = QLatin1Char('/');
|
const QChar slash = QLatin1Char('/');
|
||||||
const QString sourcePath = sourceDirectory + slash + cwFile.source;
|
const QString sourcePath = sourceDirectory + slash + cwFile.source;
|
||||||
replaceFields(fm, &cwFile.target);
|
// Field replacement on target path
|
||||||
|
Internal::CustomWizardContext::replaceFields(fm, &cwFile.target);
|
||||||
const QString targetPath = QDir::toNativeSeparators(targetDirectory + slash + cwFile.target);
|
const QString targetPath = QDir::toNativeSeparators(targetDirectory + slash + cwFile.target);
|
||||||
if (CustomWizardPrivate::verbose)
|
if (CustomWizardPrivate::verbose)
|
||||||
qDebug() << "generating " << targetPath << sourcePath << fm;
|
qDebug() << "generating " << targetPath << sourcePath << fm;
|
||||||
@@ -197,9 +150,10 @@ static inline bool createFile(Internal::CustomWizardFile cwFile,
|
|||||||
*errorMessage = QString::fromLatin1("Cannot open %1: %2").arg(sourcePath, file.errorString());
|
*errorMessage = QString::fromLatin1("Cannot open %1: %2").arg(sourcePath, file.errorString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Field replacement on contents
|
||||||
QString contents = QString::fromLocal8Bit(file.readAll());
|
QString contents = QString::fromLocal8Bit(file.readAll());
|
||||||
if (!contents.isEmpty() && !fm.isEmpty())
|
if (!contents.isEmpty() && !fm.isEmpty())
|
||||||
replaceFields(fm, &contents);
|
Internal::CustomWizardContext::replaceFields(fm, &contents);
|
||||||
Core::GeneratedFile generatedFile;
|
Core::GeneratedFile generatedFile;
|
||||||
generatedFile.setContents(contents);
|
generatedFile.setContents(contents);
|
||||||
generatedFile.setPath(targetPath);
|
generatedFile.setPath(targetPath);
|
||||||
@@ -223,9 +177,16 @@ Core::GeneratedFiles CustomWizard::generateFiles(const QWizard *dialog, QString
|
|||||||
const Internal::CustomWizardPage *cwp = findWizardPage<Internal::CustomWizardPage>(dialog);
|
const Internal::CustomWizardPage *cwp = findWizardPage<Internal::CustomWizardPage>(dialog);
|
||||||
QTC_ASSERT(cwp, return Core::GeneratedFiles())
|
QTC_ASSERT(cwp, return Core::GeneratedFiles())
|
||||||
QString path = cwp->path();
|
QString path = cwp->path();
|
||||||
const FieldReplacementMap fieldMap = defaultReplacementMap(dialog);
|
const FieldReplacementMap fieldMap = replacementMap(dialog);
|
||||||
if (CustomWizardPrivate::verbose)
|
if (CustomWizardPrivate::verbose) {
|
||||||
qDebug() << "CustomWizard::generateFiles" << dialog << path << fieldMap;
|
QString logText;
|
||||||
|
QTextStream str(&logText);
|
||||||
|
str << "CustomWizard::generateFiles: " << path << '\n';
|
||||||
|
const FieldReplacementMap::const_iterator cend = fieldMap.constEnd();
|
||||||
|
for (FieldReplacementMap::const_iterator it = fieldMap.constBegin(); it != cend; ++it)
|
||||||
|
str << " '" << it.key() << "' -> '" << it.value() << "'\n";
|
||||||
|
qWarning("%s", qPrintable(logText));
|
||||||
|
}
|
||||||
return generateWizardFiles(path, fieldMap, errorMessage);
|
return generateWizardFiles(path, fieldMap, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,20 +204,14 @@ Core::GeneratedFiles CustomWizard::generateWizardFiles(const QString &targetPath
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a default replacement map from the wizard dialog via fields
|
// Create a replacement map of static base fields + wizard dialog fields
|
||||||
// and add some useful fields.
|
CustomWizard::FieldReplacementMap CustomWizard::replacementMap(const QWizard *w) const
|
||||||
CustomWizard::FieldReplacementMap CustomWizard::defaultReplacementMap(const QWizard *w) const
|
|
||||||
{
|
{
|
||||||
FieldReplacementMap fieldReplacementMap;
|
FieldReplacementMap fieldReplacementMap = d->m_context->baseReplacements;
|
||||||
foreach(const Internal::CustomWizardField &field, d->m_parameters->fields) {
|
foreach(const Internal::CustomWizardField &field, d->m_parameters->fields) {
|
||||||
const QString value = w->field(field.name).toString();
|
const QString value = w->field(field.name).toString();
|
||||||
fieldReplacementMap.insert(field.name, value);
|
fieldReplacementMap.insert(field.name, value);
|
||||||
}
|
}
|
||||||
const Core::MimeDatabase *mdb = Core::ICore::instance()->mimeDatabase();
|
|
||||||
fieldReplacementMap.insert(QLatin1String("CppSourceSuffix"),
|
|
||||||
mdb->preferredSuffixByType(QLatin1String(CppTools::Constants::CPP_SOURCE_MIMETYPE)));
|
|
||||||
fieldReplacementMap.insert(QLatin1String("CppHeaderSuffix"),
|
|
||||||
mdb->preferredSuffixByType(QLatin1String(CppTools::Constants::CPP_HEADER_MIMETYPE)));
|
|
||||||
return fieldReplacementMap;
|
return fieldReplacementMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,6 +220,11 @@ CustomWizard::CustomWizardParametersPtr CustomWizard::parameters() const
|
|||||||
return d->m_parameters;
|
return d->m_parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CustomWizard::CustomWizardContextPtr CustomWizard::context() const
|
||||||
|
{
|
||||||
|
return d->m_context;
|
||||||
|
}
|
||||||
|
|
||||||
// Static factory map
|
// Static factory map
|
||||||
typedef QMap<QString, QSharedPointer<ICustomWizardFactory> > CustomWizardFactoryMap;
|
typedef QMap<QString, QSharedPointer<ICustomWizardFactory> > CustomWizardFactoryMap;
|
||||||
Q_GLOBAL_STATIC(CustomWizardFactoryMap, customWizardFactoryMap)
|
Q_GLOBAL_STATIC(CustomWizardFactoryMap, customWizardFactoryMap)
|
||||||
@@ -407,17 +367,25 @@ void CustomProjectWizard::initProjectWizardDialog(BaseProjectWizardDialog *w,
|
|||||||
const QString &defaultPath,
|
const QString &defaultPath,
|
||||||
const WizardPageList &extensionPages) const
|
const WizardPageList &extensionPages) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!parameters().isNull(), return);
|
const CustomWizardParametersPtr pa = parameters();
|
||||||
if (!parameters()->fields.isEmpty()) {
|
QTC_ASSERT(!pa.isNull(), return);
|
||||||
Internal::CustomWizardFieldPage *cp = new Internal::CustomWizardFieldPage(parameters()->fields);
|
|
||||||
|
const CustomWizardContextPtr ctx = context();
|
||||||
|
ctx->reset();
|
||||||
|
|
||||||
|
if (!pa->fields.isEmpty()) {
|
||||||
|
Internal::CustomWizardFieldPage *cp = new Internal::CustomWizardFieldPage(ctx, pa->fields);
|
||||||
addWizardPage(w, cp, parameters()->firstPageId);
|
addWizardPage(w, cp, parameters()->firstPageId);
|
||||||
if (!parameters()->fieldPageTitle.isEmpty())
|
if (!pa->fieldPageTitle.isEmpty())
|
||||||
cp->setTitle(parameters()->fieldPageTitle);
|
cp->setTitle(pa->fieldPageTitle);
|
||||||
}
|
}
|
||||||
foreach(QWizardPage *ep, extensionPages)
|
foreach(QWizardPage *ep, extensionPages)
|
||||||
w->addPage(ep);
|
w->addPage(ep);
|
||||||
w->setPath(defaultPath);
|
w->setPath(defaultPath);
|
||||||
w->setProjectName(BaseProjectWizardDialog::uniqueProjectName(defaultPath));
|
w->setProjectName(BaseProjectWizardDialog::uniqueProjectName(defaultPath));
|
||||||
|
|
||||||
|
connect(w, SIGNAL(introPageLeft(QString,QString)), this, SLOT(introPageLeft(QString,QString)));
|
||||||
|
|
||||||
if (CustomWizardPrivate::verbose)
|
if (CustomWizardPrivate::verbose)
|
||||||
qDebug() << "initProjectWizardDialog" << w << w->pageIds();
|
qDebug() << "initProjectWizardDialog" << w << w->pageIds();
|
||||||
}
|
}
|
||||||
@@ -428,7 +396,7 @@ Core::GeneratedFiles CustomProjectWizard::generateFiles(const QWizard *w, QStrin
|
|||||||
QTC_ASSERT(dialog, return Core::GeneratedFiles())
|
QTC_ASSERT(dialog, return Core::GeneratedFiles())
|
||||||
const QString targetPath = dialog->path() + QLatin1Char('/') + dialog->projectName();
|
const QString targetPath = dialog->path() + QLatin1Char('/') + dialog->projectName();
|
||||||
// Add project name as macro.
|
// Add project name as macro.
|
||||||
FieldReplacementMap fieldReplacementMap = defaultReplacementMap(dialog);
|
FieldReplacementMap fieldReplacementMap = replacementMap(dialog);
|
||||||
fieldReplacementMap.insert(QLatin1String("ProjectName"), dialog->projectName());
|
fieldReplacementMap.insert(QLatin1String("ProjectName"), dialog->projectName());
|
||||||
if (CustomWizardPrivate::verbose)
|
if (CustomWizardPrivate::verbose)
|
||||||
qDebug() << "CustomProjectWizard::generateFiles" << dialog << targetPath << fieldReplacementMap;
|
qDebug() << "CustomProjectWizard::generateFiles" << dialog << targetPath << fieldReplacementMap;
|
||||||
@@ -449,4 +417,10 @@ bool CustomProjectWizard::postGenerateFiles(const QWizard *, const Core::Generat
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CustomProjectWizard::introPageLeft(const QString &project, const QString & /* path */)
|
||||||
|
{
|
||||||
|
// Make '%ProjectName%' available in base replacements.
|
||||||
|
context()->baseReplacements.insert(QLatin1String("ProjectName"), project);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ class BaseProjectWizardDialog;
|
|||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
struct CustomWizardParameters;
|
struct CustomWizardParameters;
|
||||||
|
struct CustomWizardContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Factory for creating wizard. Can be registered under a name
|
// Factory for creating wizard. Can be registered under a name
|
||||||
@@ -105,6 +106,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef QSharedPointer<Internal::CustomWizardParameters> CustomWizardParametersPtr;
|
typedef QSharedPointer<Internal::CustomWizardParameters> CustomWizardParametersPtr;
|
||||||
|
typedef QSharedPointer<Internal::CustomWizardContext> CustomWizardContextPtr;
|
||||||
|
|
||||||
void initWizardDialog(QWizard *w, const QString &defaultPath,
|
void initWizardDialog(QWizard *w, const QString &defaultPath,
|
||||||
const WizardPageList &extensionPages) const;
|
const WizardPageList &extensionPages) const;
|
||||||
@@ -113,10 +115,11 @@ protected:
|
|||||||
Core::GeneratedFiles generateWizardFiles(const QString &path,
|
Core::GeneratedFiles generateWizardFiles(const QString &path,
|
||||||
const FieldReplacementMap &defaultFields,
|
const FieldReplacementMap &defaultFields,
|
||||||
QString *errorMessage) const;
|
QString *errorMessage) const;
|
||||||
// Create replacement map from QWizard fields with additional useful fields.
|
// Create replacement map as static base fields + QWizard fields
|
||||||
FieldReplacementMap defaultReplacementMap(const QWizard *w) const;
|
FieldReplacementMap replacementMap(const QWizard *w) const;
|
||||||
|
|
||||||
CustomWizardParametersPtr parameters() const;
|
CustomWizardParametersPtr parameters() const;
|
||||||
|
CustomWizardContextPtr context() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setParameters(const CustomWizardParametersPtr &p);
|
void setParameters(const CustomWizardParametersPtr &p);
|
||||||
@@ -128,7 +131,9 @@ private:
|
|||||||
// A custom project wizard presenting CustomProjectWizardDialog
|
// A custom project wizard presenting CustomProjectWizardDialog
|
||||||
// (Project intro page and fields page) for wizards of type "project".
|
// (Project intro page and fields page) for wizards of type "project".
|
||||||
// Overwrites postGenerateFiles() to open the project file which is the
|
// Overwrites postGenerateFiles() to open the project file which is the
|
||||||
// last one by convention.
|
// last one by convention. Also inserts '%ProjectName%' into the base
|
||||||
|
// replacement map once the intro page is left to have it available
|
||||||
|
// for QLineEdit-type fields' default text.
|
||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT CustomProjectWizard : public CustomWizard
|
class PROJECTEXPLORER_EXPORT CustomProjectWizard : public CustomWizard
|
||||||
{
|
{
|
||||||
@@ -150,6 +155,9 @@ protected:
|
|||||||
|
|
||||||
void initProjectWizardDialog(BaseProjectWizardDialog *w, const QString &defaultPath,
|
void initProjectWizardDialog(BaseProjectWizardDialog *w, const QString &defaultPath,
|
||||||
const WizardPageList &extensionPages) const;
|
const WizardPageList &extensionPages) const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void introPageLeft(const QString &project, const QString &path);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
|||||||
@@ -63,9 +63,17 @@ void TextFieldComboBox::setText(const QString &s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --------------- CustomWizardFieldPage
|
// --------------- CustomWizardFieldPage
|
||||||
CustomWizardFieldPage::CustomWizardFieldPage(const FieldList &fields,
|
|
||||||
|
CustomWizardFieldPage::LineEditData::LineEditData(QLineEdit* le, const QString &defText) :
|
||||||
|
lineEdit(le), defaultText(defText)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomWizardFieldPage::CustomWizardFieldPage(const QSharedPointer<CustomWizardContext> &ctx,
|
||||||
|
const FieldList &fields,
|
||||||
QWidget *parent) :
|
QWidget *parent) :
|
||||||
QWizardPage(parent),
|
QWizardPage(parent),
|
||||||
|
m_context(ctx),
|
||||||
m_formLayout(new QFormLayout)
|
m_formLayout(new QFormLayout)
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
@@ -75,6 +83,10 @@ CustomWizardFieldPage::CustomWizardFieldPage(const FieldList &fields,
|
|||||||
setLayout(m_formLayout);
|
setLayout(m_formLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CustomWizardFieldPage::~CustomWizardFieldPage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void CustomWizardFieldPage::addRow(const QString &name, QWidget *w)
|
void CustomWizardFieldPage::addRow(const QString &name, QWidget *w)
|
||||||
{
|
{
|
||||||
m_formLayout->addRow(name, w);
|
m_formLayout->addRow(name, w);
|
||||||
@@ -82,18 +94,28 @@ void CustomWizardFieldPage::addRow(const QString &name, QWidget *w)
|
|||||||
|
|
||||||
// Create widget a control based on the control attributes map
|
// Create widget a control based on the control attributes map
|
||||||
// and register it with the QWizard.
|
// and register it with the QWizard.
|
||||||
QWidget *CustomWizardFieldPage::registerControl(const CustomWizardField &field)
|
void CustomWizardFieldPage::addField(const CustomWizardField &field)\
|
||||||
{
|
{
|
||||||
// Register field, Indicate mandatory by '*' (only when registering)
|
// Register field, indicate mandatory by '*' (only when registering)
|
||||||
QString fieldName = field.name;
|
QString fieldName = field.name;
|
||||||
if (field.mandatory)
|
if (field.mandatory)
|
||||||
fieldName += QLatin1Char('*');
|
fieldName += QLatin1Char('*');
|
||||||
// Check known classes: QComboBox
|
// Check known classes: QComboBox
|
||||||
const QString className = field.controlAttributes.value(QLatin1String("class"));
|
const QString className = field.controlAttributes.value(QLatin1String("class"));
|
||||||
|
QWidget *fieldWidget = 0;
|
||||||
if (className == QLatin1String("QComboBox")) {
|
if (className == QLatin1String("QComboBox")) {
|
||||||
|
fieldWidget = registerComboBox(fieldName, field);
|
||||||
|
} else {
|
||||||
|
fieldWidget = registerLineEdit(fieldName, field);
|
||||||
|
}
|
||||||
|
addRow(field.description, fieldWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *CustomWizardFieldPage::registerComboBox(const QString &fieldName,
|
||||||
|
const CustomWizardField &field)
|
||||||
|
{
|
||||||
TextFieldComboBox *combo = new TextFieldComboBox;
|
TextFieldComboBox *combo = new TextFieldComboBox;
|
||||||
// Set up items
|
do { // Set up items and current index
|
||||||
do {
|
|
||||||
const QString choices = field.controlAttributes.value(QLatin1String("combochoices"));
|
const QString choices = field.controlAttributes.value(QLatin1String("combochoices"));
|
||||||
if (choices.isEmpty())
|
if (choices.isEmpty())
|
||||||
break;
|
break;
|
||||||
@@ -109,9 +131,13 @@ QWidget *CustomWizardFieldPage::registerControl(const CustomWizardField &field)
|
|||||||
} while (false);
|
} while (false);
|
||||||
registerField(fieldName, combo, "text", SIGNAL(text4Changed(QString)));
|
registerField(fieldName, combo, "text", SIGNAL(text4Changed(QString)));
|
||||||
return combo;
|
return combo;
|
||||||
} // QComboBox
|
} // QComboBox
|
||||||
// Default to QLineEdit
|
|
||||||
|
QWidget *CustomWizardFieldPage::registerLineEdit(const QString &fieldName,
|
||||||
|
const CustomWizardField &field)
|
||||||
|
{
|
||||||
QLineEdit *lineEdit = new QLineEdit;
|
QLineEdit *lineEdit = new QLineEdit;
|
||||||
|
|
||||||
const QString validationRegExp = field.controlAttributes.value(QLatin1String("validator"));
|
const QString validationRegExp = field.controlAttributes.value(QLatin1String("validator"));
|
||||||
if (!validationRegExp.isEmpty()) {
|
if (!validationRegExp.isEmpty()) {
|
||||||
QRegExp re(validationRegExp);
|
QRegExp re(validationRegExp);
|
||||||
@@ -120,39 +146,51 @@ QWidget *CustomWizardFieldPage::registerControl(const CustomWizardField &field)
|
|||||||
} else {
|
} else {
|
||||||
qWarning("Invalid custom wizard field validator regular expression %s.", qPrintable(validationRegExp));
|
qWarning("Invalid custom wizard field validator regular expression %s.", qPrintable(validationRegExp));
|
||||||
}
|
}
|
||||||
m_validatorLineEdits.push_back(lineEdit);
|
|
||||||
}
|
}
|
||||||
lineEdit->setText(field.controlAttributes.value(QLatin1String("defaulttext")));
|
|
||||||
registerField(fieldName, lineEdit, "text", SIGNAL(textEdited(QString)));
|
registerField(fieldName, lineEdit, "text", SIGNAL(textEdited(QString)));
|
||||||
|
|
||||||
|
const QString defaultText = field.controlAttributes.value(QLatin1String("defaulttext"));
|
||||||
|
m_lineEdits.push_back(LineEditData(lineEdit, defaultText));
|
||||||
return lineEdit;
|
return lineEdit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomWizardFieldPage::addField(const CustomWizardField &field)
|
void CustomWizardFieldPage::initializePage()
|
||||||
{
|
{
|
||||||
addRow(field.description, registerControl(field));
|
QWizardPage::initializePage();
|
||||||
|
// Note that the field mechanism will always restore the value
|
||||||
|
// set on it when entering the page, so, there is no point in
|
||||||
|
// trying to preserve user modifications of the text.
|
||||||
|
foreach(const LineEditData &led, m_lineEdits) {
|
||||||
|
if (!led.defaultText.isEmpty()) {
|
||||||
|
QString defaultText = led.defaultText;
|
||||||
|
CustomWizardContext::replaceFields(m_context->baseReplacements, &defaultText);
|
||||||
|
led.lineEdit->setText(defaultText);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CustomWizardFieldPage::validatePage()
|
bool CustomWizardFieldPage::validatePage()
|
||||||
{
|
{
|
||||||
// Check line edits with validators
|
// Check line edits with validators
|
||||||
foreach(QLineEdit *le, m_validatorLineEdits) {
|
foreach(const LineEditData &led, m_lineEdits) {
|
||||||
|
if (const QValidator *val = led.lineEdit->validator()) {
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
const QValidator *val = le->validator();
|
QString text = led.lineEdit->text();
|
||||||
QTC_ASSERT(val, return false);
|
|
||||||
QString text = le->text();
|
|
||||||
if (val->validate(text, pos) != QValidator::Acceptable) {
|
if (val->validate(text, pos) != QValidator::Acceptable) {
|
||||||
le->setFocus();
|
led.lineEdit->setFocus();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return QWizardPage::validatePage();
|
return QWizardPage::validatePage();
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------- CustomWizardPage
|
// --------------- CustomWizardPage
|
||||||
|
|
||||||
CustomWizardPage::CustomWizardPage(const FieldList &f,
|
CustomWizardPage::CustomWizardPage(const QSharedPointer<CustomWizardContext> &ctx,
|
||||||
|
const FieldList &f,
|
||||||
QWidget *parent) :
|
QWidget *parent) :
|
||||||
CustomWizardFieldPage(f, parent),
|
CustomWizardFieldPage(ctx, f, parent),
|
||||||
m_pathChooser(new Utils::PathChooser)
|
m_pathChooser(new Utils::PathChooser)
|
||||||
{
|
{
|
||||||
addRow(tr("Path:"), m_pathChooser);
|
addRow(tr("Path:"), m_pathChooser);
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ namespace Internal {
|
|||||||
|
|
||||||
struct CustomWizardField;
|
struct CustomWizardField;
|
||||||
struct CustomWizardParameters;
|
struct CustomWizardParameters;
|
||||||
|
struct CustomWizardContext;
|
||||||
|
|
||||||
// A non-editable combo for text editing purposes that plays
|
// A non-editable combo for text editing purposes that plays
|
||||||
// with QWizard::registerField (providing a settable text property).
|
// with QWizard::registerField (providing a settable text property).
|
||||||
@@ -74,19 +75,33 @@ class CustomWizardFieldPage : public QWizardPage {
|
|||||||
public:
|
public:
|
||||||
typedef QList<CustomWizardField> FieldList;
|
typedef QList<CustomWizardField> FieldList;
|
||||||
|
|
||||||
explicit CustomWizardFieldPage(const FieldList &f,
|
explicit CustomWizardFieldPage(const QSharedPointer<CustomWizardContext> &ctx,
|
||||||
|
const FieldList &f,
|
||||||
QWidget *parent = 0);
|
QWidget *parent = 0);
|
||||||
|
virtual ~CustomWizardFieldPage();
|
||||||
|
|
||||||
virtual bool validatePage();
|
virtual bool validatePage();
|
||||||
|
virtual void initializePage();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
inline void addRow(const QString &name, QWidget *w);
|
inline void addRow(const QString &name, QWidget *w);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWidget *registerControl(const CustomWizardField &f);
|
struct LineEditData {
|
||||||
|
explicit LineEditData(QLineEdit* le = 0, const QString &defText = QString());
|
||||||
|
QLineEdit* lineEdit;
|
||||||
|
QString defaultText;
|
||||||
|
};
|
||||||
|
typedef QList<LineEditData> LineEditDataList;
|
||||||
|
|
||||||
|
QWidget *registerLineEdit(const QString &fieldName, const CustomWizardField &field);
|
||||||
|
QWidget *registerComboBox(const QString &fieldName, const CustomWizardField &field);
|
||||||
|
|
||||||
void addField(const CustomWizardField &f);
|
void addField(const CustomWizardField &f);
|
||||||
|
|
||||||
|
const QSharedPointer<CustomWizardContext> m_context;
|
||||||
QFormLayout *m_formLayout;
|
QFormLayout *m_formLayout;
|
||||||
QList<QLineEdit*> m_validatorLineEdits;
|
LineEditDataList m_lineEdits;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A custom wizard page presenting the fields to be used and a path chooser
|
// A custom wizard page presenting the fields to be used and a path chooser
|
||||||
@@ -96,7 +111,8 @@ private:
|
|||||||
class CustomWizardPage : public CustomWizardFieldPage {
|
class CustomWizardPage : public CustomWizardFieldPage {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit CustomWizardPage(const FieldList &f,
|
explicit CustomWizardPage(const QSharedPointer<CustomWizardContext> &ctx,
|
||||||
|
const FieldList &f,
|
||||||
QWidget *parent = 0);
|
QWidget *parent = 0);
|
||||||
|
|
||||||
QString path() const;
|
QString path() const;
|
||||||
|
|||||||
@@ -29,6 +29,10 @@
|
|||||||
|
|
||||||
#include "customwizardparameters.h"
|
#include "customwizardparameters.h"
|
||||||
|
|
||||||
|
#include <coreplugin/mimedatabase.h>
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <cpptools/cpptoolsconstants.h>
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QLocale>
|
#include <QtCore/QLocale>
|
||||||
#include <QtCore/QFile>
|
#include <QtCore/QFile>
|
||||||
@@ -467,5 +471,75 @@ QString CustomWizardParameters::toString() const
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------ CustomWizardContext
|
||||||
|
|
||||||
|
void CustomWizardContext::replaceFields(const FieldReplacementMap &fm, QString *s)
|
||||||
|
{
|
||||||
|
if (debug) {
|
||||||
|
qDebug().nospace() << "CustomWizardContext::replaceFields with " <<
|
||||||
|
fm << *s;
|
||||||
|
}
|
||||||
|
const QChar delimiter = QLatin1Char('%');
|
||||||
|
const QChar modifierDelimiter = QLatin1Char(':');
|
||||||
|
int pos = 0;
|
||||||
|
while (pos < s->size()) {
|
||||||
|
pos = s->indexOf(delimiter, pos);
|
||||||
|
if (pos < 0)
|
||||||
|
break;
|
||||||
|
int nextPos = s->indexOf(delimiter, pos + 1);
|
||||||
|
if (nextPos == -1)
|
||||||
|
break;
|
||||||
|
nextPos++; // Point past 2nd delimiter
|
||||||
|
if (nextPos == pos + 2) {
|
||||||
|
pos = nextPos; // Skip '%%'
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Evaluate field specification for modifiers
|
||||||
|
// "%field:l%"
|
||||||
|
QString fieldSpec = s->mid(pos + 1, nextPos - pos - 2);
|
||||||
|
const int fieldSpecSize = fieldSpec.size();
|
||||||
|
char modifier = '\0';
|
||||||
|
if (fieldSpecSize >= 3 && fieldSpec.at(fieldSpecSize - 2) == modifierDelimiter) {
|
||||||
|
modifier = fieldSpec.at(fieldSpecSize - 1).toLatin1();
|
||||||
|
fieldSpec.truncate(fieldSpecSize - 2);
|
||||||
|
}
|
||||||
|
const FieldReplacementMap::const_iterator it = fm.constFind(fieldSpec);
|
||||||
|
if (it == fm.constEnd()) {
|
||||||
|
pos = nextPos; // Not found, skip
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Assign
|
||||||
|
QString replacement = it.value();
|
||||||
|
switch (modifier) {
|
||||||
|
case 'l':
|
||||||
|
replacement = it.value().toLower();
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
replacement = it.value().toUpper();
|
||||||
|
break;
|
||||||
|
case 'c': // Capitalize first letter
|
||||||
|
replacement = it.value();
|
||||||
|
if (!replacement.isEmpty())
|
||||||
|
replacement[0] = replacement.at(0).toUpper();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s->replace(pos, nextPos - pos, replacement);
|
||||||
|
pos += replacement.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CustomWizardContext::reset()
|
||||||
|
{
|
||||||
|
// Basic replacement fields: Suffixes.
|
||||||
|
baseReplacements.clear();
|
||||||
|
const Core::MimeDatabase *mdb = Core::ICore::instance()->mimeDatabase();
|
||||||
|
baseReplacements.insert(QLatin1String("CppSourceSuffix"),
|
||||||
|
mdb->preferredSuffixByType(QLatin1String(CppTools::Constants::CPP_SOURCE_MIMETYPE)));
|
||||||
|
baseReplacements.insert(QLatin1String("CppHeaderSuffix"),
|
||||||
|
mdb->preferredSuffixByType(QLatin1String(CppTools::Constants::CPP_HEADER_MIMETYPE)));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
|||||||
@@ -79,6 +79,28 @@ public:
|
|||||||
int firstPageId;
|
int firstPageId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Context used for one wizard run, shared between CustomWizard
|
||||||
|
// and the CustomWizardPage as it is used for the QLineEdit-type fields'
|
||||||
|
// default texts as well. Contains basic replacement fields
|
||||||
|
// like '%CppSourceSuffix%', '%CppHeaderSuffix%' (settings-dependent)
|
||||||
|
// reset() should be called before each wizard run to refresh them.
|
||||||
|
// CustomProjectWizard additionally inserts '%ProjectName%' from
|
||||||
|
// the intro page to have it available for default texts.
|
||||||
|
|
||||||
|
struct CustomWizardContext {
|
||||||
|
typedef QMap<QString, QString> FieldReplacementMap;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
FieldReplacementMap baseReplacements;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user