Add JsonWizard

This is a generalization of the customwizard (using Json for its
configuration files since that is so easy to handle in Qt 5 and
since it is incompatible with the customwizard anyway).

It allows to define an arbitrary number of pages and generators to
generate the actual files.

Change-Id: I45a01cf7fb906701b627fa1471a898cad472f679
Reviewed-by: Daniel Teske <daniel.teske@digia.com>
This commit is contained in:
Tobias Hunger
2014-08-27 14:16:06 +02:00
parent e90a8a051c
commit 3491b1f22a
15 changed files with 1551 additions and 0 deletions

View File

@@ -0,0 +1,176 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "jsonwizard.h"
#include "jsonwizardexpander.h"
#include "jsonwizardgeneratorfactory.h"
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <QFileInfo>
#include <QMessageBox>
#include <QVariant>
namespace ProjectExplorer {
JsonWizard::JsonWizard(QWidget *parent) :
Utils::Wizard(parent),
m_expander(new Internal::JsonWizardExpander(this))
{ }
JsonWizard::~JsonWizard()
{
qDeleteAll(m_generators);
delete m_expander;
}
void JsonWizard::addGenerator(JsonWizardGenerator *gen)
{
QTC_ASSERT(gen, return);
QTC_ASSERT(!m_generators.contains(gen), return);
m_generators.append(gen);
}
Utils::AbstractMacroExpander *JsonWizard::expander() const
{
return m_expander;
}
JsonWizard::GeneratorFiles JsonWizard::fileList()
{
QString errorMessage;
GeneratorFiles list;
QString targetPath = value(QLatin1String("TargetPath")).toString();
if (targetPath.isEmpty()) {
errorMessage = tr("Could not determine target path. \"TargetPath\", \"Path\", or "
"\"ProjectName\" were not set on any page.");
return list;
}
if (m_files.isEmpty()) {
emit preGenerateFiles();
foreach (JsonWizardGenerator *gen, m_generators) {
Core::GeneratedFiles tmp = gen->fileList(m_expander, value(QStringLiteral("WizardDir")).toString(),
targetPath, &errorMessage);
if (!errorMessage.isEmpty())
break;
list.append(Utils::transform(tmp, [&gen](const Core::GeneratedFile &f)
{ return GeneratorFile(f, gen); }));
}
if (errorMessage.isEmpty())
m_files = list;
emit postGenerateFiles(m_files);
}
if (!errorMessage.isEmpty()) {
QMessageBox::critical(this, tr("File Generation Failed"),
tr("The wizard failed to generate files.<br>"
"The error message was: \"%1\".").arg(errorMessage));
reject();
return GeneratorFiles();
}
return m_files;
}
QVariant JsonWizard::value(const QString &n) const
{
QVariant v = property(n.toUtf8());
if (v.isValid()) {
if (v.type() == QVariant::String)
return Utils::expandMacros(v.toString(), m_expander);
else
return v;
}
if (hasField(n))
return field(n); // Can not contain macros!
return QVariant();
}
void JsonWizard::setValue(const QString &key, const QVariant &value)
{
setProperty(key.toUtf8(), value);
}
bool JsonWizard::boolFromVariant(const QVariant &v, Utils::AbstractMacroExpander *expander)
{
if (v.type() == QVariant::String)
return !Utils::expandMacros(v.toString(), expander).isEmpty();
return v.toBool();
}
void JsonWizard::accept()
{
Utils::Wizard::accept();
QString errorMessage;
GeneratorFiles list = fileList();
if (list.isEmpty())
return;
emit prePromptForOverwrite(m_files);
JsonWizardGenerator::OverwriteResult overwrite =
JsonWizardGenerator::promptForOverwrite(&list, &errorMessage);
if (overwrite == JsonWizardGenerator::OverwriteError) {
if (!errorMessage.isEmpty())
QMessageBox::warning(this, tr("Failed to Overwrite Files"), errorMessage);
return;
}
emit preFormatFiles(m_files);
if (!JsonWizardGenerator::formatFiles(this, &list, &errorMessage)) {
if (!errorMessage.isEmpty())
QMessageBox::warning(this, tr("Failed to Format Files"), errorMessage);
return;
}
emit preWriteFiles(m_files);
if (!JsonWizardGenerator::writeFiles(this, &list, &errorMessage)) {
if (!errorMessage.isEmpty())
QMessageBox::warning(this, tr("Failed to Write Files"), errorMessage);
return;
}
emit postProcessFiles(m_files);
if (!JsonWizardGenerator::postWrite(this, &list, &errorMessage)) {
if (!errorMessage.isEmpty())
QMessageBox::warning(this, tr("Failed to Post-Process Files"), errorMessage);
return;
}
emit filesReady(m_files);
}
} // namespace ProjectExplorer

View File

