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] |
56 | ClassWizard::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] |
75 | void 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 = 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 (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] |
213 | IntroPage::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] |
233 | ClassInfoPage::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 ¯o" )); |
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] |
299 | CodeStylePage::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] |
354 | void 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 | |
377 | OutputFilesPage::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] |
412 | void 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 | |
421 | ConclusionPage::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 | |
435 | void 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 | |