2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2009-05-11 13:34:58 +02:00
|
|
|
**
|
2015-01-14 18:07:15 +01:00
|
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
|
|
|
** Contact: http://www.qt.io/licensing
|
2009-05-11 13:34:58 +02:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2009-05-11 13:34:58 +02:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** 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
|
2015-01-14 18:07:15 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms and
|
|
|
|
|
** conditions see http://www.qt.io/terms-conditions. For further information
|
2014-10-01 13:21:18 +02:00
|
|
|
** use the contact form at http://www.qt.io/contact-us.
|
2009-05-11 13:34:58 +02:00
|
|
|
**
|
|
|
|
|
** GNU Lesser General Public License Usage
|
2012-10-02 09:12:39 +02:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2014-10-01 13:21:18 +02:00
|
|
|
** General Public License version 2.1 or version 3 as published by the Free
|
|
|
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
|
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
|
|
|
** following information to ensure the GNU Lesser General Public License
|
|
|
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2012-10-02 09:12:39 +02:00
|
|
|
**
|
2015-01-14 18:07:15 +01:00
|
|
|
** In addition, as a special exception, The Qt Company gives you certain additional
|
|
|
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
2010-12-17 16:01:08 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2009-05-11 13:34:58 +02:00
|
|
|
|
2014-05-02 17:38:42 +02:00
|
|
|
#include "iwizardfactory.h"
|
2015-05-19 15:09:51 +02:00
|
|
|
|
|
|
|
|
#include "actionmanager/actionmanager.h"
|
|
|
|
|
#include "documentmanager.h"
|
|
|
|
|
#include "icore.h"
|
|
|
|
|
#include "featureprovider.h"
|
2009-05-07 15:50:26 +02:00
|
|
|
|
2014-07-16 12:26:36 +02:00
|
|
|
#include <extensionsystem/pluginspec.h>
|
2009-05-11 13:34:58 +02:00
|
|
|
#include <extensionsystem/pluginmanager.h>
|
|
|
|
|
|
2014-07-29 16:39:03 +02:00
|
|
|
#include <utils/qtcassert.h>
|
2014-07-16 12:26:36 +02:00
|
|
|
|
2015-05-19 15:09:51 +02:00
|
|
|
#include <QAction>
|
2012-01-18 13:50:14 +01:00
|
|
|
|
2009-05-07 15:50:26 +02:00
|
|
|
/*!
|
2014-05-02 17:38:42 +02:00
|
|
|
\class Core::IWizardFactory
|
2009-05-07 15:50:26 +02:00
|
|
|
\mainclass
|
|
|
|
|
|
2014-05-02 17:38:42 +02:00
|
|
|
\brief The class IWizardFactory is the base class for all wizard factories
|
2009-05-07 15:50:26 +02:00
|
|
|
(for example shown in \gui {File | New}).
|
|
|
|
|
|
|
|
|
|
The wizard interface is a very thin abstraction for the \gui{New...} wizards.
|
|
|
|
|
Basically it defines what to show to the user in the wizard selection dialogs,
|
|
|
|
|
and a hook that is called if the user selects the wizard.
|
|
|
|
|
|
|
|
|
|
Wizards can then perform any operations they like, including showing dialogs and
|
|
|
|
|
creating files. Often it is not necessary to create your own wizard from scratch,
|
|
|
|
|
instead use one of the predefined wizards and adapt it to your needs.
|
|
|
|
|
|
2014-05-02 17:38:42 +02:00
|
|
|
To make your wizard known to the system, add your IWizardFactory instance to the
|
2013-10-07 13:34:40 +02:00
|
|
|
plugin manager's object pool in your plugin's initialize function:
|
2009-05-07 15:50:26 +02:00
|
|
|
\code
|
|
|
|
|
bool MyPlugin::initialize(const QStringList &arguments, QString *errorString)
|
|
|
|
|
{
|
|
|
|
|
// ... do setup
|
2014-05-02 17:38:42 +02:00
|
|
|
addAutoReleasedObject(new MyWizardFactory);
|
2009-05-07 15:50:26 +02:00
|
|
|
// ... do more setup
|
|
|
|
|
}
|
|
|
|
|
\endcode
|
|
|
|
|
\sa Core::BaseFileWizard
|
|
|
|
|
\sa Core::StandardFileWizard
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
2014-05-02 17:38:42 +02:00
|
|
|
\enum Core::IWizardFactory::WizardKind
|
2009-05-07 15:50:26 +02:00
|
|
|
Used to specify what kind of objects the wizard creates. This information is used
|
|
|
|
|
to show e.g. only wizards that create projects when selecting a \gui{New Project}
|
|
|
|
|
menu item.
|
|
|
|
|
\value FileWizard
|
|
|
|
|
The wizard creates one or more files.
|
|
|
|
|
\value ClassWizard
|
|
|
|
|
The wizard creates a new class (e.g. source+header files).
|
|
|
|
|
\value ProjectWizard
|
|
|
|
|
The wizard creates a new project.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
2014-05-02 17:38:42 +02:00
|
|
|
\fn IWizardFactory::IWizardFactory(QObject *parent)
|
2009-05-07 15:50:26 +02:00
|
|
|
\internal
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
2014-05-02 17:38:42 +02:00
|
|
|
\fn IWizardFactory::~IWizardFactory()
|
2009-05-07 15:50:26 +02:00
|
|
|
\internal
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
2014-05-02 17:38:42 +02:00
|
|
|
\fn Kind IWizardFactory::kind() const
|
2009-05-07 15:50:26 +02:00
|
|
|
Returns what kind of objects are created by the wizard.
|
|
|
|
|
\sa Kind
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
2014-05-02 17:38:42 +02:00
|
|
|
\fn QIcon IWizardFactory::icon() const
|
2009-05-07 15:50:26 +02:00
|
|
|
Returns an icon to show in the wizard selection dialog.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
2014-05-02 17:38:42 +02:00
|
|
|
\fn QString IWizardFactory::description() const
|
2009-05-07 15:50:26 +02:00
|
|
|
Returns a translated description to show when this wizard is selected
|
|
|
|
|
in the dialog.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
2014-05-02 17:38:42 +02:00
|
|
|
\fn QString IWizardFactory::displayName() const
|
2009-05-07 15:50:26 +02:00
|
|
|
Returns the translated name of the wizard, how it should appear in the
|
|
|
|
|
dialog.
|
|
|
|
|
*/
|
|
|
|
|
|
2009-11-27 10:33:24 +01:00
|
|
|
/*!
|
2014-05-02 17:38:42 +02:00
|
|
|
\fn QString IWizardFactory::id() const
|
2009-11-27 10:33:24 +01:00
|
|
|
Returns an arbitrary id that is used for sorting within the category.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2009-05-07 15:50:26 +02:00
|
|
|
/*!
|
2014-05-02 17:38:42 +02:00
|
|
|
\fn QString IWizardFactory::category() const
|
2009-05-07 15:50:26 +02:00
|
|
|
Returns a category ID to add the wizard to.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
2014-05-02 17:38:42 +02:00
|
|
|
\fn QString IWizardFactory::displayCategory() const
|
2009-05-07 15:50:26 +02:00
|
|
|
Returns the translated string of the category, how it should appear
|
|
|
|
|
in the dialog.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
2014-05-02 17:38:42 +02:00
|
|
|
\fn void IWizardFactory::runWizard(const QString &path,
|
2013-05-23 16:13:55 +02:00
|
|
|
QWidget *parent,
|
|
|
|
|
const QString &platform,
|
|
|
|
|
const QVariantMap &variables)
|
|
|
|
|
|
2013-10-07 13:34:40 +02:00
|
|
|
This function is executed when the wizard has been selected by the user
|
2009-05-07 15:50:26 +02:00
|
|
|
for execution. Any dialogs the wizard opens should use the given \a parent.
|
|
|
|
|
The \a path argument is a suggestion for the location where files should be
|
2009-06-12 13:07:15 +02:00
|
|
|
created. The wizard should fill this in its path selection elements as a
|
2009-05-07 15:50:26 +02:00
|
|
|
default path.
|
|
|
|
|
*/
|
2009-05-11 13:34:58 +02:00
|
|
|
|
|
|
|
|
using namespace Core;
|
|
|
|
|
|
2015-05-22 17:16:36 +02:00
|
|
|
|
2014-07-29 16:39:03 +02:00
|
|
|
namespace {
|
|
|
|
|
static QList<IFeatureProvider *> s_providerList;
|
2015-05-22 17:16:36 +02:00
|
|
|
QList<IWizardFactory *> s_allFactories;
|
|
|
|
|
QList<IWizardFactory::FactoryCreator> s_factoryCreators;
|
|
|
|
|
bool s_areFactoriesLoaded = false;
|
2015-05-29 15:55:49 +02:00
|
|
|
bool s_isWizardRunning = false;
|
2014-07-29 16:39:03 +02:00
|
|
|
}
|
|
|
|
|
|
2009-05-11 13:34:58 +02:00
|
|
|
/* A utility to find all wizards supporting a view mode and matching a predicate */
|
2015-05-29 11:43:03 +02:00
|
|
|
QList<IWizardFactory*> findWizardFactories(const std::function<bool(IWizardFactory*)> &predicate)
|
2009-05-11 13:34:58 +02:00
|
|
|
{
|
2015-05-29 11:43:03 +02:00
|
|
|
const QList<IWizardFactory *> allFactories = IWizardFactory::allWizardFactories();
|
|
|
|
|
QList<IWizardFactory *> rc;
|
|
|
|
|
auto cend = allFactories.constEnd();
|
|
|
|
|
for (auto it = allFactories.constBegin(); it != cend; ++it) {
|
|
|
|
|
if (predicate(*it))
|
2009-05-11 13:34:58 +02:00
|
|
|
rc.push_back(*it);
|
2015-05-29 11:43:03 +02:00
|
|
|
}
|
2009-05-11 13:34:58 +02:00
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-19 15:09:51 +02:00
|
|
|
static Id actionId(const IWizardFactory *factory)
|
|
|
|
|
{
|
|
|
|
|
return factory->id().withPrefix("Wizard.Impl.");
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-02 17:38:42 +02:00
|
|
|
QList<IWizardFactory*> IWizardFactory::allWizardFactories()
|
2009-05-11 13:34:58 +02:00
|
|
|
{
|
2015-05-22 17:16:36 +02:00
|
|
|
if (!s_areFactoriesLoaded) {
|
|
|
|
|
QTC_ASSERT(s_allFactories.isEmpty(), return s_allFactories);
|
|
|
|
|
|
|
|
|
|
s_areFactoriesLoaded = true;
|
|
|
|
|
|
|
|
|
|
QHash<Id, IWizardFactory *> sanityCheck;
|
|
|
|
|
foreach (const FactoryCreator &fc, s_factoryCreators) {
|
|
|
|
|
QList<IWizardFactory *> tmp = fc();
|
|
|
|
|
foreach (IWizardFactory *newFactory, tmp) {
|
|
|
|
|
QTC_ASSERT(newFactory, continue);
|
|
|
|
|
IWizardFactory *existingFactory = sanityCheck.value(newFactory->id());
|
|
|
|
|
|
|
|
|
|
QTC_ASSERT(existingFactory != newFactory, continue);
|
|
|
|
|
if (existingFactory) {
|
|
|
|
|
qWarning("%s", qPrintable(tr("Factory with id=\"%1\" already registered. Deleting.")
|
|
|
|
|
.arg(existingFactory->id().toString())));
|
|
|
|
|
delete newFactory;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-19 15:09:51 +02:00
|
|
|
QTC_ASSERT(!newFactory->m_action, continue);
|
|
|
|
|
newFactory->m_action = new QAction(newFactory->displayName(), newFactory);
|
|
|
|
|
ActionManager::registerAction(newFactory->m_action, actionId(newFactory));
|
|
|
|
|
|
|
|
|
|
connect(newFactory->m_action, &QAction::triggered, newFactory, [newFactory]() {
|
|
|
|
|
QString path = newFactory->runPath(QString());
|
|
|
|
|
newFactory->runWizard(path, ICore::dialogParent(), QString(), QVariantMap());
|
|
|
|
|
});
|
|
|
|
|
|
2015-05-22 17:16:36 +02:00
|
|
|
sanityCheck.insert(newFactory->id(), newFactory);
|
|
|
|
|
s_allFactories << newFactory;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return s_allFactories;
|
2009-05-11 13:34:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Utility to find all registered wizards of a certain kind
|
2014-05-02 17:38:42 +02:00
|
|
|
QList<IWizardFactory*> IWizardFactory::wizardFactoriesOfKind(WizardKind kind)
|
2009-05-11 13:34:58 +02:00
|
|
|
{
|
2015-05-29 11:43:03 +02:00
|
|
|
return findWizardFactories([kind](IWizardFactory *f) { return f->kind() == kind; });
|
2009-05-11 13:34:58 +02:00
|
|
|
}
|
|
|
|
|
|
2015-05-19 15:09:51 +02:00
|
|
|
QString IWizardFactory::runPath(const QString &defaultPath)
|
|
|
|
|
{
|
|
|
|
|
QString path = defaultPath;
|
|
|
|
|
if (path.isEmpty()) {
|
|
|
|
|
switch (kind()) {
|
|
|
|
|
case IWizardFactory::ProjectWizard:
|
|
|
|
|
// Project wizards: Check for projects directory or
|
|
|
|
|
// use last visited directory of file dialog. Never start
|
|
|
|
|
// at current.
|
|
|
|
|
path = DocumentManager::useProjectsDirectory() ?
|
|
|
|
|
DocumentManager::projectsDirectory() :
|
|
|
|
|
DocumentManager::fileDialogLastVisitedDirectory();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
path = DocumentManager::fileDialogInitialDirectory();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return path;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 15:55:49 +02:00
|
|
|
void IWizardFactory::runWizard(const QString &path, QWidget *parent, const QString &platform, const QVariantMap &variables)
|
|
|
|
|
{
|
|
|
|
|
s_isWizardRunning = true;
|
|
|
|
|
ICore::validateNewDialogIsRunning();
|
|
|
|
|
|
|
|
|
|
runWizardImpl(path, parent, platform, variables);
|
|
|
|
|
|
|
|
|
|
s_isWizardRunning = false;
|
|
|
|
|
ICore::validateNewDialogIsRunning();
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-02 17:38:42 +02:00
|
|
|
bool IWizardFactory::isAvailable(const QString &platformName) const
|
2012-01-18 13:50:14 +01:00
|
|
|
{
|
2015-05-28 16:28:27 +02:00
|
|
|
if (platformName.isEmpty())
|
|
|
|
|
return true;
|
|
|
|
|
|
2015-05-27 15:29:27 +02:00
|
|
|
return availableFeatures(platformName).contains(requiredFeatures());
|
2012-01-18 13:50:14 +01:00
|
|
|
}
|
2012-02-08 17:25:35 +01:00
|
|
|
|
2014-05-02 17:38:42 +02:00
|
|
|
QStringList IWizardFactory::supportedPlatforms() const
|
2012-02-08 17:25:35 +01:00
|
|
|
{
|
|
|
|
|
QStringList stringList;
|
|
|
|
|
|
|
|
|
|
foreach (const QString &platform, allAvailablePlatforms()) {
|
|
|
|
|
if (isAvailable(platform))
|
|
|
|
|
stringList.append(platform);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return stringList;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-22 17:16:36 +02:00
|
|
|
void IWizardFactory::registerFactoryCreator(const IWizardFactory::FactoryCreator &creator)
|
|
|
|
|
{
|
|
|
|
|
s_factoryCreators << creator;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-02 17:38:42 +02:00
|
|
|
QStringList IWizardFactory::allAvailablePlatforms()
|
2012-02-08 17:25:35 +01:00
|
|
|
{
|
|
|
|
|
QStringList platforms;
|
|
|
|
|
|
2014-11-16 10:52:41 +02:00
|
|
|
foreach (const IFeatureProvider *featureManager, s_providerList)
|
2012-02-08 17:25:35 +01:00
|
|
|
platforms.append(featureManager->availablePlatforms());
|
|
|
|
|
|
|
|
|
|
return platforms;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-02 17:38:42 +02:00
|
|
|
QString IWizardFactory::displayNameForPlatform(const QString &string)
|
2012-02-08 17:25:35 +01:00
|
|
|
{
|
2014-11-16 10:52:41 +02:00
|
|
|
foreach (const IFeatureProvider *featureManager, s_providerList) {
|
2012-02-08 17:25:35 +01:00
|
|
|
QString displayName = featureManager->displayNameForPlatform(string);
|
|
|
|
|
if (!displayName.isEmpty())
|
|
|
|
|
return displayName;
|
|
|
|
|
}
|
|
|
|
|
return QString();
|
|
|
|
|
}
|
2014-07-29 16:39:03 +02:00
|
|
|
|
|
|
|
|
void IWizardFactory::registerFeatureProvider(IFeatureProvider *provider)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(!s_providerList.contains(provider), return);
|
|
|
|
|
s_providerList.append(provider);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 15:55:49 +02:00
|
|
|
bool IWizardFactory::isWizardRunning()
|
|
|
|
|
{
|
|
|
|
|
return s_isWizardRunning;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-29 16:39:03 +02:00
|
|
|
void IWizardFactory::destroyFeatureProvider()
|
|
|
|
|
{
|
|
|
|
|
qDeleteAll(s_providerList);
|
|
|
|
|
s_providerList.clear();
|
|
|
|
|
}
|
2014-08-27 13:03:32 +02:00
|
|
|
|
2015-05-19 15:09:51 +02:00
|
|
|
void IWizardFactory::clearWizardFactories()
|
|
|
|
|
{
|
2015-05-29 15:57:03 +02:00
|
|
|
QTC_ASSERT(!ICore::isNewItemDialogRunning(), return);
|
|
|
|
|
|
2015-05-19 15:09:51 +02:00
|
|
|
foreach (IWizardFactory *factory, s_allFactories)
|
|
|
|
|
ActionManager::unregisterAction(factory->m_action, actionId(factory));
|
|
|
|
|
|
|
|
|
|
qDeleteAll(s_allFactories);
|
|
|
|
|
s_allFactories.clear();
|
|
|
|
|
|
|
|
|
|
s_areFactoriesLoaded = false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-27 13:03:32 +02:00
|
|
|
FeatureSet IWizardFactory::pluginFeatures() const
|
|
|
|
|
{
|
|
|
|
|
static FeatureSet plugins;
|
|
|
|
|
if (plugins.isEmpty()) {
|
|
|
|
|
QStringList list;
|
|
|
|
|
// Implicitly create a feature for each plugin loaded:
|
|
|
|
|
foreach (ExtensionSystem::PluginSpec *s, ExtensionSystem::PluginManager::plugins()) {
|
|
|
|
|
if (s->state() == ExtensionSystem::PluginSpec::Running)
|
2015-05-27 15:45:07 +02:00
|
|
|
list.append(s->name());
|
2014-08-27 13:03:32 +02:00
|
|
|
}
|
|
|
|
|
plugins = FeatureSet::fromStringList(list);
|
|
|
|
|
}
|
|
|
|
|
return plugins;
|
|
|
|
|
}
|
2015-05-22 17:16:36 +02:00
|
|
|
|
2015-05-27 15:29:27 +02:00
|
|
|
FeatureSet IWizardFactory::availableFeatures(const QString &platformName) const
|
|
|
|
|
{
|
2015-05-29 11:27:17 +02:00
|
|
|
FeatureSet availableFeatures;
|
2015-05-27 15:29:27 +02:00
|
|
|
|
|
|
|
|
foreach (const IFeatureProvider *featureManager, s_providerList)
|
|
|
|
|
availableFeatures |= featureManager->availableFeatures(platformName);
|
|
|
|
|
|
|
|
|
|
return availableFeatures;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-22 17:16:36 +02:00
|
|
|
void IWizardFactory::initialize()
|
|
|
|
|
{
|
2015-05-19 15:09:51 +02:00
|
|
|
connect(ICore::instance(), &ICore::coreAboutToClose, &IWizardFactory::clearWizardFactories);
|
2015-05-19 15:37:19 +02:00
|
|
|
|
|
|
|
|
auto resetAction = new QAction(tr("Reload All Wizards"), ActionManager::instance());
|
|
|
|
|
ActionManager::registerAction(resetAction, "Wizard.Factory.Reset");
|
|
|
|
|
|
|
|
|
|
connect(resetAction, &QAction::triggered, &IWizardFactory::clearWizardFactories);
|
2015-05-29 15:57:03 +02:00
|
|
|
connect(ICore::instance(), &ICore::newItemDialogRunningChanged, resetAction,
|
|
|
|
|
[resetAction]() { resetAction->setEnabled(!ICore::isNewItemDialogRunning()); });
|
2015-05-22 17:16:36 +02:00
|
|
|
}
|