@@ -0,0 +1,103 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef JSONWIZARD_H
#define JSONWIZARD_H
#include "../projectexplorer_export.h"
#include <coreplugin/generatedfile.h>
#include <utils/wizard.h>
namespace Utils { class AbstractMacroExpander; }
namespace ProjectExplorer {
namespace Internal { class JsonWizardExpander; }
class JsonWizardGenerator;
// Documentation inside.
class PROJECTEXPLORER_EXPORT JsonWizard : public Utils::Wizard
{
Q_OBJECT
public:
class GeneratorFile {
public:
GeneratorFile() : generator(0) { }
GeneratorFile(const Core::GeneratedFile &f, JsonWizardGenerator *g) :
file(f), generator(g)
{ }
bool isValid() const { return generator; }
Core::GeneratedFile file;
JsonWizardGenerator *generator;
};
typedef QList<GeneratorFile> GeneratorFiles;
Q_PROPERTY(GeneratorFiles fileList READ fileList)
explicit JsonWizard(QWidget *parent = 0);
~JsonWizard();
void addGenerator(JsonWizardGenerator *gen);
Utils::AbstractMacroExpander *expander() const;
GeneratorFiles fileList();
QVariant value(const QString &n) const;
void setValue(const QString &key, const QVariant &value);
static bool boolFromVariant(const QVariant &v, Utils::AbstractMacroExpander *expander);
signals:
void preGenerateFiles(); // emitted before files are generated.
void postGenerateFiles(const JsonWizard::GeneratorFiles &files); // emitted after files are generated.
void prePromptForOverwrite(const JsonWizard::GeneratorFiles &files); // emitted before overwriting checks are done.
void preFormatFiles(const JsonWizard::GeneratorFiles &files); // emitted before files are formatted.
void preWriteFiles(const JsonWizard::GeneratorFiles &files); // emitted before files are written to disk.
void postProcessFiles(const JsonWizard::GeneratorFiles &files); // emitted before files are post-processed.
void filesReady(const JsonWizard::GeneratorFiles &files); // emitted just after files are in final state on disk.
public slots:
void accept();
private:
QList<JsonWizardGenerator *> m_generators;
GeneratorFiles m_files;
Internal::JsonWizardExpander *m_expander;
};
} // namespace ProjectExplorer
#endif // JSONWIZARD_H

View File

@@ -0,0 +1,11 @@
HEADERS += $$PWD/jsonwizard.h \
$$PWD/jsonwizardexpander.h \
$$PWD/jsonwizardfactory.h \
$$PWD/jsonwizardgeneratorfactory.h \
$$PWD/jsonwizardpagefactory.h
SOURCES += $$PWD/jsonwizard.cpp \
$$PWD/jsonwizardexpander.cpp \
$$PWD/jsonwizardfactory.cpp \
$$PWD/jsonwizardgeneratorfactory.cpp \
$$PWD/jsonwizardpagefactory.cpp

View File

@@ -0,0 +1,65 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "jsonwizardexpander.h"
#include "jsonwizard.h"
#include <coreplugin/variablemanager.h>
#include <utils/qtcassert.h>
#include <QVariant>
namespace ProjectExplorer {
namespace Internal {
// --------------------------------------------------------------------
// JsonWizardExpander:
// --------------------------------------------------------------------
JsonWizardExpander::JsonWizardExpander(JsonWizard *wizard) :
m_wizard(wizard)
{
QTC_CHECK(m_wizard);
}
bool JsonWizardExpander::resolveMacro(const QString &name, QString *ret)
{
QVariant v = m_wizard->value(name);
if (v.isValid()) {
*ret = v.toString();
return true;
}
return Core::VariableManager::macroExpander()->resolveMacro(name, ret);
}
} // namespace Internal
} // namespace ProjectExplorer

View File

@@ -0,0 +1,58 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef JSONWIZARDEXPANDER_H
#define JSONWIZARDEXPANDER_H
#include <utils/stringutils.h>
#include <QString>
namespace ProjectExplorer {
class JsonWizard;
namespace Internal {
// Documentation inside.
class JsonWizardExpander : public Utils::AbstractMacroExpander
{
public:
explicit JsonWizardExpander(JsonWizard *wizard);
bool resolveMacro(const QString &name, QString *ret);
public:
JsonWizard *m_wizard;
};
} // namespace Internal
} // namespace ProjectExplorer
#endif // JSONWIZARDEXPANDER_H

View File

