iwizardfactory.cpp 9.45 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
Eike Ziller's avatar
Eike Ziller committed
3
4
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8
9
10
11
** 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
Eike Ziller's avatar
Eike Ziller committed
12
13
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
Eike Ziller's avatar
Eike Ziller committed
14
** use the contact form at http://www.qt.io/contact-us.
15
16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
** Alternatively, this file may be used under the terms of the GNU Lesser
Eike Ziller's avatar
Eike Ziller committed
18
19
20
21
22
23
** 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.
hjk's avatar
hjk committed
24
**
Eike Ziller's avatar
Eike Ziller committed
25
26
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
con's avatar
con committed
27
28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
29
****************************************************************************/
30

Tobias Hunger's avatar
Tobias Hunger committed
31
#include "iwizardfactory.h"
32
33
#include <coreplugin/icore.h>
#include <coreplugin/featureprovider.h>
con's avatar
con committed
34

35
#include <extensionsystem/pluginspec.h>
36
37
#include <extensionsystem/pluginmanager.h>

38
#include <utils/algorithm.h>
39
#include <utils/qtcassert.h>
40

41
#include <QStringList>
42

con's avatar
con committed
43
/*!
Tobias Hunger's avatar
Tobias Hunger committed
44
    \class Core::IWizardFactory
con's avatar
con committed
45
46
    \mainclass

Tobias Hunger's avatar
Tobias Hunger committed
47
    \brief The class IWizardFactory is the base class for all wizard factories
con's avatar
con committed
48
49
50
51
52
53
54
55
56
57
    (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.

Tobias Hunger's avatar
Tobias Hunger committed
58
    To make your wizard known to the system, add your IWizardFactory instance to the
59
    plugin manager's object pool in your plugin's initialize function:
con's avatar
con committed
60
61
62
63
    \code
        bool MyPlugin::initialize(const QStringList &arguments, QString *errorString)
        {
            // ... do setup
Tobias Hunger's avatar
Tobias Hunger committed
64
            addAutoReleasedObject(new MyWizardFactory);
con's avatar
con committed
65
66
67
68
69
70
71
72
            // ... do more setup
        }
    \endcode
    \sa Core::BaseFileWizard
    \sa Core::StandardFileWizard
*/

/*!
Tobias Hunger's avatar
Tobias Hunger committed
73
    \enum Core::IWizardFactory::WizardKind
con's avatar
con committed
74
75
76
77
78
79
80
81
82
83
84
85
    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.
*/

/*!
Tobias Hunger's avatar
Tobias Hunger committed
86
    \fn IWizardFactory::IWizardFactory(QObject *parent)
con's avatar
con committed
87
88
89
90
    \internal
*/

/*!
Tobias Hunger's avatar
Tobias Hunger committed
91
    \fn IWizardFactory::~IWizardFactory()
con's avatar
con committed
92
93
94
95
    \internal
*/

/*!
Tobias Hunger's avatar
Tobias Hunger committed
96
    \fn Kind IWizardFactory::kind() const
con's avatar
con committed
97
98
99
100
101
    Returns what kind of objects are created by the wizard.
    \sa Kind
*/

/*!
Tobias Hunger's avatar
Tobias Hunger committed
102
    \fn QIcon IWizardFactory::icon() const
con's avatar
con committed
103
104
105
106
    Returns an icon to show in the wizard selection dialog.
*/

/*!
Tobias Hunger's avatar
Tobias Hunger committed
107
    \fn QString IWizardFactory::description() const
con's avatar
con committed
108
109
110
111
112
    Returns a translated description to show when this wizard is selected
    in the dialog.
*/

/*!
Tobias Hunger's avatar
Tobias Hunger committed
113
    \fn QString IWizardFactory::displayName() const
con's avatar
con committed
114
115
116
117
    Returns the translated name of the wizard, how it should appear in the
    dialog.
*/

Friedemann Kleint's avatar
Friedemann Kleint committed
118
/*!
Tobias Hunger's avatar
Tobias Hunger committed
119
    \fn QString IWizardFactory::id() const
Friedemann Kleint's avatar
Friedemann Kleint committed
120
121
122
123
    Returns an arbitrary id that is used for sorting within the category.
*/


con's avatar
con committed
124
/*!
Tobias Hunger's avatar
Tobias Hunger committed
125
    \fn QString IWizardFactory::category() const
con's avatar
con committed
126
127
128
129
    Returns a category ID to add the wizard to.
*/

/*!
Tobias Hunger's avatar
Tobias Hunger committed
130
    \fn QString IWizardFactory::displayCategory() const
con's avatar
con committed
131
132
133
134
135
    Returns the translated string of the category, how it should appear
    in the dialog.
*/

/*!
Tobias Hunger's avatar
Tobias Hunger committed
136
    \fn void IWizardFactory::runWizard(const QString &path,
137
138
139
140
                                      QWidget *parent,
                                      const QString &platform,
                                      const QVariantMap &variables)

141
    This function is executed when the wizard has been selected by the user
con's avatar
con committed
142
143
    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
Thorbjørn Lindeijer's avatar
Thorbjørn Lindeijer committed
144
    created. The wizard should fill this in its path selection elements as a
con's avatar
con committed
145
146
    default path.
*/
147
148
149

