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(page: new IntroPage);
60 addPage(page: new ClassInfoPage);
61 addPage(page: new CodeStylePage);
62 addPage(page: new OutputFilesPage);
63 addPage(page: new ConclusionPage);
64//! [0]
65
66 setPixmap(which: QWizard::BannerPixmap, pixmap: QPixmap(":/images/banner.png"));
67 setPixmap(which: QWizard::BackgroundPixmap, pixmap: QPixmap(":/images/background.png"));
68
69 setWindowTitle(tr(s: "Class Wizard"));
70//! [2]
71}
72//! [1] //! [2]
73
74//! [3]
75void ClassWizard::accept()
76//! [3] //! [4]
77{
78 QByteArray className = field(name: "className").toByteArray();
79 QByteArray baseClass = field(name: "baseClass").toByteArray();
80 QByteArray macroName = field(name: "macroName").toByteArray();
81 QByteArray baseInclude = field(name: "baseInclude").toByteArray();
82
83 QString outputDir = field(name: "outputDir").toString();
84 QString header = field(name: "header").toString();
85 QString implementation = field(name: "implementation").toString();
86//! [4]
87
88 QByteArray block;
89
90 if (field(name: "comment").toBool()) {
91 block += "/*\n";
92 block += " " + header.toLatin1() + '\n';
93 block += "*/\n";
94 block += '\n';
95 }
96 if (field(name: "protect").toBool()) {
97 block += "#ifndef " + macroName + '\n';
98 block += "#define " + macroName + '\n';
99 block += '\n';
100 }
101 if (field(name: "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(name: "qobjectMacro").toBool()) {
115 block += " Q_OBJECT\n";
116 block += '\n';
117 }
118 block += "public:\n";
119
120 if (field(name: "qobjectCtor").toBool()) {
121 block += " " + className + "(QObject *parent = nullptr);\n";
122 } else if (field(name: "qwidgetCtor").toBool()) {
123 block += " " + className + "(QWidget *parent = nullptr);\n";
124 } else if (field(name: "defaultCtor").toBool()) {
125 block += " " + className + "();\n";
126 if (field(name: "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(name: "protect").toBool()) {
136 block += '\n';
137 block += "#endif\n";
138 }
139
140 QFile headerFile(outputDir + '/' + header);
141 if (!headerFile.open(flags: QFile::WriteOnly | QFile::Text)) {
142 QMessageBox::warning(parent: nullptr, title: QObject::tr(s: "Simple Wizard"),
143 text: QObject::tr(s: "Cannot write file %1:\n%2")
144 .arg(a: headerFile.fileName())
145 .arg(a: headerFile.errorString()));
146 return;
147 }
148 headerFile.write(data: block);
149
150 block.clear();
151
152 if (field(name: "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(name: "qobjectCtor").toBool()) {
162 block += className + "::" + className + "(QObject *parent)\n";
163 block += " : " + baseClass + "(parent)\n";
164 block += "{\n";
165 block += "}\n";
166 } else if (field(name: "qwidgetCtor").toBool()) {
167 block += className + "::" + className + "(QWidget *parent)\n";
168 block += " : " + baseClass + "(parent)\n";
169 block += "{\n";
170 block += "}\n";
171 } else if (field(name: "defaultCtor").toBool()) {
172 block += className + "::" + className + "()\n";
173 block += "{\n";
174 block += " // missing code\n";
175 block += "}\n";
176
177 if (field(name: "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(flags: QFile::WriteOnly | QFile::Text)) {
198 QMessageBox::warning(parent: nullptr, title: QObject::tr(s: "Simple Wizard"),
199 text: QObject::tr(s: "Cannot write file %1:\n%2")
200 .arg(a: implementationFile.fileName())
201 .arg(a: implementationFile.errorString()));
202 return;
203 }
204 implementationFile.write(data: 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(s: "Introduction"));
217 setPixmap(which: QWizard::WatermarkPixmap, pixmap: QPixmap(":/images/watermark1.png"));
218
219 label = new QLabel(tr(s: "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(s: "Class Information"));
238 setSubTitle(tr(s: "Specify basic information about the class for which you "
239 "want to generate skeleton source code files."));
240 setPixmap(which: QWizard::LogoPixmap, pixmap: QPixmap(":/images/logo1.png"));
241
242//! [10]
243 classNameLabel = new QLabel(tr(s: "&Class name:"));
244 classNameLineEdit = new QLineEdit;
245 classNameLabel->setBuddy(classNameLineEdit);
246
247 baseClassLabel = new QLabel(tr(s: "B&ase class:"));
248 baseClassLineEdit = new QLineEdit;
249 baseClassLabel->setBuddy(baseClassLineEdit);
250
251 qobjectMacroCheckBox = new QCheckBox(tr(s: "Generate Q_OBJECT &macro"));
252
253//! [10]
254 groupBox = new QGroupBox(tr(s: "C&onstructor"));
255//! [9]
256
257 qobjectCtorRadioButton = new QRadioButton(tr(s: "&QObject-style constructor"));
258 qwidgetCtorRadioButton = new QRadioButton(tr(s: "Q&Widget-style constructor"));
259 defaultCtorRadioButton = new QRadioButton(tr(s: "&Default constructor"));
260 copyCtorCheckBox = new QCheckBox(tr(s: "&Generate copy constructor and "
261 "operator="));
262
263 defaultCtorRadioButton->setChecked(true);
264
265 connect(sender: defaultCtorRadioButton, signal: &QAbstractButton::toggled,
266 receiver: copyCtorCheckBox, slot: &QWidget::setEnabled);
267
268//! [11] //! [12]
269 registerField(name: "className*", widget: classNameLineEdit);
270 registerField(name: "baseClass", widget: baseClassLineEdit);
271 registerField(name: "qobjectMacro", widget: qobjectMacroCheckBox);
272//! [11]
273 registerField(name: "qobjectCtor", widget: qobjectCtorRadioButton);
274 registerField(name: "qwidgetCtor", widget: qwidgetCtorRadioButton);
275 registerField(name: "defaultCtor", widget: defaultCtorRadioButton);
276 registerField(name: "copyCtor", widget: 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, row: 0, column: 0);
288 layout->addWidget(classNameLineEdit, row: 0, column: 1);
289 layout->addWidget(baseClassLabel, row: 1, column: 0);
290 layout->addWidget(baseClassLineEdit, row: 1, column: 1);
291 layout->addWidget(qobjectMacroCheckBox, row: 2, column: 0, rowSpan: 1, columnSpan: 2);
292 layout->addWidget(groupBox, row: 3, column: 0, rowSpan: 1, columnSpan: 2);
293 setLayout(layout);
294//! [13]
295}
296//! [13]
297
298//! [14]
299CodeStylePage::CodeStylePage(QWidget *parent)
300 : QWizardPage(parent)
301{
302 setTitle(tr(s: "Code Style Options"));
303 setSubTitle(tr(s: "Choose the formatting of the generated code."));
304 setPixmap(which: QWizard::LogoPixmap, pixmap: QPixmap(":/images/logo2.png"));
305
306 commentCheckBox = new QCheckBox(tr(s: "&Start generated files with a "
307//! [14]
308 "comment"));
309 commentCheckBox->setChecked(true);
310
311 protectCheckBox = new QCheckBox(tr(s: "&Protect header file against multiple "
312 "inclusions"));
313 protectCheckBox->setChecked(true);
314
315 macroNameLabel = new QLabel(tr(s: "&Macro name:"));
316 macroNameLineEdit = new QLineEdit;
317 macroNameLabel->setBuddy(macroNameLineEdit);
318
319 includeBaseCheckBox = new QCheckBox(tr(s: "&Include base class definition"));
320 baseIncludeLabel = new QLabel(tr(s: "Base class include:"));
321 baseIncludeLineEdit = new QLineEdit;
322 baseIncludeLabel->setBuddy(baseIncludeLineEdit);
323
324 connect(sender: protectCheckBox, signal: &QAbstractButton::toggled,
325 receiver: macroNameLabel, slot: &QWidget::setEnabled);
326 connect(sender: protectCheckBox, signal: &QAbstractButton::toggled,
327 receiver: macroNameLineEdit, slot: &QWidget::setEnabled);
328 connect(sender: includeBaseCheckBox, signal: &QAbstractButton::toggled,
329 receiver: baseIncludeLabel, slot: &QWidget::setEnabled);
330 connect(sender: includeBaseCheckBox, signal: &QAbstractButton::toggled,
331 receiver: baseIncludeLineEdit, slot: &QWidget::setEnabled);
332
333 registerField(name: "comment", widget: commentCheckBox);
334 registerField(name: "protect", widget: protectCheckBox);
335 registerField(name: "macroName", widget: macroNameLineEdit);
336 registerField(name: "includeBase", widget: includeBaseCheckBox);
337 registerField(name: "baseInclude", widget: baseIncludeLineEdit);
338
339 QGridLayout *layout = new QGridLayout;
340 layout->setColumnMinimumWidth(column: 0, minSize: 20);
341 layout->addWidget(commentCheckBox, row: 0, column: 0, rowSpan: 1, columnSpan: 3);
342 layout->addWidget(protectCheckBox, row: 1, column: 0, rowSpan: 1, columnSpan: 3);
343 layout->addWidget(macroNameLabel, row: 2, column: 1);
344 layout->addWidget(macroNameLineEdit, row: 2, column: 2);
345 layout->addWidget(includeBaseCheckBox, row: 3, column: 0, rowSpan: 1, columnSpan: 3);
346 layout->addWidget(baseIncludeLabel, row: 4, column: 1);
347 layout->addWidget(baseIncludeLineEdit, row: 4, column: 2);
348//! [15]
349 setLayout(layout);
350}
351//! [15]
352
353//! [16]
354void CodeStylePage::initializePage()
355{
356 QString className = field(name: "className").toString();
357 macroNameLineEdit->setText(className.toUpper() + "_H");
358
359 QString baseClass = field(name: "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(subject: 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(s: "Output Files"));
381 setSubTitle(tr(s: "Specify where you want the wizard to put the generated "
382 "skeleton code."));
383 setPixmap(which: QWizard::LogoPixmap, pixmap: QPixmap(":/images/logo3.png"));
384
385 outputDirLabel = new QLabel(tr(s: "&Output directory:"));
386 outputDirLineEdit = new QLineEdit;
387 outputDirLabel->setBuddy(outputDirLineEdit);
388
389 headerLabel = new QLabel(tr(s: "&Header file name:"));
390 headerLineEdit = new QLineEdit;
391 headerLabel->setBuddy(headerLineEdit);
392
393 implementationLabel = new QLabel(tr(s: "&Implementation file name:"));
394 implementationLineEdit = new QLineEdit;
395 implementationLabel->setBuddy(implementationLineEdit);
396
397 registerField(name: "outputDir*", widget: outputDirLineEdit);
398 registerField(name: "header*", widget: headerLineEdit);
399 registerField(name: "implementation*", widget: implementationLineEdit);
400
401 QGridLayout *layout = new QGridLayout;
402 layout->addWidget(outputDirLabel, row: 0, column: 0);
403 layout->addWidget(outputDirLineEdit, row: 0, column: 1);
404 layout->addWidget(headerLabel, row: 1, column: 0);
405 layout->addWidget(headerLineEdit, row: 1, column: 1);
406 layout->addWidget(implementationLabel, row: 2, column: 0);
407 layout->addWidget(implementationLineEdit, row: 2, column: 1);
408 setLayout(layout);
409}
410
411//! [17]
412void OutputFilesPage::initializePage()
413{
414 QString className = field(name: "className").toString();
415 headerLineEdit->setText(className.toLower() + ".h");
416 implementationLineEdit->setText(className.toLower() + ".cpp");
417 outputDirLineEdit->setText(QDir::toNativeSeparators(pathName: QDir::tempPath()));
418}
419//! [17]
420
421ConclusionPage::ConclusionPage(QWidget *parent)
422 : QWizardPage(parent)
423{
424 setTitle(tr(s: "Conclusion"));
425 setPixmap(which: QWizard::WatermarkPixmap, pixmap: 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(which: QWizard::FinishButton);
438 finishText.remove(c: '&');
439 label->setText(tr(s: "Click %1 to generate the class skeleton.")
440 .arg(a: finishText));
441}
442

source code of qtbase/examples/widgets/dialogs/classwizard/classwizard.cpp