@@ -0,0 +1,604 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "jsonwizardfactory.h"
#include "jsonwizard.h"
#include "jsonwizardgeneratorfactory.h"
#include "jsonwizardpagefactory.h"
#include "../projectexplorerconstants.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
#include <utils/wizard.h>
#include <utils/wizardpage.h>
#include <QDebug>
#include <QDir>
#include <QMap>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
namespace ProjectExplorer {
static QList<JsonWizardPageFactory *> s_pageFactories;
static QList<JsonWizardGeneratorFactory *> s_generatorFactories;
static const char WIZARD_PATH[] = "templates/wizards";
static const char WIZARD_FILE[] = "wizard.json";
static const char VERSION_KEY[] = "version";
static const char DISABLED_KEY[] = "disabled";
static const char KIND_KEY[] = "kind";
static const char ID_KEY[] = "id";
static const char CATEGORY_KEY[] = "category";
static const char CATEGORY_NAME_KEY[] = "trDisplayCategory";
static const char DISPLAY_NAME_KEY[] = "trDisplayName";
static const char ICON_KEY[] = "icon";
static const char DESCRIPTION_KEY[] = "trDescription";
static const char REQUIRED_FEATURES_KEY[] = "featuresRequired";
static const char SUGGESTED_FEATURES_KEY[] = "featuresSuggested";
static const char GENERATOR_KEY[] = "generators";
static const char PAGES_KEY[] = "pages";
static const char TYPE_ID_KEY[] = "typeId";
static const char DATA_KEY[] = "data";
static const char PAGE_SUB_TITLE_KEY[] = "trSubTitle";
static const char PAGE_SHORT_TITLE_KEY[] = "trShortTitle";
static const char PAGE_INDEX_KEY[] = "index";
static const char OPTIONS_KEY[] = "options";
static const char PLATFORM_INDEPENDENT_KEY[] = "platformIndependent";
QList<Utils::FileName> JsonWizardFactory::m_searchPaths
= QList<Utils::FileName>()
<< Utils::FileName::fromString(Core::ICore::userResourcePath() + QLatin1Char('/') + QLatin1String(WIZARD_PATH))
<< Utils::FileName::fromString(Core::ICore::resourcePath() + QLatin1Char('/') + QLatin1String(WIZARD_PATH));
int JsonWizardFactory::m_verbose = 0;
// Return locale language attribute "de_UTF8" -> "de", empty string for "C"
static QString languageSetting()
{
QString name = Core::ICore::userInterfaceLanguage();
const int underScorePos = name.indexOf(QLatin1Char('_'));
if (underScorePos != -1)
name.truncate(underScorePos);
if (name.compare(QLatin1String("C"), Qt::CaseInsensitive) == 0)
name.clear();
return name;
}
template<class T>
static QString supportedTypeIds(const QList<T *> &factories)
{
QStringList tmp;
foreach (const T*f, factories) {
foreach (Core::Id i, f->supportedIds())
tmp.append(i.toString());
}
return tmp.join(QLatin1String("', '"));
}
static JsonWizardFactory::Generator parseGenerator(const QVariant &value, QString *errorMessage)
{
JsonWizardFactory::Generator gen;
if (value.type() != QVariant::Map) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonWizardFactory", "Generator is not a object.");
return gen;
}
QVariantMap data = value.toMap();
QString strVal = data.value(QLatin1String(TYPE_ID_KEY)).toString();
if (strVal.isEmpty()) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonWizardFactory", "Generator has no typeId set.");
return gen;
}
Core::Id typeId = Core::Id::fromString(QLatin1String(Constants::GENERATOR_ID_PREFIX) + strVal);
JsonWizardGeneratorFactory *factory
= Utils::findOr(s_generatorFactories, 0, [typeId](JsonWizardGeneratorFactory *f) { return f->canCreate(typeId); });
if (!factory) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonWizardFactory",
"TypeId \"%1\" of generator is unknown. Supported typeIds are: \"%2\".")
.arg(strVal)
.arg(supportedTypeIds(s_generatorFactories).replace(QLatin1String(Constants::GENERATOR_ID_PREFIX), QLatin1String("")));
return gen;
}
QVariant varVal = data.value(QLatin1String(DATA_KEY));
if (!factory->validateData(typeId, varVal, errorMessage))
return gen;
gen.typeId = typeId;
gen.data = varVal;
return gen;
}
static JsonWizardFactory::Page parsePage(const QVariant &value, QString *errorMessage)
{
JsonWizardFactory::Page p;
if (value.type() != QVariant::Map) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonWizardFactory", "Page is not a object.");
return p;
}
QVariantMap data = value.toMap();
QString strVal = data.value(QLatin1String(TYPE_ID_KEY)).toString();
if (strVal.isEmpty()) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonWizardFactory", "Page has no typeId set.");
return p;
}
Core::Id typeId = Core::Id::fromString(QLatin1String(Constants::PAGE_ID_PREFIX) + strVal);
JsonWizardPageFactory *factory
= Utils::findOr(s_pageFactories, 0, [typeId](JsonWizardPageFactory *f) { return f->canCreate(typeId); });
if (!factory) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonWizardFactory",
"TypeId \"%1\" of page is unknown. Supported typeIds are: \"%2\".")
.arg(strVal)
.arg(supportedTypeIds(s_pageFactories).replace(QLatin1String(Constants::PAGE_ID_PREFIX), QLatin1String("")));
return p;
}
QString title = JsonWizardFactory::localizedString(data.value(QLatin1String(DISPLAY_NAME_KEY)));
QString subTitle = JsonWizardFactory::localizedString(data.value(QLatin1String(PAGE_SUB_TITLE_KEY)));
QString shortTitle = JsonWizardFactory::localizedString(data.value(QLatin1String(PAGE_SHORT_TITLE_KEY)));
bool ok;
int index = data.value(QLatin1String(PAGE_INDEX_KEY), -1).toInt(&ok);
if (!ok) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonWizardFactory", "Page with typeId \"%1\" has invalid index.")
.arg(typeId.toString());
return p;
}
QVariant varVal = data.value(QLatin1String(DATA_KEY));
if (!factory->validateData(typeId, varVal, errorMessage))
return p;
p.typeId = typeId;
p.title = title;
p.subTitle = subTitle;
p.shortTitle = shortTitle;
p.index = index;
p.data = varVal;
return p;
}
QList<JsonWizardFactory *> JsonWizardFactory::createWizardFactories()
{
QString errorMessage;
QString verboseLog;
const QString wizardFileName = QLatin1String(WIZARD_FILE);
QList <JsonWizardFactory *> result;
foreach (const Utils::FileName &path, m_searchPaths) {
if (path.isEmpty())
continue;
QDir dir(path.toString());
if (!dir.exists()) {
if (verbose())
verboseLog.append(tr("Path \"%1\" does not exist when checking Json wizard search paths.\n")
.arg(path.toUserOutput()));
continue;
}
const QDir::Filters filters = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
const QDir::SortFlags sortflags = QDir::Name|QDir::IgnoreCase;
QList<QFileInfo> dirs = dir.entryInfoList(filters, sortflags);
while (!dirs.isEmpty()) {
const QFileInfo dirFi = dirs.takeFirst();
const QDir current(dirFi.absoluteFilePath());
if (verbose())
verboseLog.append(tr("Checking \"%1\" for %2.\n")
.arg(QDir::toNativeSeparators(current.absolutePath()))
.arg(wizardFileName));
if (current.exists(wizardFileName)) {
QFile configFile(current.absoluteFilePath(wizardFileName));
configFile.open(QIODevice::ReadOnly);
QJsonParseError error;
QByteArray fileData = configFile.readAll();
QJsonDocument json = QJsonDocument::fromJson(fileData, &error);
configFile.close();
if (error.error != QJsonParseError::NoError) {
int line = 1;
int column = 1;
for (int i = 0; i < error.offset; ++i) {
if (fileData.at(i) == '\n') {
++line;
column = 1;
} else {
++column;
}
}
verboseLog.append(tr("* Failed to parse \"%1\":%2:%3: %4\n")
.arg(configFile.fileName())
.arg(line).arg(column)
.arg(error.errorString()));
continue;
}
if (!json.isObject()) {
verboseLog.append(tr("* Did not find a JSON object in \"%1\".\n")
.arg(configFile.fileName()));
continue;
}
if (verbose())
verboseLog.append(tr("* Configuration found and parsed.\n"));
QVariantMap data = json.object().toVariantMap();
int version = data.value(QLatin1String(VERSION_KEY), 0).toInt();
if (version < 1 || version > 1) {
verboseLog.append(tr("* Version %1 not supported.\n").arg(version));
continue;
}
bool isDisabled = data.value(QLatin1String(DISABLED_KEY), false).toBool();
if (isDisabled) {
verboseLog.append(tr("* Wizard is disabled.\n"));
continue;
}
JsonWizardFactory *factory = createWizardFactory(data, current, &errorMessage);
if (!factory) {
verboseLog.append(tr("* Failed to create: %1\n").arg(errorMessage));
continue;
}
result << factory;
} else {
QList<QFileInfo> subDirs = current.entryInfoList(filters, sortflags);
if (!subDirs.isEmpty()) {
// There is no QList::prepend(QList)...
dirs.swap(subDirs);
dirs.append(subDirs);
} else if (verbose()) {
verboseLog.append(tr("JsonWizard: \"%1\" not found\n").arg(wizardFileName));
}
}
}
}
if (verbose()) { // Print to output pane for Windows.
qWarning("%s", qPrintable(verboseLog));
Core::MessageManager::write(verboseLog, Core::MessageManager::ModeSwitch);
}
return result;
}
JsonWizardFactory *JsonWizardFactory::createWizardFactory(const QVariantMap &data, const QDir &baseDir,
QString *errorMessage)
{
JsonWizardFactory *factory = new JsonWizardFactory;
if (!factory->initialize(data, baseDir, errorMessage)) {
delete factory;
factory = 0;
}
return factory;
}
void JsonWizardFactory::addWizardPath(const Utils::FileName &path)
{
m_searchPaths.append(path);
}
void JsonWizardFactory::setVerbose(int level)
{
m_verbose = level;
}
int JsonWizardFactory::verbose()
{
return m_verbose;
}
void JsonWizardFactory::registerPageFactory(JsonWizardPageFactory *factory)
{
QTC_ASSERT(!s_pageFactories.contains(factory), return);
s_pageFactories.append(factory);
}
void JsonWizardFactory::registerGeneratorFactory(JsonWizardGeneratorFactory *factory)
{
QTC_ASSERT(!s_generatorFactories.contains(factory), return);
s_generatorFactories.append(factory);
}
JsonWizardFactory::~JsonWizardFactory()
{ }
void JsonWizardFactory::runWizard(const QString &path, QWidget *parent, const QString &platform,
const QVariantMap &variables)
{
JsonWizard wizard(parent);
wizard.setWindowIcon(icon());
wizard.setValue(QStringLiteral("WizardDir"), m_wizardDir);
Core::FeatureSet tmp = requiredFeatures();
tmp.remove(pluginFeatures());
wizard.setValue(QStringLiteral("RequiredFeatures"), tmp.toStringList());
tmp = m_preferredFeatures;
tmp.remove(pluginFeatures());
wizard.setValue(QStringLiteral("PreferredFeatures"), tmp.toStringList());
// Add data to wizard:
for (auto i = variables.constBegin(); i != variables.constEnd(); ++i)
wizard.setProperty(i.key().toUtf8(), i.value());
wizard.setValue(QStringLiteral("GivenPath"), path);
wizard.setValue(QStringLiteral("Platform"), platform);
QString kindStr = QLatin1String(Core::Constants::WIZARD_KIND_UNKNOWN);
if (kind() == IWizardFactory::FileWizard)
kindStr = QLatin1String(Core::Constants::WIZARD_KIND_FILE);
else if (kind() == IWizardFactory::ClassWizard)
kindStr = QLatin1String(Core::Constants::WIZARD_KIND_CLASS);
else if (kind() == IWizardFactory::ProjectWizard)
kindStr = QLatin1String(Core::Constants::WIZARD_KIND_PROJECT);
wizard.setValue(QStringLiteral("kind"), kindStr);
for (auto i = m_options.constBegin(); i != m_options.constEnd(); ++i)
wizard.setValue(i.key(), i.value());
foreach (const Page &data, m_pages) {
QTC_ASSERT(data.isValid(), continue);
JsonWizardPageFactory *factory = Utils::findOr(s_pageFactories, 0,
[&data](JsonWizardPageFactory *f) {
return f->canCreate(data.typeId);
});
QTC_ASSERT(factory, continue);
Utils::WizardPage *page = factory->create(&wizard, data.typeId, data.data);
QTC_ASSERT(page, continue);
page->setTitle(data.title);
page->setSubTitle(data.subTitle);
page->setProperty(Utils::SHORT_TITLE_PROPERTY, data.shortTitle);
if (data.index >= 0) {
wizard.setPage(data.index, page);
if (wizard.page(data.index) != page) // Failed to set page!
delete page;
} else {
wizard.addPage(page);
}
}
foreach (const Generator &data, m_generators) {
QTC_ASSERT(data.isValid(), continue);
JsonWizardGeneratorFactory *factory = Utils::findOr(s_generatorFactories, 0,
[&data](JsonWizardGeneratorFactory *f) {
return f->canCreate(data.typeId);
});
QTC_ASSERT(factory, continue);
JsonWizardGenerator *gen = factory->create(data.typeId, data.data, path, platform, variables);
QTC_ASSERT(gen, continue);
wizard.addGenerator(gen);
}
if (!m_pages.isEmpty())
wizard.exec();
else
wizard.accept();
}
QList<QVariant> JsonWizardFactory::objectOrList(const QVariant &data, QString *errorMessage)
{
QList<QVariant> result;
if (data.type() == QVariant::Map)
result.append(data);
else if (data.type() == QVariant::List)
result = data.toList();
else
*errorMessage = tr("Expected an object or a list.");
return result;
}
QString JsonWizardFactory::localizedString(const QVariant &value)
{
if (value.isNull())
return QString();
if (value.type() == QVariant::Map) {
QVariantMap tmp = value.toMap();
const QString locale = languageSetting().toLower();
QStringList locales;
locales << locale << QLatin1String("en") << QLatin1String("C") << tmp.keys();
foreach (const QString &locale, locales) {
QString result = tmp.value(locale, QString()).toString();
if (!result.isEmpty())
return result;
}
return QString();
}
return QCoreApplication::translate("ProjectExplorer::JsonWizardFactory", value.toByteArray());
}
void JsonWizardFactory::destroyAllFactories()
{
qDeleteAll(s_pageFactories);
s_pageFactories.clear();
qDeleteAll(s_generatorFactories);
s_generatorFactories.clear();
}
bool JsonWizardFactory::initialize(const QVariantMap &data, const QDir &baseDir, QString *errorMessage)
{
QTC_ASSERT(errorMessage, return false);
errorMessage->clear();
m_wizardDir = baseDir.absolutePath();
QString strVal = data.value(QLatin1String(KIND_KEY)).toString();
if (strVal != QLatin1String("class")
&& strVal != QLatin1String("file")
&& strVal != QLatin1String("project")) {
*errorMessage = tr("\"kind\" value \"%1\" is not \"class\", \"file\" or \"project\".").arg(strVal);
return false;
}
IWizardFactory::WizardKind kind = IWizardFactory::ProjectWizard;
if (strVal == QLatin1String("class"))
kind = IWizardFactory::ClassWizard;
if (strVal == QLatin1String("file"))
kind = IWizardFactory::FileWizard;
setWizardKind(kind);
strVal = data.value(QLatin1String(ID_KEY)).toString();
if (strVal.isEmpty()) {
*errorMessage = tr("No id set.");
return false;
}
setId(strVal);
strVal = data.value(QLatin1String(CATEGORY_KEY)).toString();
if (strVal.isEmpty()) {
*errorMessage = tr("No category is set.");
return false;
}
setCategory(strVal);
strVal = data.value(QLatin1String(ICON_KEY)).toString();
if (!strVal.isEmpty()) {
strVal = baseDir.absoluteFilePath(strVal);
if (!QFileInfo(strVal).exists()) {
*errorMessage = tr("Icon \"%1\" not found.").arg(strVal);
return false;
}
setIcon(QIcon(strVal));
}
setRequiredFeatures(Core::FeatureSet::fromStringList(data.value(QLatin1String(REQUIRED_FEATURES_KEY)).toStringList()));
m_preferredFeatures = Core::FeatureSet::fromStringList(data.value(QLatin1String(SUGGESTED_FEATURES_KEY)).toStringList());
m_preferredFeatures |= requiredFeatures();
strVal = localizedString(data.value(QLatin1String(DISPLAY_NAME_KEY)));
if (strVal.isEmpty()) {
*errorMessage = tr("No displayName set.");
return false;
}
setDisplayName(strVal);
strVal = localizedString(data.value(QLatin1String(CATEGORY_NAME_KEY)));
if (strVal.isEmpty()) {
*errorMessage = tr("No displayCategory set.");
return false;
}
setDisplayCategory(strVal);
strVal = localizedString(data.value(QLatin1String(DESCRIPTION_KEY)));
if (strVal.isEmpty()) {
*errorMessage = tr("No description set.");
return false;
}
setDescription(strVal);
// Generator:
QVariantList list = objectOrList(data.value(QLatin1String(GENERATOR_KEY)), errorMessage);
if (list.isEmpty()) {
*errorMessage = tr("When parsing \"generators\": %1").arg(*errorMessage);
return false;
}
foreach (const QVariant &v, list) {
Generator gen = parseGenerator(v, errorMessage);
if (gen.isValid())
m_generators.append(gen);
else
return false;
}
// Pages:
list = objectOrList(data.value(QLatin1String(PAGES_KEY)), errorMessage);
if (!errorMessage->isEmpty()) {
*errorMessage = tr("When parsing \"pages\": %1").arg(*errorMessage);
return false;
}
foreach (const QVariant &v, list) {
Page p = parsePage(v, errorMessage);
if (p.isValid())
m_pages.append(p);
else
return false;
}
WizardFlags flags = 0;
if (data.value(QLatin1String(PLATFORM_INDEPENDENT_KEY), false).toBool())
flags |= PlatformIndependent;
setFlags(flags);
// Options:
QVariant optionValue = data.value(QLatin1String(OPTIONS_KEY));
if (optionValue.type() == QVariant::List) {
foreach (const QVariant &v, optionValue.toList()) {
if (v.type() != QVariant::Map) {
*errorMessage = tr("List element of \"options\" is not an object.");
return false;
}
QVariantMap data = v.toMap();
const QString key = data.value(QStringLiteral("key"), QString()).toString();
const QString value = data.value(QStringLiteral("value"), QString()).toString();
if (key.isEmpty()) {
*errorMessage = tr("No \"key\" given for entry in \"options\".");
return false;
}
if (m_options.contains(key)) {
*errorMessage = tr("When parsing \"options\": Key \"%1\" set more than once.").arg(key);
return false;
}
m_options.insert(key, value);
}
} else if (optionValue.isValid()) {
*errorMessage = tr("Value for \"options\" is not a list");
return false;
}
return true;
}
} // namespace ProjectExplorer

