diff --git a/src/plugins/designer/CMakeLists.txt b/src/plugins/designer/CMakeLists.txt
index d51c0ccf3e9..71a999dd8b4 100644
--- a/src/plugins/designer/CMakeLists.txt
+++ b/src/plugins/designer/CMakeLists.txt
@@ -17,6 +17,7 @@ add_qtc_plugin(Designer
cpp/formclasswizarddialog.cpp cpp/formclasswizarddialog.h
cpp/formclasswizardpage.cpp cpp/formclasswizardpage.h cpp/formclasswizardpage.ui
cpp/formclasswizardparameters.cpp cpp/formclasswizardparameters.h
+ cpp/newclasswidget.cpp cpp/newclasswidget.h cpp/newclasswidget.ui
designer_export.h
designerconstants.h
designercontext.cpp designercontext.h
diff --git a/src/plugins/designer/cpp/cpp.pri b/src/plugins/designer/cpp/cpp.pri
index 1527c50cdea..0941cafbda0 100644
--- a/src/plugins/designer/cpp/cpp.pri
+++ b/src/plugins/designer/cpp/cpp.pri
@@ -3,11 +3,15 @@ DEFINES+=CPP_ENABLED
HEADERS+=$$PWD/formclasswizardpage.h \
$$PWD/formclasswizarddialog.h \
$$PWD/formclasswizard.h \
- $$PWD/formclasswizardparameters.h
+ $$PWD/formclasswizardparameters.h \
+ $$PWD/newclasswidget.h
SOURCES+=$$PWD/formclasswizardpage.cpp \
$$PWD/formclasswizarddialog.cpp \
$$PWD/formclasswizard.cpp \
- $$PWD/formclasswizardparameters.cpp
+ $$PWD/formclasswizardparameters.cpp \
+ $$PWD/newclasswidget.cpp
-FORMS+=$$PWD/formclasswizardpage.ui
+FORMS+= \
+ $$PWD/formclasswizardpage.ui \
+ $$PWD/newclasswidget.ui
diff --git a/src/plugins/designer/cpp/formclasswizardpage.cpp b/src/plugins/designer/cpp/formclasswizardpage.cpp
index 358db5a691d..5fd54dbaa0d 100644
--- a/src/plugins/designer/cpp/formclasswizardpage.cpp
+++ b/src/plugins/designer/cpp/formclasswizardpage.cpp
@@ -48,12 +48,8 @@ FormClassWizardPage::FormClassWizardPage(QWidget * parent) :
{
m_ui->setupUi(this);
- m_ui->newClassWidget->setBaseClassInputVisible(false);
- m_ui->newClassWidget->setNamespacesEnabled(true);
- m_ui->newClassWidget->setAllowDirectories(true);
- m_ui->newClassWidget->setClassTypeComboVisible(false);
-
- connect(m_ui->newClassWidget, &Utils::NewClassWidget::validChanged, this, &FormClassWizardPage::slotValidChanged);
+ connect(m_ui->newClassWidget, &NewClassWidget::validChanged, this,
+ &FormClassWizardPage::slotValidChanged);
initFileGenerationSettings();
diff --git a/src/plugins/designer/cpp/formclasswizardpage.ui b/src/plugins/designer/cpp/formclasswizardpage.ui
index 473125d2786..c36c5c274f4 100644
--- a/src/plugins/designer/cpp/formclasswizardpage.ui
+++ b/src/plugins/designer/cpp/formclasswizardpage.ui
@@ -13,7 +13,7 @@
-
-
+
@@ -22,9 +22,9 @@
- Utils::NewClassWidget
+ Designer::Internal::NewClassWidget
QWidget
-
+
1
diff --git a/src/plugins/designer/cpp/newclasswidget.cpp b/src/plugins/designer/cpp/newclasswidget.cpp
new file mode 100644
index 00000000000..2cd400e666c
--- /dev/null
+++ b/src/plugins/designer/cpp/newclasswidget.cpp
@@ -0,0 +1,331 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "newclasswidget.h"
+#include "ui_newclasswidget.h"
+
+#include
+#include
+#include
+
+enum { debugNewClassWidget = 0 };
+
+/*! \class Utils::NewClassWidget
+
+ \brief The NewClassWidget class is a utility widget for 'New Class' wizards.
+
+ This widget prompts the user
+ to enter a class name (optionally derived from some base class) and file
+ names for header, source and form files. Has some smart logic to derive
+ the file names from the class name. */
+
+namespace Designer {
+namespace Internal {
+
+struct NewClassWidgetPrivate {
+ NewClassWidgetPrivate();
+
+ Ui::NewClassWidget m_ui;
+ QString m_headerExtension;
+ QString m_sourceExtension;
+ QString m_formExtension;
+ bool m_valid = false;
+ bool m_classEdited = false;
+ QRegExp m_classNameValidator;
+};
+
+NewClassWidgetPrivate:: NewClassWidgetPrivate() :
+ m_headerExtension(QLatin1Char('h')),
+ m_sourceExtension(QLatin1String("cpp")),
+ m_formExtension(QLatin1String("ui"))
+{
+}
+
+// --------------------- NewClassWidget
+NewClassWidget::NewClassWidget(QWidget *parent) :
+ QWidget(parent),
+ d(new NewClassWidgetPrivate)
+{
+ d->m_ui.setupUi(this);
+
+ d->m_ui.baseClassLabel->setVisible(false);
+ d->m_ui.baseClassComboBox->setVisible(false);
+ d->m_ui.classTypeLabel->setVisible(false);
+ d->m_ui.classTypeComboBox->setVisible(false);
+
+ setNamesDelimiter(QLatin1String("::"));
+
+ connect(d->m_ui.classLineEdit, &Utils::ClassNameValidatingLineEdit::updateFileName,
+ this, &NewClassWidget::slotUpdateFileNames);
+ connect(d->m_ui.classLineEdit, &QLineEdit::textEdited,
+ this, &NewClassWidget::classNameEdited);
+ connect(d->m_ui.baseClassComboBox,
+ QOverload::of(&QComboBox::currentIndexChanged),
+ this, &NewClassWidget::suggestClassNameFromBase);
+ connect(d->m_ui.baseClassComboBox, &QComboBox::editTextChanged,
+ this, &NewClassWidget::slotValidChanged);
+ connect(d->m_ui.classLineEdit, &Utils::FancyLineEdit::validChanged,
+ this, &NewClassWidget::slotValidChanged);
+ connect(d->m_ui.headerFileLineEdit, &Utils::FancyLineEdit::validChanged,
+ this, &NewClassWidget::slotValidChanged);
+ connect(d->m_ui.sourceFileLineEdit, &Utils::FancyLineEdit::validChanged,
+ this, &NewClassWidget::slotValidChanged);
+ connect(d->m_ui.formFileLineEdit, &Utils::FancyLineEdit::validChanged,
+ this, &NewClassWidget::slotValidChanged);
+ connect(d->m_ui.pathChooser, &Utils::PathChooser::validChanged,
+ this, &NewClassWidget::slotValidChanged);
+
+ connect(d->m_ui.classLineEdit, &Utils::FancyLineEdit::validReturnPressed,
+ this, &NewClassWidget::slotActivated);
+ connect(d->m_ui.headerFileLineEdit, &Utils::FancyLineEdit::validReturnPressed,
+ this, &NewClassWidget::slotActivated);
+ connect(d->m_ui.sourceFileLineEdit, &Utils::FancyLineEdit::validReturnPressed,
+ this, &NewClassWidget::slotActivated);
+ connect(d->m_ui.formFileLineEdit, &Utils::FancyLineEdit::validReturnPressed,
+ this, &NewClassWidget::slotActivated);
+ connect(d->m_ui.formFileLineEdit, &Utils::FancyLineEdit::validReturnPressed,
+ this, &NewClassWidget::slotActivated);
+ connect(d->m_ui.pathChooser, &Utils::PathChooser::returnPressed,
+ this, &NewClassWidget::slotActivated);
+
+ setClassType(NoClassType);
+}
+
+NewClassWidget::~NewClassWidget()
+{
+ delete d;
+}
+
+void NewClassWidget::classNameEdited()
+{
+ if (debugNewClassWidget)
+ qDebug() << Q_FUNC_INFO << d->m_headerExtension << d->m_sourceExtension;
+ d->m_classEdited = true;
+}
+
+void NewClassWidget::suggestClassNameFromBase()
+{
+ if (debugNewClassWidget)
+ qDebug() << Q_FUNC_INFO << d->m_headerExtension << d->m_sourceExtension;
+ if (d->m_classEdited)
+ return;
+ // Suggest a class unless edited ("QMainWindow"->"MainWindow")
+ QString base = baseClassName();
+ if (base.startsWith(QLatin1Char('Q'))) {
+ base.remove(0, 1);
+ setClassName(base);
+ }
+}
+
+void NewClassWidget::setClassName(const QString &suggestedName)
+{
+ if (debugNewClassWidget)
+ qDebug() << Q_FUNC_INFO << suggestedName << d->m_headerExtension << d->m_sourceExtension;
+ d->m_ui.classLineEdit->setText(
+ Utils::ClassNameValidatingLineEdit::createClassName(suggestedName));
+}
+
+QString NewClassWidget::className() const
+{
+ return d->m_ui.classLineEdit->text();
+}
+
+QString NewClassWidget::baseClassName() const
+{
+ return d->m_ui.baseClassComboBox->currentText();
+}
+
+QString NewClassWidget::sourceFileName() const
+{
+ return d->m_ui.sourceFileLineEdit->text();
+}
+
+QString NewClassWidget::headerFileName() const
+{
+ return d->m_ui.headerFileLineEdit->text();
+}
+
+QString NewClassWidget::formFileName() const
+{
+ return d->m_ui.formFileLineEdit->text();
+}
+
+QString NewClassWidget::path() const
+{
+ return d->m_ui.pathChooser->path();
+}
+
+void NewClassWidget::setPath(const QString &path)
+{
+ d->m_ui.pathChooser->setPath(path);
+}
+
+QString NewClassWidget::sourceExtension() const
+{
+ return d->m_sourceExtension;
+}
+
+void NewClassWidget::setSourceExtension(const QString &e)
+{
+ if (debugNewClassWidget)
+ qDebug() << Q_FUNC_INFO << e;
+ d->m_sourceExtension = fixSuffix(e);
+}
+
+QString NewClassWidget::headerExtension() const
+{
+ return d->m_headerExtension;
+}
+
+void NewClassWidget::setHeaderExtension(const QString &e)
+{
+ if (debugNewClassWidget)
+ qDebug() << Q_FUNC_INFO << e;
+ d->m_headerExtension = fixSuffix(e);
+}
+
+QString NewClassWidget::formExtension() const
+{
+ return d->m_formExtension;
+}
+
+
+void NewClassWidget::setLowerCaseFiles(bool v)
+{
+ d->m_ui.classLineEdit->setLowerCaseFileName(v);
+}
+
+void NewClassWidget::setClassType(ClassType ct)
+{
+ d->m_ui.classTypeComboBox->setCurrentIndex(ct);
+}
+
+void NewClassWidget::setNamesDelimiter(const QString &delimiter)
+{
+ d->m_ui.classLineEdit->setNamespaceDelimiter(delimiter);
+ const QString escaped = QRegExp::escape(delimiter);
+ d->m_classNameValidator = QRegExp(QLatin1String("[a-zA-Z_][a-zA-Z0-9_]*(")
+ + escaped
+ + QLatin1String("[a-zA-Z_][a-zA-Z0-9_]*)*"));
+}
+
+void NewClassWidget::slotValidChanged()
+{
+ const bool newValid = isValid();
+ if (newValid != d->m_valid) {
+ d->m_valid = newValid;
+ emit validChanged();
+ }
+}
+
+bool NewClassWidget::isValid(QString *error) const
+{
+ if (!d->m_ui.classLineEdit->isValid()) {
+ if (error)
+ *error = d->m_ui.classLineEdit->errorMessage();
+ return false;
+ }
+
+ if (!d->m_ui.headerFileLineEdit->isValid()) {
+ if (error)
+ *error = tr("Invalid header file name: \"%1\"").arg(d->m_ui.headerFileLineEdit->errorMessage());
+ return false;
+ }
+
+ if (!d->m_ui.sourceFileLineEdit->isValid()) {
+ if (error)
+ *error = tr("Invalid source file name: \"%1\"").arg(d->m_ui.sourceFileLineEdit->errorMessage());
+ return false;
+ }
+
+ if (!d->m_ui.formFileLineEdit->isValid()) {
+ if (error)
+ *error = tr("Invalid form file name: \"%1\"").arg(d->m_ui.formFileLineEdit->errorMessage());
+ return false;
+ }
+
+ if (!d->m_ui.pathChooser->isValid()) {
+ if (error)
+ *error = d->m_ui.pathChooser->errorMessage();
+ return false;
+ }
+ return true;
+}
+
+void NewClassWidget::slotUpdateFileNames(const QString &baseName)
+{
+ if (debugNewClassWidget)
+ qDebug() << Q_FUNC_INFO << baseName << d->m_headerExtension << d->m_sourceExtension;
+ const QChar dot = QLatin1Char('.');
+ d->m_ui.sourceFileLineEdit->setText(baseName + dot + d->m_sourceExtension);
+ d->m_ui.headerFileLineEdit->setText(baseName + dot + d->m_headerExtension);
+ d->m_ui.formFileLineEdit->setText(baseName + dot + d->m_formExtension);
+}
+
+void NewClassWidget::slotActivated()
+{
+ if (d->m_valid)
+ emit activated();
+}
+
+QString NewClassWidget::fixSuffix(const QString &suffix)
+{
+ QString s = suffix;
+ if (s.startsWith(QLatin1Char('.')))
+ s.remove(0, 1);
+ return s;
+}
+
+// Utility to add a suffix to a file unless the user specified one
+static QString ensureSuffix(QString f, const QString &extension)
+{
+ const QChar dot = QLatin1Char('.');
+ if (f.contains(dot))
+ return f;
+ f += dot;
+ f += extension;
+ return f;
+}
+
+// If a non-empty name was passed, expand to directory and suffix
+static QString expandFileName(const QDir &dir, const QString &name, const QString &extension)
+{
+ if (name.isEmpty())
+ return QString();
+ return dir.absoluteFilePath(ensureSuffix(name, extension));
+}
+
+QStringList NewClassWidget::files() const
+{
+ QStringList rc;
+ const QDir dir = QDir(path());
+ rc.push_back(expandFileName(dir, headerFileName(), headerExtension()));
+ rc.push_back(expandFileName(dir, sourceFileName(), sourceExtension()));
+ rc.push_back(expandFileName(dir, formFileName(), formExtension()));
+ return rc;
+}
+
+} // namespace Internal
+} // namespace Designer
diff --git a/src/plugins/designer/cpp/newclasswidget.h b/src/plugins/designer/cpp/newclasswidget.h
new file mode 100644
index 00000000000..91868c13cfc
--- /dev/null
+++ b/src/plugins/designer/cpp/newclasswidget.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include
+
+QT_BEGIN_NAMESPACE
+class QStringList;
+QT_END_NAMESPACE
+
+namespace Designer {
+namespace Internal {
+
+struct NewClassWidgetPrivate;
+
+class NewClassWidget : public QWidget
+{
+ Q_OBJECT
+ Q_ENUMS(ClassType)
+
+public:
+ enum ClassType { NoClassType,
+ ClassInheritsQObject,
+ ClassInheritsQWidget,
+ ClassInheritsQDeclarativeItem,
+ ClassInheritsQQuickItem,
+ SharedDataClass
+ };
+ explicit NewClassWidget(QWidget *parent = nullptr);
+ ~NewClassWidget() override;
+
+ QString className() const;
+ QString baseClassName() const;
+ QString sourceFileName() const;
+ QString headerFileName() const;
+ QString formFileName() const;
+ QString path() const;
+ QString sourceExtension() const;
+ QString headerExtension() const;
+ QString formExtension() const;
+
+ bool isValid(QString *error = nullptr) const;
+
+ QStringList files() const;
+
+signals:
+ void validChanged();
+ void activated();
+
+public slots:
+
+ /**
+ * The name passed into the new class widget will be reformatted to be a
+ * valid class name.
+ */
+ void setClassName(const QString &suggestedName);
+ void setPath(const QString &path);
+ void setSourceExtension(const QString &e);
+ void setHeaderExtension(const QString &e);
+ void setLowerCaseFiles(bool v);
+ void setClassType(ClassType ct);
+ void setNamesDelimiter(const QString &delimiter);
+
+ /**
+ * Suggest a class name from the base class by stripping the leading 'Q'
+ * character. This will happen automagically if the base class combo
+ * changes until the class line edited is manually edited.
+ */
+ void suggestClassNameFromBase();
+
+private:
+ void slotUpdateFileNames(const QString &t);
+ void slotValidChanged();
+ void slotActivated();
+ void classNameEdited();
+
+ QString fixSuffix(const QString &suffix);
+ NewClassWidgetPrivate *d;
+};
+
+} // namespace Internal
+} // namespace Designer
diff --git a/src/plugins/designer/cpp/newclasswidget.ui b/src/plugins/designer/cpp/newclasswidget.ui
new file mode 100644
index 00000000000..50a01383029
--- /dev/null
+++ b/src/plugins/designer/cpp/newclasswidget.ui
@@ -0,0 +1,212 @@
+
+
+ Designer::Internal::NewClassWidget
+
+
+
+ 0
+ 0
+ 300
+ 194
+
+
+
+
+ QFormLayout::ExpandingFieldsGrow
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ &Class name:
+
+
+ classLineEdit
+
+
+
+ -
+
+
+ -
+
+
+ &Base class:
+
+
+ baseClassComboBox
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ &Type information:
+
+
+ classTypeComboBox
+
+
+
+ -
+
+
-
+
+ None
+
+
+ -
+
+ Inherits QObject
+
+
+ -
+
+ Inherits QWidget
+
+
+ -
+
+ Inherits QDeclarativeItem - Qt Quick 1
+
+
+ -
+
+ Inherits QQuickItem - Qt Quick 2
+
+
+ -
+
+ Based on QSharedData
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Fixed
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Fixed
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ &Header file:
+
+
+ headerFileLineEdit
+
+
+
+ -
+
+
+ -
+
+
+ &Source file:
+
+
+ sourceFileLineEdit
+
+
+
+ -
+
+
+ -
+
+
+ &Form file:
+
+
+ formFileLineEdit
+
+
+
+ -
+
+
+ -
+
+
+ &Path:
+
+
+ pathLabel
+
+
+
+ -
+
+
+
+
+
+
+ Utils::ClassNameValidatingLineEdit
+ QLineEdit
+ utils/classnamevalidatinglineedit.h
+
+
+ Utils::FileNameValidatingLineEdit
+ QLineEdit
+ utils/filenamevalidatinglineedit.h
+
+
+ Utils::PathChooser
+ QWidget
+
+ 1
+
+
+
+
+
diff --git a/src/plugins/designer/designer.qbs b/src/plugins/designer/designer.qbs
index b991840f919..af855234fde 100644
--- a/src/plugins/designer/designer.qbs
+++ b/src/plugins/designer/designer.qbs
@@ -72,6 +72,7 @@ QtcPlugin {
"formclasswizarddialog.cpp", "formclasswizarddialog.h",
"formclasswizardpage.cpp", "formclasswizardpage.h", "formclasswizardpage.ui",
"formclasswizardparameters.cpp", "formclasswizardparameters.h",
+ "newclasswidget.cpp", "newclasswidget.h", "newclasswidget.ui",
]
}