1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include <QtWidgets>
52
53#include "classwizard.h"
54
55//! [0] //! [1]
56ClassWizard::ClassWizard(QWidget *parent)
57 : QWizard(parent)
58{
59 addPage(new IntroPage);
60 addPage(new ClassInfoPage);
61 addPage(new CodeStylePage);
62 addPage(new OutputFilesPage);
63 addPage(new ConclusionPage);
64//! [0]
65
66 setPixmap(QWizard::BannerPixmap, QPixmap(":/images/banner.png"));
67 setPixmap(QWizard::BackgroundPixmap, QPixmap(":/images/background.png"));
68
69 setWindowTitle(tr("Class Wizard"));
70//! [2]
71}
72//! [1] //! [2]
73
74//! [3]
75void ClassWizard::accept()
76//! [3] //! [4]
77{
78 QByteArray className = field("className").toByteArray();
79 QByteArray baseClass = field("baseClass").toByteArray();
80 QByteArray macroName = field("macroName").toByteArray();
81 QByteArray baseInclude = field("baseInclude").toByteArray();
82
83 QString outputDir = field("outputDir").toString();
84 QString header = field("header").toString();
85 QString implementation = field("implementation").toString();
86//! [4]
87
88 QByteArray block;
89
90 if (field("comment").toBool()) {
91 block += "/*\n";
92 block += " " + header.toLatin1() + '\n';
93 block += "*/\n";
94 block += '\n';
95 }
96 if (field("protect").toBool()) {
97 block += "#ifndef " + macroName + '\n';
98 block += "#define " + macroName + '\n';
99 block += '\n';
100 }
101 if (field("includeBase").toBool()) {
102 block += "#include " + baseInclude + '\n';
103 block += '\n';
104 }
105
106 block += "class " + className;
107 if (!baseClass.isEmpty())
108 block += " : public " + baseClass;
109 block += '\n';
110 block += "{\n";
111
112 /* qmake ignore Q_OBJECT */
113
114 if (field("qobjectMacro").toBool()) {
115 block += " Q_OBJECT\n";
116 block += '\n';
117 }
118 block += "public:\n";
119
120 if (field("qobjectCtor").toBool()) {
121 block += " " + className + "(QObject *parent = nullptr);\n";
122 } else if (field("qwidgetCtor").toBool()) {
123 block += " " + className + "(QWidget *parent = nullptr);\n";
124 } else if (field("defaultCtor").toBool()) {
125 block += " " + className + "();\n";
126 if (field("copyCtor").toBool()) {
127 block += " " + className + "(const " + className + " &other);\n";
128 block += '\n';
129 block += " " + className + " &operator=" + "(const " + className
130 + " &other);\n";
131 }
132 }
133 block += "};\n";
134
135 if (field("protect").toBool()) {
136 block += '\n';
137 block += "#endif\n";
138 }
139
140 QFile headerFile(outputDir + '/' + header);
141 if (!headerFile.open(QFile::WriteOnly | QFile::Text)) {
142 QMessageBox::warning(nullptr, QObject::tr("Simple Wizard"),
143 QObject::tr("Cannot write file %1:\n%2")
144 .arg(headerFile.fileName())
145 .arg(headerFile.errorString()));
146 return;
147 }
148 headerFile.write(block);
149
150 block.clear();
151
152 if (field("comment").toBool()) {
153 block += "/*\n";
154 block += " " + implementation.toLatin1() + '\n';
155 block += "*/\n";
156 block += '\n';
157 }
158 block += "#include \"" + header.toLatin1() + "\"\n";
159 block += '\n';
160
161 if (field("qobjectCtor").toBool()) {
162 block += className + "::" + className + "(QObject *parent)\n";
163 block += " : " + baseClass + "(parent)\n";
164 block += "{\n";
165 block += "}\n";
166 } else if (field("qwidgetCtor").toBool()) {
167 block += className + "::" + className + "(QWidget *parent)\n";
168 block += " : " + baseClass + "(parent)\n";
169 block += "{\n";
170 block += "}\n";
171 } else if (field("defaultCtor").toBool()) {
172 block += className + "::" + className + "()\n";
173 block += "{\n";
174 block += " // missing code\n";
175 block += "}\n";
176
177 if (field("copyCtor").toBool()) {
178 block += "\n";
179 block += className + "::" + className + "(const " + className
180 + " &other)\n";
181 block += "{\n";
182 block += " *this = other;\n";
183 block += "}\n";
184 block += '\n';
185 block += className + " &" + className + "::operator=(const "
186 + className + " &other)\n";
187 block += "{\n";
188 if (!baseClass.isEmpty())
189 block += " " + baseClass + "::operator=(other);\n";
190 block += " // missing code\n";
191 block += " return *this;\n";
192 block += "}\n";
193 }
194 }
195
196 QFile implementationFile(outputDir + '/' + implementation);
197 if (!implementationFile.open(QFile::WriteOnly | QFile::Text)) {
198 QMessageBox::warning(nullptr, QObject::tr("Simple Wizard"),
199 QObject::tr("Cannot write file %1:\n%2")
200 .arg(implementationFile.fileName())
201 .arg(implementationFile.errorString()));
202 return;
203 }
204 implementationFile.write(block);
205
206//! [5]
207 QDialog::accept();
208//! [5] //! [6]
209}
210//! [6]
211
212//! [7]
213IntroPage::IntroPage(QWidget *parent)
214 : QWizardPage(parent)
215{
216 setTitle(tr("Introduction"));
217 setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/watermark1.png"));
218
219 label = new QLabel(tr("This wizard will generate a skeleton C++ class "
220 "definition, including a few functions. You simply "
221 "need to specify the class name and set a few "
222 "options to produce a header file and an "
223 "implementation file for your new C++ class."));
224 label->setWordWrap(true);
225
226 QVBoxLayout *layout = new QVBoxLayout;
227 layout->addWidget(label);
228 setLayout(layout);
229}
230//! [7]
231
232//! [8] //! [9]
233ClassInfoPage::ClassInfoPage(QWidget *parent)
234 : QWizardPage(parent)
235{
236//! [8]
237 setTitle(tr("Class Information"));
238 setSubTitle(tr("Specify basic information about the class for which you "
239 "want to generate skeleton source code files."));
240 setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo1.png"));
241
242//! [10]
243 classNameLabel = new QLabel(tr("&Class name:"));
244 classNameLineEdit = new QLineEdit;
245 classNameLabel->setBuddy(classNameLineEdit);
246
247 baseClassLabel = new QLabel(tr("B&ase class:"));
248 baseClassLineEdit = new QLineEdit;
249 baseClassLabel->setBuddy(baseClassLineEdit);
250
251 qobjectMacroCheckBox = new QCheckBox(tr("Generate Q_OBJECT &macro"));
252
253//! [10]
254 groupBox = new QGroupBox(tr("C&onstructor"));
255//! [9]
256
257 qobjectCtorRadioButton = new QRadioButton(tr("&QObject-style constructor"));
258 qwidgetCtorRadioButton = new QRadioButton(tr("Q&Widget-style constructor"));
259 defaultCtorRadioButton = new QRadioButton(tr("&Default constructor"));
260 copyCtorCheckBox = new QCheckBox(tr("&Generate copy constructor and "
261 "operator="));
262
263 defaultCtorRadioButton->setChecked(true);
264
265 connect(defaultCtorRadioButton, &QAbstractButton::toggled,
266 copyCtorCheckBox, &QWidget::setEnabled);
267
268//! [11] //! [12]
269 registerField("className*", classNameLineEdit);
270 registerField("baseClass", baseClassLineEdit);
271 registerField("qobjectMacro", qobjectMacroCheckBox);
272//! [11]
273 registerField("qobjectCtor", qobjectCtorRadioButton);
274 registerField("qwidgetCtor", qwidgetCtorRadioButton);
275 registerField("defaultCtor", defaultCtorRadioButton);
276 registerField("copyCtor", copyCtorCheckBox);
277
278 QVBoxLayout *groupBoxLayout = new QVBoxLayout;
279//! [12]
280 groupBoxLayout->addWidget(qobjectCtorRadioButton);
281 groupBoxLayout->addWidget(qwidgetCtorRadioButton);
282 groupBoxLayout->addWidget(defaultCtorRadioButton);
283 groupBoxLayout->addWidget(copyCtorCheckBox);
284 groupBox->setLayout(groupBoxLayout);
285
286 QGridLayout *layout = new QGridLayout;
287 layout->addWidget(classNameLabel, 0, 0);
288 layout->addWidget(classNameLineEdit, 0, 1);
289 layout->addWidget(baseClassLabel, 1, 0);
290 layout->addWidget(baseClassLineEdit, 1, 1);
291 layout->addWidget(qobjectMacroCheckBox, 2, 0, 1, 2);
292 layout->addWidget(groupBox, 3, 0, 1, 2);
293 setLayout(layout);
294//! [13]
295}
296//! [13]
297
298//! [14]
299CodeStylePage::CodeStylePage(QWidget *parent)
300 : QWizardPage(parent)
301{
302 setTitle(tr("Code Style Options"));
303 setSubTitle(tr("Choose the formatting of the generated code."));
304 setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo2.png"));
305
306 commentCheckBox = new QCheckBox(tr("&Start generated files with a "
307//! [14]
308 "comment"));
309 commentCheckBox->setChecked(true);
310
311 protectCheckBox = new QCheckBox(tr("&Protect header file against multiple "
312 "inclusions"));
313 protectCheckBox->setChecked(true);
314
315 macroNameLabel = new QLabel(tr("&Macro name:"));
316 macroNameLineEdit = new QLineEdit;
317 macroNameLabel->setBuddy(macroNameLineEdit);
318
319 includeBaseCheckBox = new QCheckBox(tr("&Include base class definition"));
320 baseIncludeLabel = new QLabel(tr("Base class include:"));
321 baseIncludeLineEdit = new QLineEdit;
322 baseIncludeLabel->setBuddy(baseIncludeLineEdit);
323
324 connect(protectCheckBox, &QAbstractButton::toggled,
325 macroNameLabel, &QWidget::setEnabled);
326 connect(protectCheckBox, &QAbstractButton::toggled,
327 macroNameLineEdit, &QWidget::setEnabled);
328 connect(includeBaseCheckBox, &QAbstractButton::toggled,
329 baseIncludeLabel, &QWidget::setEnabled);
330 connect(includeBaseCheckBox, &QAbstractButton::toggled,
331 baseIncludeLineEdit, &QWidget::setEnabled);
332
333 registerField("comment", commentCheckBox);
334 registerField("protect", protectCheckBox);
335 registerField("macroName", macroNameLineEdit);
336 registerField("includeBase", includeBaseCheckBox);
337 registerField("baseInclude", baseIncludeLineEdit);
338
339 QGridLayout *layout = new QGridLayout;
340 layout->setColumnMinimumWidth(0, 20);
341 layout->addWidget(commentCheckBox, 0, 0, 1, 3);
342 layout->addWidget(protectCheckBox, 1, 0, 1, 3);
343 layout->addWidget(macroNameLabel, 2, 1);
344 layout->addWidget(macroNameLineEdit, 2, 2);
345 layout->addWidget(includeBaseCheckBox, 3, 0, 1, 3);
346 layout->addWidget(baseIncludeLabel, 4, 1);
347 layout->addWidget(baseIncludeLineEdit, 4, 2);
348//! [15]
349 setLayout(layout);
350}
351//! [15]
352
353//! [16]
354void CodeStylePage::initializePage()
355{
356 QString className = field("className").toString();
357 macroNameLineEdit->setText(className.toUpper() + "_H");
358
359 QString baseClass = field("baseClass").toString();
360
361 includeBaseCheckBox->setChecked(!baseClass.isEmpty());
362 includeBaseCheckBox->setEnabled(!baseClass.isEmpty());
363 baseIncludeLabel->setEnabled(!baseClass.isEmpty());
364 baseIncludeLineEdit->setEnabled(!baseClass.isEmpty());
365
366 QRegularExpression rx("Q[A-Z].*");
367 if (baseClass.isEmpty()) {
368 baseIncludeLineEdit->clear();
369 } else if (rx.match(baseClass).hasMatch()) {
370 baseIncludeLineEdit->setText('<' + baseClass + '>');
371 } else {
372 baseIncludeLineEdit->setText('"' + baseClass.toLower() + ".h\"");
373 }
374}
375//! [16]
376
377OutputFilesPage::OutputFilesPage(QWidget *parent)
378 : QWizardPage(parent)
379{
380 setTitle(tr("Output Files"));
381 setSubTitle(tr("Specify where you want the wizard to put the generated "
382 "skeleton code."));
383 setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo3.png"));
384
385 outputDirLabel = new QLabel(tr("&Output directory:"));
386 outputDirLineEdit = new QLineEdit;
387 outputDirLabel->setBuddy(outputDirLineEdit);
388
389 headerLabel = new QLabel(tr("&Header file name:"));
390 headerLineEdit = new QLineEdit;
391 headerLabel->setBuddy(headerLineEdit);
392
393 implementationLabel = new QLabel(tr("&Implementation file name:"));
394 implementationLineEdit = new QLineEdit;
395 implementationLabel->setBuddy(implementationLineEdit);
396
397 registerField("outputDir*", outputDirLineEdit);
398 registerField("header*", headerLineEdit);
399 registerField("implementation*", implementationLineEdit);
400
401 QGridLayout *layout = new QGridLayout;
402 layout->addWidget(outputDirLabel, 0, 0);
403 layout->addWidget(outputDirLineEdit, 0, 1);
404 layout->addWidget(headerLabel, 1, 0);
405 layout->addWidget(headerLineEdit, 1, 1);
406 layout->addWidget(implementationLabel, 2, 0);
407 layout->addWidget(implementationLineEdit, 2, 1);
408 setLayout(layout);
409}
410
411//! [17]
412void OutputFilesPage::initializePage()
413{
414 QString className = field("className").toString();
415 headerLineEdit->setText(className.toLower() + ".h");
416 implementationLineEdit->setText(className.toLower() + ".cpp");
417 outputDirLineEdit->setText(QDir::toNativeSeparators(QDir::tempPath()));
418}
419//! [17]
420
421ConclusionPage::ConclusionPage(QWidget *parent)
422 : QWizardPage(parent)
423{
424 setTitle(tr("Conclusion"));
425 setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/watermark2.png"));
426
427 label = new QLabel;
428 label->setWordWrap(true);
429
430 QVBoxLayout *layout = new QVBoxLayout;
431 layout->addWidget(label);
432 setLayout(layout);
433}
434
435void ConclusionPage::initializePage()
436{
437 QString finishText = wizard()->buttonText(QWizard::FinishButton);
438 finishText.remove('&');
439 label->setText(tr("Click %1 to generate the class skeleton.")
440 .arg(finishText));
441}
442