View File

@@ -0,0 +1,121 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef JSONWIZARDFACTORY_H
#define JSONWIZARDFACTORY_H
#include "../projectexplorer_export.h"
#include <coreplugin/iwizardfactory.h>
#include <utils/fileutils.h>
#include <QMap>
QT_BEGIN_NAMESPACE
class QDir;
QT_END_NAMESPACE
namespace ProjectExplorer {
class JsonWizardFactory;
class JsonWizardPageFactory;
class JsonWizardGeneratorFactory;
class ProjectExplorerPlugin;
// Documentation inside.
class PROJECTEXPLORER_EXPORT JsonWizardFactory : public Core::IWizardFactory
{
Q_OBJECT
public:
// Add search paths for wizard.json files. All subdirs are going to be checked.
static void addWizardPath(const Utils::FileName &path);
// actual interface of the wizard factory:
class Generator {
public:
bool isValid() const { return typeId.isValid(); }
Core::Id typeId;
QVariant data;
};
class Page {
public:
bool isValid() const { return typeId.isValid(); }
QString title;
QString subTitle;
QString shortTitle;
int index; // page index in the wizard
Core::Id typeId;
QVariant data;
};
static void registerPageFactory(JsonWizardPageFactory *factory);
static void registerGeneratorFactory(JsonWizardGeneratorFactory *factory);
~JsonWizardFactory();
void runWizard(const QString &path, QWidget *parent, const QString &platform,
const QVariantMap &variables);
static QList<QVariant> objectOrList(const QVariant &data, QString *errorMessage);
static QString localizedString(const QVariant &value);
private:
// Create all wizards. As other plugins might register factories for derived
// classes. Called when the new file dialog is shown for the first time.
static QList<JsonWizardFactory *> createWizardFactories();
static JsonWizardFactory *createWizardFactory(const QVariantMap &data, const QDir &baseDir,
QString *errorMessage);
static void setVerbose(int level);
static int verbose();
static void destroyAllFactories();
bool initialize(const QVariantMap &data, const QDir &baseDir, QString *errorMessage);
QString m_wizardDir;
QList<Generator> m_generators;
QList<Page> m_pages;
QMap<QString, QString> m_options;
Core::FeatureSet m_preferredFeatures;
static QList<Utils::FileName> m_searchPaths;
static int m_verbose;
friend class ProjectExplorerPlugin;
};
} //namespace ProjectExplorer
#endif // JSONWIZARDFACTORY_H