using namespace Core;

150

151
152
namespace {
static QList<IFeatureProvider *> s_providerList;
153
154
155
QList<IWizardFactory *> s_allFactories;
QList<IWizardFactory::FactoryCreator> s_factoryCreators;
bool s_areFactoriesLoaded = false;
156
157
}

158
159
/* A utility to find all wizards supporting a view mode and matching a predicate */
template <class Predicate>
Tobias Hunger's avatar
Tobias Hunger committed
160
    QList<IWizardFactory*> findWizardFactories(Predicate predicate)
161
162
{
    // Filter all wizards
Tobias Hunger's avatar
Tobias Hunger committed
163
164
165
166
    const QList<IWizardFactory*> allFactories = IWizardFactory::allWizardFactories();
    QList<IWizardFactory*> rc;
    const QList<IWizardFactory*>::const_iterator cend = allFactories.constEnd();
    for (QList<IWizardFactory*>::const_iterator it = allFactories.constBegin(); it != cend; ++it)
167
168
169
170
171
        if (predicate(*(*it)))
            rc.push_back(*it);
    return rc;
}

Tobias Hunger's avatar
Tobias Hunger committed
172
QList<IWizardFactory*> IWizardFactory::allWizardFactories()
173
{
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
    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;
                }

                sanityCheck.insert(newFactory->id(), newFactory);
                s_allFactories << newFactory;
            }
        }
    }

    return s_allFactories;
201
202
203
204
205
206
}

// Utility to find all registered wizards of a certain kind

class WizardKindPredicate {
public:
Tobias Hunger's avatar
Tobias Hunger committed
207
208
    WizardKindPredicate(IWizardFactory::WizardKind kind) : m_kind(kind) {}
    bool operator()(const IWizardFactory &w) const { return w.kind() == m_kind; }
209
private:
Tobias Hunger's avatar
Tobias Hunger committed
210
    const IWizardFactory::WizardKind m_kind;
211
212
};

Tobias Hunger's avatar
Tobias Hunger committed
213
QList<IWizardFactory*> IWizardFactory::wizardFactoriesOfKind(WizardKind kind)
214
{
Tobias Hunger's avatar
Tobias Hunger committed
215
    return findWizardFactories(WizardKindPredicate(kind));
216
217
}

Tobias Hunger's avatar
Tobias Hunger committed
218
bool IWizardFactory::isAvailable(const QString &platformName) const
219
{
220
    FeatureSet availableFeatures = pluginFeatures();
221

Orgad Shaneh's avatar
Orgad Shaneh committed
222
    foreach (const IFeatureProvider *featureManager, s_providerList)
223
        availableFeatures |= featureManager->availableFeatures(platformName);
224
225
226

    return availableFeatures.contains(requiredFeatures());
}
227

Tobias Hunger's avatar
Tobias Hunger committed
228
QStringList IWizardFactory::supportedPlatforms() const
229
230
231
232
233
234
235
236
237
238
239
{
    QStringList stringList;

    foreach (const QString &platform, allAvailablePlatforms()) {
        if (isAvailable(platform))
            stringList.append(platform);
    }

    return stringList;
}

240
241
242
243
244
void IWizardFactory::registerFactoryCreator(const IWizardFactory::FactoryCreator &creator)
{
    s_factoryCreators << creator;
}

Tobias Hunger's avatar
Tobias Hunger committed
245
QStringList IWizardFactory::allAvailablePlatforms()
246
247
248
{
    QStringList platforms;

Orgad Shaneh's avatar
Orgad Shaneh committed
249
    foreach (const IFeatureProvider *featureManager, s_providerList)
250
251
252
253
254
        platforms.append(featureManager->availablePlatforms());

    return platforms;
}

Tobias Hunger's avatar
Tobias Hunger committed
255
QString IWizardFactory::displayNameForPlatform(const QString &string)
256
{
Orgad Shaneh's avatar
Orgad Shaneh committed
257
    foreach (const IFeatureProvider *featureManager, s_providerList) {
258
259
260
261
262
263
        QString displayName = featureManager->displayNameForPlatform(string);
        if (!displayName.isEmpty())
            return displayName;
    }
    return QString();
}
264
265
266
267
268
269
270
271
272
273
274
275

void IWizardFactory::registerFeatureProvider(IFeatureProvider *provider)
{
    QTC_ASSERT(!s_providerList.contains(provider), return);
    s_providerList.append(provider);
}

void IWizardFactory::destroyFeatureProvider()
{
    qDeleteAll(s_providerList);
    s_providerList.clear();
}
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

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)
                list.append(QString::fromLatin1("Plugin.") + s->name());
        }
        plugins = FeatureSet::fromStringList(list);
    }
    return plugins;
}
291
292
293
294
295
296

void IWizardFactory::initialize()
{
    connect(ICore::instance(), &ICore::coreAboutToClose,
            ICore::instance(), []() { qDeleteAll(s_allFactories); s_allFactories.clear(); });
}