forked from qt-creator/qt-creator
ce37f05297
That method was used to set a title in the progress view of the wizard that is different from the page title. That is used exactly once and there it adds more confusion than it helps. So get rid of the whole thing. Consistently set the "shortTitle" property instead for all wizards that want to have a separate short title. Change-Id: Ia4881e9c00891058629491f9e9de4ac421c59727 Reviewed-by: Orgad Shaneh <orgads@gmail.com>
361 lines
14 KiB
C++
361 lines
14 KiB
C++
/****************************************************************************
|
|
**
|
|
** 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 "cppclasswizard.h"
|
|
|
|
#include "cppeditorconstants.h"
|
|
|
|
#include <coreplugin/icore.h>
|
|
#include <coreplugin/mimedatabase.h>
|
|
#include <cpptools/abstracteditorsupport.h>
|
|
#include <cpptools/cpptoolsconstants.h>
|
|
|
|
#include <utils/codegeneration.h>
|
|
#include <utils/newclasswidget.h>
|
|
#include <utils/qtcassert.h>
|
|
#include <utils/wizard.h>
|
|
|
|
#include <QDebug>
|
|
#include <QTextStream>
|
|
#include <QVBoxLayout>
|
|
#include <QSpacerItem>
|
|
#include <QWizard>
|
|
|
|
using namespace CppEditor;
|
|
using namespace CppEditor::Internal;
|
|
|
|
// ========= ClassNamePage =========
|
|
|
|
ClassNamePage::ClassNamePage(QWidget *parent) :
|
|
QWizardPage(parent),
|
|
m_isValid(false)
|
|
{
|
|
setTitle(tr("Enter Class Name"));
|
|
setSubTitle(tr("The header and source file names will be derived from the class name"));
|
|
|
|
m_newClassWidget = new Utils::NewClassWidget;
|
|
// Order, set extensions first before suggested name is derived
|
|
m_newClassWidget->setBaseClassInputVisible(true);
|
|
m_newClassWidget->setBaseClassChoices(QStringList() << QString()
|
|
<< QLatin1String("QObject")
|
|
<< QLatin1String("QWidget")
|
|
<< QLatin1String("QMainWindow")
|
|
<< QLatin1String("QDeclarativeItem")
|
|
<< QLatin1String("QQuickItem"));
|
|
m_newClassWidget->setBaseClassEditable(true);
|
|
m_newClassWidget->setFormInputVisible(false);
|
|
m_newClassWidget->setNamespacesEnabled(true);
|
|
m_newClassWidget->setAllowDirectories(true);
|
|
m_newClassWidget->setBaseClassInputVisible(true);
|
|
|
|
connect(m_newClassWidget, SIGNAL(validChanged()), this, SLOT(slotValidChanged()));
|
|
|
|
QVBoxLayout *pageLayout = new QVBoxLayout(this);
|
|
pageLayout->addWidget(m_newClassWidget);
|
|
QSpacerItem *vSpacer = new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::Expanding);
|
|
pageLayout->addItem(vSpacer);
|
|
|
|
initParameters();
|
|
|
|
setProperty(Utils::SHORT_TITLE_PROPERTY, tr("Details"));
|
|
}
|
|
|
|
// Retrieve settings of CppTools plugin.
|
|
static bool lowerCaseFiles()
|
|
{
|
|
QString lowerCaseSettingsKey = QLatin1String(CppTools::Constants::CPPTOOLS_SETTINGSGROUP);
|
|
lowerCaseSettingsKey += QLatin1Char('/');
|
|
lowerCaseSettingsKey += QLatin1String(CppTools::Constants::LOWERCASE_CPPFILES_KEY);
|
|
const bool lowerCaseDefault = CppTools::Constants::lowerCaseFilesDefault;
|
|
return Core::ICore::settings()->value(lowerCaseSettingsKey, QVariant(lowerCaseDefault)).toBool();
|
|
}
|
|
|
|
// Set up new class widget from settings
|
|
void ClassNamePage::initParameters()
|
|
{
|
|
m_newClassWidget->setHeaderExtension(Core::MimeDatabase::preferredSuffixByType(QLatin1String(Constants::CPP_HEADER_MIMETYPE)));
|
|
m_newClassWidget->setSourceExtension(Core::MimeDatabase::preferredSuffixByType(QLatin1String(Constants::CPP_SOURCE_MIMETYPE)));
|
|
m_newClassWidget->setLowerCaseFiles(lowerCaseFiles());
|
|
}
|
|
|
|
void ClassNamePage::slotValidChanged()
|
|
{
|
|
const bool validNow = m_newClassWidget->isValid();
|
|
if (m_isValid != validNow) {
|
|
m_isValid = validNow;
|
|
emit completeChanged();
|
|
}
|
|
}
|
|
|
|
CppClassWizardDialog::CppClassWizardDialog(QWidget *parent) :
|
|
Core::BaseFileWizard(parent),
|
|
m_classNamePage(new ClassNamePage(this))
|
|
{
|
|
setWindowTitle(tr("C++ Class Wizard"));
|
|
addPage(m_classNamePage);
|
|
}
|
|
|
|
void CppClassWizardDialog::setPath(const QString &path)
|
|
{
|
|
m_classNamePage->newClassWidget()->setPath(path);
|
|
}
|
|
|
|
CppClassWizardParameters CppClassWizardDialog::parameters() const
|
|
{
|
|
CppClassWizardParameters rc;
|
|
const Utils::NewClassWidget *ncw = m_classNamePage->newClassWidget();
|
|
rc.className = ncw->className();
|
|
rc.headerFile = ncw->headerFileName();
|
|
rc.sourceFile = ncw->sourceFileName();
|
|
rc.baseClass = ncw->baseClassName();
|
|
rc.path = ncw->path();
|
|
rc.classType = ncw->classType();
|
|
return rc;
|
|
}
|
|
|
|
// ========= CppClassWizard =========
|
|
|
|
CppClassWizard::CppClassWizard()
|
|
{
|
|
}
|
|
|
|
QString CppClassWizard::sourceSuffix() const
|
|
{
|
|
return preferredSuffix(QLatin1String(Constants::CPP_SOURCE_MIMETYPE));
|
|
}
|
|
|
|
QString CppClassWizard::headerSuffix() const
|
|
{
|
|
return preferredSuffix(QLatin1String(Constants::CPP_HEADER_MIMETYPE));
|
|
}
|
|
|
|
Core::BaseFileWizard *CppClassWizard::create(QWidget *parent, const Core::WizardDialogParameters ¶meters) const
|
|
{
|
|
CppClassWizardDialog *wizard = new CppClassWizardDialog(parent);
|
|
foreach (QWizardPage *p, parameters.extensionPages())
|
|
wizard->addPage(p);
|
|
wizard->setPath(parameters.defaultPath());
|
|
return wizard;
|
|
}
|
|
|
|
Core::GeneratedFiles CppClassWizard::generateFiles(const QWizard *w, QString *errorMessage) const
|
|
{
|
|
const CppClassWizardDialog *wizard = qobject_cast<const CppClassWizardDialog *>(w);
|
|
const CppClassWizardParameters params = wizard->parameters();
|
|
|
|
const QString sourceFileName = Core::BaseFileWizardFactory::buildFileName(params.path, params.sourceFile, sourceSuffix());
|
|
const QString headerFileName = Core::BaseFileWizardFactory::buildFileName(params.path, params.headerFile, headerSuffix());
|
|
|
|
Core::GeneratedFile sourceFile(sourceFileName);
|
|
Core::GeneratedFile headerFile(headerFileName);
|
|
|
|
QString header, source;
|
|
if (!generateHeaderAndSource(params, &header, &source)) {
|
|
*errorMessage = tr("Error while generating file contents.");
|
|
return Core::GeneratedFiles();
|
|
}
|
|
headerFile.setContents(header);
|
|
headerFile.setAttributes(Core::GeneratedFile::OpenEditorAttribute);
|
|
|
|
sourceFile.setContents(source);
|
|
sourceFile.setAttributes(Core::GeneratedFile::OpenEditorAttribute);
|
|
return Core::GeneratedFiles() << headerFile << sourceFile;
|
|
}
|
|
|
|
|
|
bool CppClassWizard::generateHeaderAndSource(const CppClassWizardParameters ¶ms,
|
|
QString *header, QString *source)
|
|
{
|
|
// TODO:
|
|
// Quite a bit of this code has been copied from FormClassWizardParameters::generateCpp
|
|
// and is duplicated in the library wizard.
|
|
// Maybe more of it could be merged into Utils.
|
|
|
|
const QString indent = QString(4, QLatin1Char(' '));
|
|
|
|
// Do we have namespaces?
|
|
QStringList namespaceList = params.className.split(QLatin1String("::"));
|
|
if (namespaceList.empty()) // Paranoia!
|
|
return false;
|
|
|
|
const QString headerLicense =
|
|
CppTools::AbstractEditorSupport::licenseTemplate(params.headerFile,
|
|
params.className);
|
|
const QString sourceLicense =
|
|
CppTools::AbstractEditorSupport::licenseTemplate(params.sourceFile,
|
|
params.className);
|
|
|
|
const QString unqualifiedClassName = namespaceList.takeLast();
|
|
const QString guard = Utils::headerGuard(params.headerFile, namespaceList);
|
|
|
|
// == Header file ==
|
|
QTextStream headerStr(header);
|
|
headerStr << headerLicense << "#ifndef " << guard
|
|
<< "\n#define " << guard << '\n';
|
|
|
|
QRegExp qtClassExpr(QLatin1String("^Q[A-Z3].+"));
|
|
QTC_CHECK(qtClassExpr.isValid());
|
|
// Determine parent QObject type for Qt types. Provide base
|
|
// class in case the user did not specify one.
|
|
QString parentQObjectClass;
|
|
bool defineQObjectMacro = false;
|
|
switch (params.classType) {
|
|
case Utils::NewClassWidget::ClassInheritsQObject:
|
|
parentQObjectClass = QLatin1String("QObject");
|
|
defineQObjectMacro = true;
|
|
break;
|
|
case Utils::NewClassWidget::ClassInheritsQWidget:
|
|
parentQObjectClass = QLatin1String("QWidget");
|
|
defineQObjectMacro = true;
|
|
break;
|
|
case Utils::NewClassWidget::ClassInheritsQDeclarativeItem:
|
|
parentQObjectClass = QLatin1String("QDeclarativeItem");
|
|
defineQObjectMacro = true;
|
|
break;
|
|
case Utils::NewClassWidget::ClassInheritsQQuickItem:
|
|
parentQObjectClass = QLatin1String("QQuickItem");
|
|
defineQObjectMacro = true;
|
|
break;
|
|
case Utils::NewClassWidget::NoClassType:
|
|
case Utils::NewClassWidget::SharedDataClass:
|
|
break;
|
|
}
|
|
const QString baseClass = params.baseClass.isEmpty()
|
|
&& params.classType != Utils::NewClassWidget::NoClassType ?
|
|
parentQObjectClass : params.baseClass;
|
|
const bool superIsQtClass = qtClassExpr.exactMatch(baseClass);
|
|
if (superIsQtClass) {
|
|
headerStr << '\n';
|
|
Utils::writeIncludeFileDirective(baseClass, true, headerStr);
|
|
}
|
|
if (params.classType == Utils::NewClassWidget::SharedDataClass) {
|
|
headerStr << '\n';
|
|
Utils::writeIncludeFileDirective(QLatin1String("QSharedDataPointer"), true, headerStr);
|
|
}
|
|
|
|
const QString namespaceIndent = Utils::writeOpeningNameSpaces(namespaceList, QString(), headerStr);
|
|
|
|
const QString sharedDataClass = unqualifiedClassName + QLatin1String("Data");
|
|
|
|
if (params.classType == Utils::NewClassWidget::SharedDataClass)
|
|
headerStr << '\n' << "class " << sharedDataClass << ";\n";
|
|
|
|
// Class declaration
|
|
headerStr << '\n' << namespaceIndent << "class " << unqualifiedClassName;
|
|
if (!baseClass.isEmpty())
|
|
headerStr << " : public " << baseClass << "\n";
|
|
else
|
|
headerStr << "\n";
|
|
headerStr << namespaceIndent << "{\n";
|
|
if (defineQObjectMacro)
|
|
headerStr << namespaceIndent << indent << "Q_OBJECT\n";
|
|
headerStr << namespaceIndent << "public:\n"
|
|
<< namespaceIndent << indent;
|
|
// Constructor
|
|
if (parentQObjectClass.isEmpty()) {
|
|
headerStr << unqualifiedClassName << "();\n";
|
|
} else {
|
|
headerStr << "explicit " << unqualifiedClassName << '(' << parentQObjectClass
|
|
<< " *parent = 0);\n";
|
|
}
|
|
// Copy/Assignment for shared data classes.
|
|
if (params.classType == Utils::NewClassWidget::SharedDataClass) {
|
|
headerStr << namespaceIndent << indent
|
|
<< unqualifiedClassName << "(const " << unqualifiedClassName << " &);\n"
|
|
<< namespaceIndent << indent
|
|
<< unqualifiedClassName << " &operator=(const " << unqualifiedClassName << " &);\n"
|
|
<< namespaceIndent << indent
|
|
<< '~' << unqualifiedClassName << "();\n";
|
|
}
|
|
if (defineQObjectMacro)
|
|
headerStr << '\n' << namespaceIndent << "signals:\n\n" << namespaceIndent << "public slots:\n\n";
|
|
if (params.classType == Utils::NewClassWidget::SharedDataClass) {
|
|
headerStr << '\n' << namespaceIndent << "private:\n"
|
|
<< namespaceIndent << indent << "QSharedDataPointer<" << sharedDataClass << "> data;\n";
|
|
}
|
|
headerStr << namespaceIndent << "};\n";
|
|
|
|
Utils::writeClosingNameSpaces(namespaceList, QString(), headerStr);
|
|
|
|
headerStr << '\n';
|
|
headerStr << "#endif // "<< guard << '\n';
|
|
|
|
// == Source file ==
|
|
QTextStream sourceStr(source);
|
|
sourceStr << sourceLicense;
|
|
Utils::writeIncludeFileDirective(params.headerFile, false, sourceStr);
|
|
if (params.classType == Utils::NewClassWidget::SharedDataClass)
|
|
Utils::writeIncludeFileDirective(QLatin1String("QSharedData"), true, sourceStr);
|
|
|
|
Utils::writeOpeningNameSpaces(namespaceList, QString(), sourceStr);
|
|
// Private class:
|
|
if (params.classType == Utils::NewClassWidget::SharedDataClass) {
|
|
sourceStr << '\n' << namespaceIndent << "class " << sharedDataClass
|
|
<< " : public QSharedData {\n"
|
|
<< namespaceIndent << "public:\n"
|
|
<< namespaceIndent << "};\n";
|
|
}
|
|
|
|
// Constructor
|
|
sourceStr << '\n' << namespaceIndent;
|
|
if (parentQObjectClass.isEmpty()) {
|
|
sourceStr << unqualifiedClassName << "::" << unqualifiedClassName << "()";
|
|
if (params.classType == Utils::NewClassWidget::SharedDataClass)
|
|
sourceStr << " : data(new " << sharedDataClass << ')';
|
|
sourceStr << '\n';
|
|
} else {
|
|
sourceStr << unqualifiedClassName << "::" << unqualifiedClassName
|
|
<< '(' << parentQObjectClass << " *parent) :\n"
|
|
<< namespaceIndent << indent << baseClass << "(parent)\n";
|
|
}
|
|
|
|
sourceStr << namespaceIndent << "{\n" << namespaceIndent << "}\n";
|
|
if (params.classType == Utils::NewClassWidget::SharedDataClass) {
|
|
// Copy
|
|
sourceStr << '\n' << namespaceIndent << unqualifiedClassName << "::" << unqualifiedClassName << "(const "
|
|
<< unqualifiedClassName << " &rhs) : data(rhs.data)\n"
|
|
<< namespaceIndent << "{\n" << namespaceIndent << "}\n\n";
|
|
// Assignment
|
|
sourceStr << namespaceIndent << unqualifiedClassName << " &"
|
|
<< unqualifiedClassName << "::operator=(const " << unqualifiedClassName << " &rhs)\n"
|
|
<< namespaceIndent << "{\n"
|
|
<< namespaceIndent << indent << "if (this != &rhs)\n"
|
|
<< namespaceIndent << indent << indent << "data.operator=(rhs.data);\n"
|
|
<< namespaceIndent << indent << "return *this;\n"
|
|
<< namespaceIndent << "}\n\n";
|
|
// Destructor
|
|
sourceStr << namespaceIndent << unqualifiedClassName << "::~"
|
|
<< unqualifiedClassName << "()\n"
|
|
<< namespaceIndent << "{\n"
|
|
<< namespaceIndent << "}\n";
|
|
}
|
|
Utils::writeClosingNameSpaces(namespaceList, QString(), sourceStr);
|
|
return true;
|
|
}
|