View File

@@ -0,0 +1,172 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "jsonwizardgeneratorfactory.h"
#include "jsonwizard.h"
#include "../projectexplorerconstants.h"
#include <coreplugin/dialogs/promptoverwritedialog.h>
#include <utils/algorithm.h>
#include <utils/stringutils.h>
#include <utils/qtcassert.h>
#include <QCoreApplication>
#include <QDir>
#include <QFileInfo>
#include <QDebug>
#include <QStringList>
namespace ProjectExplorer {
// --------------------------------------------------------------------
// JsonWizardGenerator:
// --------------------------------------------------------------------
JsonWizardGenerator::OverwriteResult JsonWizardGenerator::promptForOverwrite(JsonWizard::GeneratorFiles *files,
QString *errorMessage)
{
QStringList existingFiles;
bool oddStuffFound = false;
foreach (const JsonWizard::GeneratorFile &f, *files) {
const QFileInfo fi(f.file.path());
if (fi.exists() && !(f.file.attributes() & Core::GeneratedFile::ForceOverwrite))
existingFiles.append(f.file.path());
}
if (existingFiles.isEmpty())
return OverwriteOk;
// Before prompting to overwrite existing files, loop over files and check
// if there is anything blocking overwriting them (like them being links or folders).
// Format a file list message as ( "<file1> [readonly], <file2> [folder]").
const QString commonExistingPath = Utils::commonPath(existingFiles);
QString fileNamesMsgPart;
foreach (const QString &fileName, existingFiles) {
const QFileInfo fi(fileName);
if (fi.exists()) {
if (!fileNamesMsgPart.isEmpty())
fileNamesMsgPart += QLatin1String(", ");
const QString namePart = QDir::toNativeSeparators(fileName.mid(commonExistingPath.size() + 1));
if (fi.isDir()) {
oddStuffFound = true;
fileNamesMsgPart += QCoreApplication::translate("ProjectExplorer::JsonWizardGenerator", "%1 [folder]")
.arg(namePart);
} else if (fi.isSymLink()) {
oddStuffFound = true;
fileNamesMsgPart += QCoreApplication::translate("ProjectExplorer::JsonWizardGenerator", "%1 [symbolic link]")
.arg(namePart);
} else if (!fi.isWritable()) {
oddStuffFound = true;
fileNamesMsgPart += QCoreApplication::translate("ProjectExplorer::JsonWizardGenerator", "%1 [read only]")
.arg(namePart);
}
}
}
if (oddStuffFound) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonWizardGenerator",
"The directory %1 contains files which cannot be overwritten:\n%2.")
.arg(QDir::toNativeSeparators(commonExistingPath)).arg(fileNamesMsgPart);
return OverwriteError;
}
// Prompt to overwrite existing files.
Core::PromptOverwriteDialog overwriteDialog;
// Scripts cannot handle overwrite
overwriteDialog.setFiles(existingFiles);
foreach (const JsonWizard::GeneratorFile &file, *files)
if (!file.generator->canKeepExistingFiles())
overwriteDialog.setFileEnabled(file.file.path(), false);
if (overwriteDialog.exec() != QDialog::Accepted)
return OverwriteCanceled;
const QStringList existingFilesToKeep = overwriteDialog.uncheckedFiles();
if (existingFilesToKeep.size() == files->size()) // All exist & all unchecked->Cancel.
return OverwriteCanceled;
// Set 'keep' attribute in files
foreach (const QString &keepFile, existingFilesToKeep) {
JsonWizard::GeneratorFile file
= Utils::findOr(*files, JsonWizard::GeneratorFile(),
[&keepFile](const JsonWizard::GeneratorFile &f)
{ return f.file.path() == keepFile; });
if (!file.isValid())
return OverwriteCanceled;
file.file.setAttributes(file.file.attributes() | Core::GeneratedFile::KeepExistingFileAttribute);
}
return OverwriteOk;
}
bool JsonWizardGenerator::formatFiles(const JsonWizard *wizard, JsonWizard::GeneratorFiles *files, QString *errorMessage)
{
for (auto i = files->begin(); i != files->end(); ++i) {
if (!i->generator->formatFile(wizard, &(i->file), errorMessage))
return false;
}
return true;
}
bool JsonWizardGenerator::writeFiles(const JsonWizard *wizard, JsonWizard::GeneratorFiles *files, QString *errorMessage)
{
for (auto i = files->begin(); i != files->end(); ++i) {
if (!i->generator->writeFile(wizard, &(i->file), errorMessage))
return false;
}
return true;
}
bool JsonWizardGenerator::postWrite(const JsonWizard *wizard, JsonWizard::GeneratorFiles *files, QString *errorMessage)
{
for (auto i = files->begin(); i != files->end(); ++i) {
if (!i->generator->postWrite(wizard, &(i->file), errorMessage))
return false;
}
return true;
}
// --------------------------------------------------------------------
// JsonWizardGeneratorFactory:
// --------------------------------------------------------------------
void JsonWizardGeneratorFactory::setTypeIdsSuffixes(const QStringList &suffixes)
{
m_typeIds = Utils::transform(suffixes, [](QString suffix)
{ return Core::Id::fromString(QString::fromLatin1(Constants::GENERATOR_ID_PREFIX) + suffix); });
}
void JsonWizardGeneratorFactory::setTypeIdsSuffix(const QString &suffix)
{
setTypeIdsSuffixes(QStringList() << suffix);
}
} // namespace ProjectExplorer

