2 ******************************************************************************
4 * @file newclasswidget.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
8 * @see The GNU Public License (GPL) Version 3
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "newclasswidget.h"
30 #include "ui_newclasswidget.h"
32 #include <utils/filewizardpage.h>
34 #include <QFileDialog>
35 #include <QtCore/QFileInfo>
36 #include <QtCore/QStringList>
37 #include <QtCore/QDir>
38 #include <QtCore/QDebug>
39 #include <QtCore/QRegExp>
41 enum { debugNewClassWidget
= 0 };
44 struct NewClassWidgetPrivate
{
45 NewClassWidgetPrivate();
47 Ui::NewClassWidget m_ui
;
48 QString m_headerExtension
;
49 QString m_sourceExtension
;
50 QString m_formExtension
;
53 // Store the "visible" values to prevent the READ accessors from being
54 // fooled by a temporarily hidden widget
55 bool m_baseClassInputVisible
;
56 bool m_formInputVisible
;
57 bool m_pathInputVisible
;
58 bool m_qobjectCheckBoxVisible
;
59 bool m_formInputCheckable
;
62 NewClassWidgetPrivate::NewClassWidgetPrivate() :
63 m_headerExtension(QLatin1String("h")),
64 m_sourceExtension(QLatin1String("cpp")),
65 m_formExtension(QLatin1String("ui")),
68 m_baseClassInputVisible(true),
69 m_formInputVisible(true),
70 m_pathInputVisible(true),
71 m_qobjectCheckBoxVisible(false),
72 m_formInputCheckable(false)
76 // --------------------- NewClassWidget
77 NewClassWidget::NewClassWidget(QWidget
*parent
) :
79 m_d(new NewClassWidgetPrivate
)
81 m_d
->m_ui
.setupUi(this);
83 m_d
->m_ui
.baseClassComboBox
->setEditable(false);
85 connect(m_d
->m_ui
.classLineEdit
, SIGNAL(updateFileName(QString
)),
86 this, SLOT(slotUpdateFileNames(QString
)));
87 connect(m_d
->m_ui
.classLineEdit
, SIGNAL(textEdited(QString
)),
88 this, SLOT(classNameEdited()));
89 connect(m_d
->m_ui
.baseClassComboBox
, SIGNAL(currentIndexChanged(int)),
90 this, SLOT(suggestClassNameFromBase()));
91 connect(m_d
->m_ui
.baseClassComboBox
, SIGNAL(editTextChanged(QString
)),
92 this, SLOT(slotValidChanged()));
93 connect(m_d
->m_ui
.classLineEdit
, SIGNAL(validChanged()),
94 this, SLOT(slotValidChanged()));
95 connect(m_d
->m_ui
.headerFileLineEdit
, SIGNAL(validChanged()),
96 this, SLOT(slotValidChanged()));
97 connect(m_d
->m_ui
.sourceFileLineEdit
, SIGNAL(validChanged()),
98 this, SLOT(slotValidChanged()));
99 connect(m_d
->m_ui
.formFileLineEdit
, SIGNAL(validChanged()),
100 this, SLOT(slotValidChanged()));
101 connect(m_d
->m_ui
.pathChooser
, SIGNAL(validChanged()),
102 this, SLOT(slotValidChanged()));
104 connect(m_d
->m_ui
.classLineEdit
, SIGNAL(validReturnPressed()),
105 this, SLOT(slotActivated()));
106 connect(m_d
->m_ui
.headerFileLineEdit
, SIGNAL(validReturnPressed()),
107 this, SLOT(slotActivated()));
108 connect(m_d
->m_ui
.sourceFileLineEdit
, SIGNAL(validReturnPressed()),
109 this, SLOT(slotActivated()));
110 connect(m_d
->m_ui
.formFileLineEdit
, SIGNAL(validReturnPressed()),
111 this, SLOT(slotActivated()));
112 connect(m_d
->m_ui
.formFileLineEdit
, SIGNAL(validReturnPressed()),
113 this, SLOT(slotActivated()));
114 connect(m_d
->m_ui
.pathChooser
, SIGNAL(returnPressed()),
115 this, SLOT(slotActivated()));
117 connect(m_d
->m_ui
.generateFormCheckBox
, SIGNAL(stateChanged(int)),
118 this, SLOT(slotFormInputChecked()));
120 m_d
->m_ui
.generateFormCheckBox
->setChecked(true);
121 setFormInputCheckable(false, true);
122 setClassType(NoClassType
);
125 NewClassWidget::~NewClassWidget()
130 void NewClassWidget::classNameEdited()
132 if (debugNewClassWidget
) {
133 qDebug() << Q_FUNC_INFO
<< m_d
->m_headerExtension
<< m_d
->m_sourceExtension
;
135 m_d
->m_classEdited
= true;
138 void NewClassWidget::suggestClassNameFromBase()
140 if (debugNewClassWidget
) {
141 qDebug() << Q_FUNC_INFO
<< m_d
->m_headerExtension
<< m_d
->m_sourceExtension
;
143 if (m_d
->m_classEdited
) {
146 // Suggest a class unless edited ("QMainWindow"->"MainWindow")
147 QString base
= baseClassName();
148 if (base
.startsWith(QLatin1Char('Q'))) {
154 QStringList
NewClassWidget::baseClassChoices() const
157 const int count
= m_d
->m_ui
.baseClassComboBox
->count();
159 for (int i
= 0; i
< count
; i
++) {
160 rc
.push_back(m_d
->m_ui
.baseClassComboBox
->itemText(i
));
165 void NewClassWidget::setBaseClassChoices(const QStringList
&choices
)
167 m_d
->m_ui
.baseClassComboBox
->clear();
168 m_d
->m_ui
.baseClassComboBox
->addItems(choices
);
171 void NewClassWidget::setBaseClassInputVisible(bool visible
)
173 m_d
->m_baseClassInputVisible
= visible
;
174 m_d
->m_ui
.baseClassLabel
->setVisible(visible
);
175 m_d
->m_ui
.baseClassComboBox
->setVisible(visible
);
178 void NewClassWidget::setBaseClassEditable(bool editable
)
180 m_d
->m_ui
.baseClassComboBox
->setEditable(editable
);
183 bool NewClassWidget::isBaseClassInputVisible() const
185 return m_d
->m_baseClassInputVisible
;
188 bool NewClassWidget::isBaseClassEditable() const
190 return m_d
->m_ui
.baseClassComboBox
->isEditable();
193 void NewClassWidget::setFormInputVisible(bool visible
)
195 m_d
->m_formInputVisible
= visible
;
196 m_d
->m_ui
.formLabel
->setVisible(visible
);
197 m_d
->m_ui
.formFileLineEdit
->setVisible(visible
);
200 bool NewClassWidget::isFormInputVisible() const
202 return m_d
->m_formInputVisible
;
205 void NewClassWidget::setFormInputCheckable(bool checkable
)
207 setFormInputCheckable(checkable
, false);
210 void NewClassWidget::setFormInputCheckable(bool checkable
, bool force
)
212 if (!force
&& checkable
== m_d
->m_formInputCheckable
) {
215 m_d
->m_formInputCheckable
= checkable
;
216 m_d
->m_ui
.generateFormLabel
->setVisible(checkable
);
217 m_d
->m_ui
.generateFormCheckBox
->setVisible(checkable
);
220 void NewClassWidget::setFormInputChecked(bool v
)
222 m_d
->m_ui
.generateFormCheckBox
->setChecked(v
);
225 bool NewClassWidget::formInputCheckable() const
227 return m_d
->m_formInputCheckable
;
230 bool NewClassWidget::formInputChecked() const
232 return m_d
->m_ui
.generateFormCheckBox
->isChecked();
235 void NewClassWidget::slotFormInputChecked()
237 const bool checked
= formInputChecked();
239 m_d
->m_ui
.formLabel
->setEnabled(checked
);
240 m_d
->m_ui
.formFileLineEdit
->setEnabled(checked
);
243 void NewClassWidget::setPathInputVisible(bool visible
)
245 m_d
->m_pathInputVisible
= visible
;
246 m_d
->m_ui
.pathLabel
->setVisible(visible
);
247 m_d
->m_ui
.pathChooser
->setVisible(visible
);
250 bool NewClassWidget::isPathInputVisible() const
252 return m_d
->m_pathInputVisible
;
255 void NewClassWidget::setClassName(const QString
&suggestedName
)
257 if (debugNewClassWidget
) {
258 qDebug() << Q_FUNC_INFO
<< suggestedName
<< m_d
->m_headerExtension
<< m_d
->m_sourceExtension
;
260 m_d
->m_ui
.classLineEdit
->setText(ClassNameValidatingLineEdit::createClassName(suggestedName
));
263 QString
NewClassWidget::className() const
265 return m_d
->m_ui
.classLineEdit
->text();
268 QString
NewClassWidget::baseClassName() const
270 return m_d
->m_ui
.baseClassComboBox
->currentText();
273 void NewClassWidget::setBaseClassName(const QString
&c
)
275 const int index
= m_d
->m_ui
.baseClassComboBox
->findText(c
);
278 m_d
->m_ui
.baseClassComboBox
->setCurrentIndex(index
);
279 suggestClassNameFromBase();
283 QString
NewClassWidget::sourceFileName() const
285 return m_d
->m_ui
.sourceFileLineEdit
->text();
288 QString
NewClassWidget::headerFileName() const
290 return m_d
->m_ui
.headerFileLineEdit
->text();
293 QString
NewClassWidget::formFileName() const
295 return m_d
->m_ui
.formFileLineEdit
->text();
298 QString
NewClassWidget::path() const
300 return m_d
->m_ui
.pathChooser
->path();
303 void NewClassWidget::setPath(const QString
&path
)
305 m_d
->m_ui
.pathChooser
->setPath(path
);
308 bool NewClassWidget::namespacesEnabled() const
310 return m_d
->m_ui
.classLineEdit
->namespacesEnabled();
313 void NewClassWidget::setNamespacesEnabled(bool b
)
315 m_d
->m_ui
.classLineEdit
->setNamespacesEnabled(b
);
318 QString
NewClassWidget::sourceExtension() const
320 return m_d
->m_sourceExtension
;
323 void NewClassWidget::setSourceExtension(const QString
&e
)
325 if (debugNewClassWidget
) {
326 qDebug() << Q_FUNC_INFO
<< e
;
328 m_d
->m_sourceExtension
= fixSuffix(e
);
331 QString
NewClassWidget::headerExtension() const
333 return m_d
->m_headerExtension
;
336 void NewClassWidget::setHeaderExtension(const QString
&e
)
338 if (debugNewClassWidget
) {
339 qDebug() << Q_FUNC_INFO
<< e
;
341 m_d
->m_headerExtension
= fixSuffix(e
);
344 QString
NewClassWidget::formExtension() const
346 return m_d
->m_formExtension
;
349 void NewClassWidget::setFormExtension(const QString
&e
)
351 if (debugNewClassWidget
) {
352 qDebug() << Q_FUNC_INFO
<< e
;
354 m_d
->m_formExtension
= fixSuffix(e
);
357 bool NewClassWidget::allowDirectories() const
359 return m_d
->m_ui
.headerFileLineEdit
->allowDirectories();
362 void NewClassWidget::setAllowDirectories(bool v
)
364 // We keep all in sync
365 if (allowDirectories() != v
) {
366 m_d
->m_ui
.sourceFileLineEdit
->setAllowDirectories(v
);
367 m_d
->m_ui
.headerFileLineEdit
->setAllowDirectories(v
);
368 m_d
->m_ui
.formFileLineEdit
->setAllowDirectories(v
);
372 bool NewClassWidget::lowerCaseFiles() const
374 return m_d
->m_ui
.classLineEdit
->lowerCaseFileName();
377 void NewClassWidget::setLowerCaseFiles(bool v
)
379 m_d
->m_ui
.classLineEdit
->setLowerCaseFileName(v
);
382 NewClassWidget::ClassType
NewClassWidget::classType() const
384 return static_cast<ClassType
>(m_d
->m_ui
.classTypeComboBox
->currentIndex());
387 void NewClassWidget::setClassType(ClassType ct
)
389 m_d
->m_ui
.classTypeComboBox
->setCurrentIndex(ct
);
392 bool NewClassWidget::isClassTypeComboVisible() const
394 return m_d
->m_ui
.classTypeLabel
->isVisible();
397 void NewClassWidget::setClassTypeComboVisible(bool v
)
399 m_d
->m_ui
.classTypeLabel
->setVisible(v
);
400 m_d
->m_ui
.classTypeComboBox
->setVisible(v
);
403 void NewClassWidget::slotValidChanged()
405 const bool newValid
= isValid();
407 if (newValid
!= m_d
->m_valid
) {
408 m_d
->m_valid
= newValid
;
413 bool NewClassWidget::isValid(QString
*error
) const
415 if (!m_d
->m_ui
.classLineEdit
->isValid()) {
417 *error
= m_d
->m_ui
.classLineEdit
->errorMessage();
422 if (isBaseClassInputVisible() && isBaseClassEditable()) {
423 // TODO: Should this be a ClassNameValidatingComboBox?
424 QRegExp
classNameValidator(QLatin1String("[a-zA-Z_][a-zA-Z0-9_]*(::[a-zA-Z_][a-zA-Z0-9_]*)*"));
425 const QString baseClass
= m_d
->m_ui
.baseClassComboBox
->currentText().trimmed();
426 if (!baseClass
.isEmpty() && !classNameValidator
.exactMatch(baseClass
)) {
428 *error
= tr("Invalid base class name");
434 if (!m_d
->m_ui
.headerFileLineEdit
->isValid()) {
436 *error
= tr("Invalid header file name: '%1'").arg(m_d
->m_ui
.headerFileLineEdit
->errorMessage());
441 if (!m_d
->m_ui
.sourceFileLineEdit
->isValid()) {
443 *error
= tr("Invalid source file name: '%1'").arg(m_d
->m_ui
.sourceFileLineEdit
->errorMessage());
448 if (isFormInputVisible()) {
449 if (!m_d
->m_ui
.formFileLineEdit
->isValid()) {
451 *error
= tr("Invalid form file name: '%1'").arg(m_d
->m_ui
.formFileLineEdit
->errorMessage());
457 if (isPathInputVisible()) {
458 if (!m_d
->m_ui
.pathChooser
->isValid()) {
460 *error
= m_d
->m_ui
.pathChooser
->errorMessage();
468 void NewClassWidget::triggerUpdateFileNames()
470 m_d
->m_ui
.classLineEdit
->triggerChanged();
473 void NewClassWidget::slotUpdateFileNames(const QString
&baseName
)
475 if (debugNewClassWidget
) {
476 qDebug() << Q_FUNC_INFO
<< baseName
<< m_d
->m_headerExtension
<< m_d
->m_sourceExtension
;
478 const QChar dot
= QLatin1Char('.');
479 m_d
->m_ui
.sourceFileLineEdit
->setText(baseName
+ dot
+ m_d
->m_sourceExtension
);
480 m_d
->m_ui
.headerFileLineEdit
->setText(baseName
+ dot
+ m_d
->m_headerExtension
);
481 m_d
->m_ui
.formFileLineEdit
->setText(baseName
+ dot
+ m_d
->m_formExtension
);
484 void NewClassWidget::slotActivated()
491 QString
NewClassWidget::fixSuffix(const QString
&suffix
)
495 if (s
.startsWith(QLatin1Char('.'))) {
501 // Utility to add a suffix to a file unless the user specified one
502 static QString
ensureSuffix(QString f
, const QString
&extension
)
504 const QChar dot
= QLatin1Char('.');
506 if (f
.contains(dot
)) {
514 // If a non-empty name was passed, expand to directory and suffix
515 static QString
expandFileName(const QDir
&dir
, const QString name
, const QString
&extension
)
517 if (name
.isEmpty()) {
520 return dir
.absoluteFilePath(ensureSuffix(name
, extension
));
523 QStringList
NewClassWidget::files() const
526 const QDir dir
= QDir(path());
528 rc
.push_back(expandFileName(dir
, headerFileName(), headerExtension()));
529 rc
.push_back(expandFileName(dir
, sourceFileName(), sourceExtension()));
530 if (isFormInputVisible()) {
531 rc
.push_back(expandFileName(dir
, formFileName(), formExtension()));