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