View File

@@ -0,0 +1,94 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef JSONWIZARDGENERATORFACTORY_H
#define JSONWIZARDGENERATORFACTORY_H
#include "../projectexplorer_export.h"
#include "jsonwizard.h"
#include <coreplugin/id.h>
#include <QList>
#include <QObject>
namespace Utils { class AbstractMacroExpander; }
namespace ProjectExplorer {
class JsonWizardGenerator
{
public:
virtual ~JsonWizardGenerator() { }
virtual Core::GeneratedFiles fileList(Utils::AbstractMacroExpander *expander,
const QString &baseDir, const QString &projectDir,
QString *errorMessage) = 0;
virtual bool formatFile(const JsonWizard *wizard, Core::GeneratedFile *file, QString *errorMessage) = 0;
virtual bool writeFile(const JsonWizard *wizard, Core::GeneratedFile *file, QString *errorMessage) = 0;
virtual bool postWrite(const JsonWizard *wizard, Core::GeneratedFile *file, QString *errorMessage) = 0;
virtual bool canKeepExistingFiles() const { return true; }
enum OverwriteResult { OverwriteOk, OverwriteError, OverwriteCanceled };
static OverwriteResult promptForOverwrite(JsonWizard::GeneratorFiles *files, QString *errorMessage);
static bool formatFiles(const JsonWizard *wizard, QList<JsonWizard::GeneratorFile> *files, QString *errorMessage);
static bool writeFiles(const JsonWizard *wizard, JsonWizard::GeneratorFiles *files, QString *errorMessage);
static bool postWrite(const JsonWizard *wizard, JsonWizard::GeneratorFiles *files, QString *errorMessage);
};
class JsonWizardGeneratorFactory : public QObject
{
Q_OBJECT
public:
bool canCreate(Core::Id typeId) const { return m_typeIds.contains(typeId); }
QList<Core::Id> supportedIds() const { return m_typeIds; }
virtual JsonWizardGenerator *create(Core::Id typeId, const QVariant &data,
const QString &path, const QString &platform,
const QVariantMap &variables) = 0;
// Basic syntax check for the data taken from the wizard.json file:
virtual bool validateData(Core::Id typeId, const QVariant &data, QString *errorMessage) = 0;
protected:
// This will add "PE.Wizard.Generator." in front of the suffixes and set those as supported typeIds
void setTypeIdsSuffixes(const QStringList &suffixes);
void setTypeIdsSuffix(const QString &suffix);
private:
QList<Core::Id> m_typeIds;
};
} // namespace ProjectExplorer
#endif // JSONWIZARDGENERATORFACTORY_H

View File

@@ -0,0 +1,53 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "jsonwizardpagefactory.h"
#include "../projectexplorerconstants.h"
#include <utils/algorithm.h>
namespace ProjectExplorer {
// --------------------------------------------------------------------
// JsonWizardPageFactory:
// --------------------------------------------------------------------
void JsonWizardPageFactory::setTypeIdsSuffixes(const QStringList &suffixes)
{
m_typeIds = Utils::transform(suffixes, [](const QString &suffix) {
return Core::Id::fromString(QString::fromLatin1(Constants::PAGE_ID_PREFIX) + suffix);});
}
void JsonWizardPageFactory::setTypeIdsSuffix(const QString &suffix)
{
setTypeIdsSuffixes(QStringList() << suffix);
}
} // namespace ProjectExplorer

View File

@@ -0,0 +1,69 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef JSONWIZARDPAGEFACTORY_H
#define JSONWIZARDPAGEFACTORY_H
#include "../projectexplorer_export.h"
#include <coreplugin/id.h>
#include <QVariant>
#include <QStringList>
namespace Utils { class WizardPage; }
namespace ProjectExplorer {
class JsonWizard;
class PROJECTEXPLORER_EXPORT JsonWizardPageFactory
{
public:
virtual ~JsonWizardPageFactory() { }
bool canCreate(Core::Id typeId) const { return m_typeIds.contains(typeId); }
QList<Core::Id> supportedIds() const { return m_typeIds; }
virtual Utils::WizardPage *create(JsonWizard *wizard, Core::Id typeId, const QVariant &data) = 0;
// Basic syntax check for the data taken from the wizard.json file:
virtual bool validateData(Core::Id typeId, const QVariant &data, QString *errorMessage) = 0;
protected:
// This will add "PE.Wizard.Page." in front of the suffixes and set those as supported typeIds
void setTypeIdsSuffixes(const QStringList &suffixes);
void setTypeIdsSuffix(const QString &suffix);
private:
QList<Core::Id> m_typeIds;
};
} // namespace ProjectExplorer
#endif // JSONWIZARDPAGEFACTORY_H

View File

@@ -35,6 +35,8 @@
#include "deployablefile.h"
#include "deployconfiguration.h"
#include "gcctoolchainfactories.h"
#include "jsonwizard/jsonwizardexpander.h"
#include "jsonwizard/jsonwizardfactory.h"
#include "project.h"
#include "projectexplorersettings.h"
#include "projectmacroexpander.h"
@@ -313,6 +315,9 @@ ProjectExplorerPlugin::~ProjectExplorerPlugin()
{
removeObject(d->m_welcomePage);
delete d->m_welcomePage;
JsonWizardFactory::destroyAllFactories();
removeObject(this);
// Force sequence of deletion:
delete d->m_kitManager; // remove all the profile informations
@@ -329,6 +334,7 @@ ProjectExplorerPlugin *ProjectExplorerPlugin::instance()
bool ProjectExplorerPlugin::parseArguments(const QStringList &arguments, QString * /* error */)
{
CustomWizard::setVerbose(arguments.count(QLatin1String("-customwizard-verbose")));
JsonWizardFactory::setVerbose(arguments.count(QLatin1String("-customwizard-verbose")));
return true;
}
@@ -1314,6 +1320,8 @@ void ProjectExplorerPlugin::loadCustomWizards()
firstTime = false;
foreach (IWizardFactory *cpw, ProjectExplorer::CustomWizard::createWizards())
addAutoReleasedObject(cpw);
foreach (IWizardFactory *cpw, JsonWizardFactory::createWizardFactories())
addAutoReleasedObject(cpw);
}
}

View File

@@ -2,6 +2,7 @@ QT += quick script xml
include(../../qtcreatorplugin.pri)
include(customwizard/customwizard.pri)
include(jsonwizard/jsonwizard.pri)
HEADERS += projectexplorer.h \
abi.h \
abiwidget.h \

View File

@@ -166,6 +166,18 @@ QtcPlugin {
]
}
Group {
name: "JsonWizard"
prefix: "jsonwizard/"
files: [
"jsonwizard.cpp", "jsonwizard.h",
"jsonwizardexpander.cpp", "jsonwizardexpander.h",
"jsonwizardfactory.cpp", "jsonwizardfactory.h",
"jsonwizardgeneratorfactory.cpp", "jsonwizardgeneratorfactory.h",
"jsonwizardpagefactory.cpp", "jsonwizardpagefactory.h"
]
}
Group {
name: "CustomWizard"
prefix: "customwizard/"

View File

@@ -260,6 +260,10 @@ const char HIDE_FILE_FILTER_DEFAULT[] = "Makefile*; *.o; *.lo; *.la; *.obj; *~;
const char SHOW_FILE_FILTER_SETTING[] = "GenericProject/ShowFileFilter";
const char SHOW_FILE_FILTER_DEFAULT[] = "*.c; *.cc; *.cpp; *.cp; *.cxx; *.c++; *.h; *.hh; *.hpp; *.hxx;";
// JsonWizard:
const char PAGE_ID_PREFIX[] = "PE.Wizard.Page.";
const char GENERATOR_ID_PREFIX[] = "PE.Wizard.Generator.";
} // namespace Constants
// Run modes