aboutsummaryrefslogtreecommitdiffstats
path: root/examples/widgets/dialogs/classwizard/classwizard.py
diff options
context:
space:
mode:
Diffstat (limited to 'examples/widgets/dialogs/classwizard/classwizard.py')
-rw-r--r--examples/widgets/dialogs/classwizard/classwizard.py628
1 files changed, 302 insertions, 326 deletions
diff --git a/examples/widgets/dialogs/classwizard/classwizard.py b/examples/widgets/dialogs/classwizard/classwizard.py
index fc2feb498..0efbde69f 100644
--- a/examples/widgets/dialogs/classwizard/classwizard.py
+++ b/examples/widgets/dialogs/classwizard/classwizard.py
@@ -1,404 +1,380 @@
-# -*- coding: utf-8 -*-
-#############################################################################
-##
-## Copyright (C) 2013 Riverbank Computing Limited.
-## Copyright (C) 2016 The Qt Company Ltd.
-## Contact: http://www.qt.io/licensing/
-##
-## This file is part of the Qt for Python examples of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:BSD$
-## You may use this file under the terms of the BSD license as follows:
-##
-## "Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are
-## met:
-## * Redistributions of source code must retain the above copyright
-## notice, this list of conditions and the following disclaimer.
-## * Redistributions in binary form must reproduce the above copyright
-## notice, this list of conditions and the following disclaimer in
-## the documentation and/or other materials provided with the
-## distribution.
-## * Neither the name of The Qt Company Ltd nor the names of its
-## contributors may be used to endorse or promote products derived
-## from this software without specific prior written permission.
-##
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-from __future__ import unicode_literals
-from PySide2 import QtCore, QtGui, QtWidgets
-
-import classwizard_rc
-
-
-class ClassWizard(QtWidgets.QWizard):
- def __init__(self, parent=None):
- super(ClassWizard, self).__init__(parent)
+# Copyright (C) 2013 Riverbank Computing Limited.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
- self.addPage(IntroPage())
- self.addPage(ClassInfoPage())
- self.addPage(CodeStylePage())
- self.addPage(OutputFilesPage())
- self.addPage(ConclusionPage())
+import os
+from pathlib import Path
+import sys
- self.setPixmap(QtWidgets.QWizard.BannerPixmap,
- QtGui.QPixmap(':/images/banner.png'))
- self.setPixmap(QtWidgets.QWizard.BackgroundPixmap,
- QtGui.QPixmap(':/images/background.png'))
+from PySide6.QtCore import QDir, QFileInfo, QUrl, Slot
+from PySide6.QtGui import QDesktopServices, QPixmap
+from PySide6.QtWidgets import (QApplication, QComboBox, QCheckBox, QFormLayout,
+ QFileDialog, QHBoxLayout, QLabel, QLineEdit,
+ QMessageBox, QToolButton, QVBoxLayout, QWizard,
+ QWizardPage)
- self.setWindowTitle("Class Wizard")
+from listchooser import PropertyChooser, SignalChooser
- def accept(self):
- className = self.field('className')
- baseClass = self.field('baseClass')
- macroName = self.field('macroName')
- baseInclude = self.field('baseInclude')
+import classwizard_rc # noqa: F401
- outputDir = self.field('outputDir')
- header = self.field('header')
- implementation = self.field('implementation')
- block = ''
+BASE_CLASSES = ['<None>', 'PySide6.QtCore.QObject',
+ 'PySide6.QtWidgets.QDialog', 'PySide6.QtWidgets.QMainWindow',
+ 'PySide6.QtWidgets.QWidget']
- if self.field('comment'):
- block += '/*\n'
- block += ' ' + header + '\n'
- block += '*/\n'
- block += '\n'
- if self.field('protect'):
- block += '#ifndef ' + macroName + '\n'
- block += '#define ' + macroName + '\n'
- block += '\n'
+PYTHON_TYPES = ['int', 'list', 'str']
- if self.field('includeBase'):
- block += '#include ' + baseInclude + '\n'
- block += '\n'
- block += 'class ' + className
- if baseClass:
- block += ' : public ' + baseClass
+INTRODUCTION = ("This wizard will generate a skeleton Python class definition, "
+ "including a few functions. You simply need to specify the class name and set "
+ "a few options to produce a Python file.")
- block += '\n'
- block += '{\n'
- if self.field('qobjectMacro'):
- block += ' Q_OBJECT\n'
- block += '\n'
+def property_accessors(property_type, name):
+ """Generate the property accessor functions."""
+ return (f' @Property({property_type})\n'
+ f' def {name}(self):\n'
+ f' return self._{name}\n\n'
+ f' @{name}.setter\n'
+ f' def {name}(self, value):\n'
+ f' self._{name} = value\n')
- block += 'public:\n'
- if self.field('qobjectCtor'):
- block += ' ' + className + '(QObject *parent = 0);\n'
- elif self.field('qwidgetCtor'):
- block += ' ' + className + '(QWidget *parent = 0);\n'
- elif self.field('defaultCtor'):
- block += ' ' + className + '();\n'
+def property_initialization(property_type, name):
+ """Generate the property initialization for __init__()."""
+ return f' self._{name} = {property_type}()\n'
- if self.field('copyCtor'):
- block += ' ' + className + '(const ' + className + ' &other);\n'
- block += '\n'
- block += ' ' + className + ' &operator=' + '(const ' + className + ' &other);\n'
- block += '};\n'
+def signal_initialization(signature):
+ """Generate the Signal initialization from the function signature."""
+ paren_pos = signature.find('(')
+ name = signature[:paren_pos]
+ parameters = signature[paren_pos:]
+ return f' {name} = Signal{parameters}\n'
- if self.field('protect'):
- block += '\n'
- block += '#endif\n'
- headerFile = QtCore.QFile(outputDir + '/' + header)
+class ClassWizard(QWizard):
+ def __init__(self, parent=None):
+ super().__init__(parent)
- if not headerFile.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text):
- QtWidgets.QMessageBox.warning(None, "Class Wizard",
- "Cannot write file %s:\n%s" % (headerFile.fileName(), headerFile.errorString()))
- return
+ self.addPage(IntroPage())
+ self._class_info_index = self.addPage(ClassInfoPage())
+ self._qobject_index = self.addPage(QObjectPage())
+ self._output_index = self.addPage(OutputFilesPage())
+ self.addPage(ConclusionPage())
- headerFile.write(QtCore.QByteArray(block.encode("utf-8")))
+ self.setPixmap(QWizard.BannerPixmap,
+ QPixmap(':/images/banner.png'))
+ self.setPixmap(QWizard.BackgroundPixmap,
+ QPixmap(':/images/background.png'))
- block = ''
+ self.setWindowTitle("Class Wizard")
- if self.field('comment'):
- block += '/*\n'
- block += ' ' + implementation + '\n'
- block += '*/\n'
+ def nextId(self):
+ """Overrides QWizard.nextId() to insert the property/signal
+ page in case the class is a QObject."""
+ idx = self.currentId()
+ if idx == self._class_info_index:
+ qobject = self.field('qobject')
+ return self._qobject_index if qobject else self._output_index
+ return super(ClassWizard, self).nextId()
+
+ def generate_code(self):
+ imports = [] # Classes to be imported
+ module_imports = {} # Module->class list
+
+ def add_import(class_str):
+ """Add a class to the import list or module hash depending on
+ whether it is 'class' or 'module.class'. Returns the
+ class name."""
+ dot = class_str.rfind('.')
+ if dot < 0:
+ imports.append(class_str)
+ return class_str
+ module = class_str[0:dot]
+ class_name = class_str[dot + 1:]
+ class_list = module_imports.get(module)
+ if class_list:
+ if class_name not in class_list:
+ class_list.append(class_name)
+ else:
+ module_imports[module] = [class_name]
+ return class_name
+
+ class_name = self.field('className')
+ qobject = self.field('qobject')
+ base_class = self.field('baseClass')
+ if base_class.startswith('<'): # <None>
+ base_class = ''
+ if qobject and not base_class:
+ base_class = 'PySide6.QtCore.QObject'
+
+ if base_class:
+ base_class = add_import(base_class)
+
+ signals = self.field('signals')
+ if signals:
+ add_import('PySide6.QtCore.Signal')
+
+ property_types = []
+ property_names = []
+ for p in self.field('properties'):
+ property_type, property_name = str(p).split(' ')
+ if property_type not in PYTHON_TYPES:
+ property_type = add_import(property_type)
+ property_types.append(property_type)
+ property_names.append(property_name)
+
+ if property_names:
+ add_import('PySide6.QtCore.Property')
+
+ signals = self.field('signals')
+ if signals:
+ add_import('PySide6.QtCore.Signal')
+
+ property_types = []
+ property_names = []
+ for p in self.field('properties'):
+ property_type, property_name = str(p).split(' ')
+ if property_type not in PYTHON_TYPES:
+ property_type = add_import(property_type)
+ property_types.append(property_type)
+ property_names.append(property_name)
+
+ if property_names:
+ add_import('PySide6.QtCore.Property')
+
+ # Generate imports
+ block = '# This Python file uses the following encoding: utf-8\n\n'
+ for module, class_list in module_imports.items():
+ class_list.sort()
+ class_list_str = ', '.join(class_list)
+ block += f'from {module} import {class_list_str}\n'
+ for klass in imports:
+ block += f'import {klass}\n'
+
+ # Generate class definition
+ block += f'\n\nclass {class_name}'
+ if base_class:
+ block += f'({base_class})'
+ block += ':\n'
+ description = self.field('description')
+ if description:
+ block += f' """{description}"""\n'
+
+ if signals:
block += '\n'
+ for s in signals:
+ block += signal_initialization(str(s))
+
+ # Generate __init__ function
+ block += '\n def __init__(self'
+ if qobject:
+ block += ', parent=None'
+ block += '):\n'
+
+ if base_class:
+ block += ' super().__init__('
+ if qobject:
+ block += 'parent'
+ block += ')\n'
+
+ for i, name in enumerate(property_names):
+ block += property_initialization(property_types[i], name)
+
+ if not base_class and not property_names:
+ block += ' pass\n'
- block += '#include "' + header + '"\n'
- block += '\n'
-
- if self.field('qobjectCtor'):
- block += className + '::' + className + '(QObject *parent)\n'
- block += ' : ' + baseClass + '(parent)\n'
- block += '{\n'
- block += '}\n'
- elif self.field('qwidgetCtor'):
- block += className + '::' + className + '(QWidget *parent)\n'
- block += ' : ' + baseClass + '(parent)\n'
- block += '{\n'
- block += '}\n'
- elif self.field('defaultCtor'):
- block += className + '::' + className + '()\n'
- block += '{\n'
- block += ' // missing code\n'
- block += '}\n'
-
- if self.field('copyCtor'):
- block += '\n'
- block += className + '::' + className + '(const ' + className + ' &other)\n'
- block += '{\n'
- block += ' *this = other;\n'
- block += '}\n'
- block += '\n'
- block += className + ' &' + className + '::operator=(const ' + className + ' &other)\n'
- block += '{\n'
-
- if baseClass:
- block += ' ' + baseClass + '::operator=(other);\n'
-
- block += ' // missing code\n'
- block += ' return *this;\n'
- block += '}\n'
-
- implementationFile = QtCore.QFile(outputDir + '/' + implementation)
-
- if not implementationFile.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text):
- QtWidgets.QMessageBox.warning(None, "Class Wizard",
- "Cannot write file %s:\n%s" % (implementationFile.fileName(), implementationFile.errorString()))
+ # Generate property accessors
+ for i, name in enumerate(property_names):
+ block += '\n' + property_accessors(property_types[i], name)
+
+ return block
+
+ def accept(self):
+ file_name = self.field('file')
+ output_dir = self.field('outputDir')
+ python_file = Path(output_dir) / file_name
+ name = os.fspath(python_file)
+ try:
+ python_file.write_text(self.generate_code())
+ except (OSError, PermissionError) as e:
+ reason = str(e)
+ QMessageBox.warning(None, "Class Wizard",
+ f"Cannot write file {name}:\n{reason}")
return
- implementationFile.write(QtCore.QByteArray(block.encode("utf-8")))
+ if self.field('launch'):
+ url = QUrl.fromLocalFile(QDir.fromNativeSeparators(name))
+ QDesktopServices.openUrl(url)
super(ClassWizard, self).accept()
-class IntroPage(QtWidgets.QWizardPage):
+class IntroPage(QWizardPage):
def __init__(self, parent=None):
- super(IntroPage, self).__init__(parent)
+ super().__init__(parent)
self.setTitle("Introduction")
- self.setPixmap(QtWidgets.QWizard.WatermarkPixmap,
- QtGui.QPixmap(':/images/watermark1.png'))
-
- label = QtWidgets.QLabel("This wizard will generate a skeleton C++ class "
- "definition, including a few functions. You simply need to "
- "specify the class name and set a few options to produce a "
- "header file and an implementation file for your new C++ "
- "class.")
+ self.setPixmap(QWizard.WatermarkPixmap,
+ QPixmap(':/images/watermark1.png'))
+
+ label = QLabel(INTRODUCTION)
label.setWordWrap(True)
- layout = QtWidgets.QVBoxLayout()
+ layout = QVBoxLayout(self)
layout.addWidget(label)
- self.setLayout(layout)
-class ClassInfoPage(QtWidgets.QWizardPage):
+class ClassInfoPage(QWizardPage):
def __init__(self, parent=None):
- super(ClassInfoPage, self).__init__(parent)
+ super().__init__(parent)
self.setTitle("Class Information")
self.setSubTitle("Specify basic information about the class for "
- "which you want to generate skeleton source code files.")
- self.setPixmap(QtWidgets.QWizard.LogoPixmap,
- QtGui.QPixmap(':/images/logo1.png'))
+ "which you want to generate a skeleton source code file.")
+ self.setPixmap(QWizard.LogoPixmap,
+ QPixmap(':/qt-project.org/logos/pysidelogo.png'))
- classNameLabel = QtWidgets.QLabel("&Class name:")
- classNameLineEdit = QtWidgets.QLineEdit()
- classNameLabel.setBuddy(classNameLineEdit)
+ class_name_line_edit = QLineEdit()
+ class_name_line_edit.setClearButtonEnabled(True)
- baseClassLabel = QtWidgets.QLabel("B&ase class:")
- baseClassLineEdit = QtWidgets.QLineEdit()
- baseClassLabel.setBuddy(baseClassLineEdit)
+ self._base_class_combo = QComboBox()
+ self._base_class_combo.addItems(BASE_CLASSES)
+ self._base_class_combo.setEditable(True)
- qobjectMacroCheckBox = QtWidgets.QCheckBox("Generate Q_OBJECT &macro")
+ base_class_line_edit = self._base_class_combo.lineEdit()
+ base_class_line_edit.setPlaceholderText('Module.Class')
+ self._base_class_combo.currentTextChanged.connect(self._base_class_changed)
- groupBox = QtWidgets.QGroupBox("C&onstructor")
+ description_line_edit = QLineEdit()
+ description_line_edit.setClearButtonEnabled(True)
- qobjectCtorRadioButton = QtWidgets.QRadioButton("&QObject-style constructor")
- qwidgetCtorRadioButton = QtWidgets.QRadioButton("Q&Widget-style constructor")
- defaultCtorRadioButton = QtWidgets.QRadioButton("&Default constructor")
- copyCtorCheckBox = QtWidgets.QCheckBox("&Generate copy constructor and operator=")
+ self._qobject_check_box = QCheckBox("Inherits QObject")
- defaultCtorRadioButton.setChecked(True)
+ self.registerField('className*', class_name_line_edit)
+ self.registerField('baseClass', base_class_line_edit)
+ self.registerField('description', description_line_edit)
+ self.registerField('qobject', self._qobject_check_box)
- defaultCtorRadioButton.toggled.connect(copyCtorCheckBox.setEnabled)
+ layout = QFormLayout(self)
+ layout.addRow("&Class name:", class_name_line_edit)
+ layout.addRow("B&ase class:", self._base_class_combo)
+ layout.addRow("&Description:", description_line_edit)
+ layout.addRow(self._qobject_check_box)
- self.registerField('className*', classNameLineEdit)
- self.registerField('baseClass', baseClassLineEdit)
- self.registerField('qobjectMacro', qobjectMacroCheckBox)
- self.registerField('qobjectCtor', qobjectCtorRadioButton)
- self.registerField('qwidgetCtor', qwidgetCtorRadioButton)
- self.registerField('defaultCtor', defaultCtorRadioButton)
- self.registerField('copyCtor', copyCtorCheckBox)
+ @Slot(str)
+ def _base_class_changed(self, text):
+ is_qobject = text.startswith('PySide')
+ self._qobject_check_box.setChecked(is_qobject)
- groupBoxLayout = QtWidgets.QVBoxLayout()
- groupBoxLayout.addWidget(qobjectCtorRadioButton)
- groupBoxLayout.addWidget(qwidgetCtorRadioButton)
- groupBoxLayout.addWidget(defaultCtorRadioButton)
- groupBoxLayout.addWidget(copyCtorCheckBox)
- groupBox.setLayout(groupBoxLayout)
- layout = QtWidgets.QGridLayout()
- layout.addWidget(classNameLabel, 0, 0)
- layout.addWidget(classNameLineEdit, 0, 1)
- layout.addWidget(baseClassLabel, 1, 0)
- layout.addWidget(baseClassLineEdit, 1, 1)
- layout.addWidget(qobjectMacroCheckBox, 2, 0, 1, 2)
- layout.addWidget(groupBox, 3, 0, 1, 2)
- self.setLayout(layout)
+class QObjectPage(QWizardPage):
+ """Allows for adding properties and signals to a QObject."""
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ self.setTitle("QObject parameters")
+ self.setSubTitle("Specify the signals, slots and properties.")
+ self.setPixmap(QWizard.LogoPixmap,
+ QPixmap(':/qt-project.org/logos/pysidelogo.png'))
+ layout = QVBoxLayout(self)
+ self._properties_chooser = PropertyChooser()
+ self.registerField('properties', self._properties_chooser, 'items')
+ layout.addWidget(self._properties_chooser)
+ self._signals_chooser = SignalChooser()
+ self.registerField('signals', self._signals_chooser, 'items')
+ layout.addWidget(self._signals_chooser)
+
+
+class OutputFilesPage(QWizardPage):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.setTitle("Output Files")
+ self.setSubTitle("Specify where you want the wizard to put the "
+ "generated skeleton code.")
+ self.setPixmap(QWizard.LogoPixmap,
+ QPixmap(':/qt-project.org/logos/pysidelogo.png'))
-class CodeStylePage(QtWidgets.QWizardPage):
- def __init__(self, parent=None):
- super(CodeStylePage, self).__init__(parent)
-
- self.setTitle("Code Style Options")
- self.setSubTitle("Choose the formatting of the generated code.")
- self.setPixmap(QtWidgets.QWizard.LogoPixmap,
- QtGui.QPixmap(':/images/logo2.png'))
-
- commentCheckBox = QtWidgets.QCheckBox("&Start generated files with a "
- "comment")
- commentCheckBox.setChecked(True)
-
- protectCheckBox = QtWidgets.QCheckBox("&Protect header file against "
- "multiple inclusions")
- protectCheckBox.setChecked(True)
-
- macroNameLabel = QtWidgets.QLabel("&Macro name:")
- self.macroNameLineEdit = QtWidgets.QLineEdit()
- macroNameLabel.setBuddy(self.macroNameLineEdit)
-
- self.includeBaseCheckBox = QtWidgets.QCheckBox("&Include base class "
- "definition")
- self.baseIncludeLabel = QtWidgets.QLabel("Base class include:")
- self.baseIncludeLineEdit = QtWidgets.QLineEdit()
- self.baseIncludeLabel.setBuddy(self.baseIncludeLineEdit)
-
- protectCheckBox.toggled.connect(macroNameLabel.setEnabled)
- protectCheckBox.toggled.connect(self.macroNameLineEdit.setEnabled)
- self.includeBaseCheckBox.toggled.connect(self.baseIncludeLabel.setEnabled)
- self.includeBaseCheckBox.toggled.connect(self.baseIncludeLineEdit.setEnabled)
-
- self.registerField('comment', commentCheckBox)
- self.registerField('protect', protectCheckBox)
- self.registerField('macroName', self.macroNameLineEdit)
- self.registerField('includeBase', self.includeBaseCheckBox)
- self.registerField('baseInclude', self.baseIncludeLineEdit)
-
- layout = QtWidgets.QGridLayout()
- layout.setColumnMinimumWidth(0, 20)
- layout.addWidget(commentCheckBox, 0, 0, 1, 3)
- layout.addWidget(protectCheckBox, 1, 0, 1, 3)
- layout.addWidget(macroNameLabel, 2, 1)
- layout.addWidget(self.macroNameLineEdit, 2, 2)
- layout.addWidget(self.includeBaseCheckBox, 3, 0, 1, 3)
- layout.addWidget(self.baseIncludeLabel, 4, 1)
- layout.addWidget(self.baseIncludeLineEdit, 4, 2)
- self.setLayout(layout)
+ output_dir_label = QLabel("&Output directory:")
+ output_dir_layout = QHBoxLayout()
+ self._output_dir_line_edit = QLineEdit()
+ output_dir_layout.addWidget(self._output_dir_line_edit)
+ output_dir_label.setBuddy(self._output_dir_line_edit)
+ output_dir_button = QToolButton()
+ output_dir_button.setText('...')
+ output_dir_button.clicked.connect(self._choose_output_dir)
+ output_dir_layout.addWidget(output_dir_button)
- def initializePage(self):
- className = self.field('className')
- self.macroNameLineEdit.setText(className.upper() + "_H")
+ self._file_line_edit = QLineEdit()
- baseClass = self.field('baseClass')
- is_baseClass = bool(baseClass)
+ self.registerField('outputDir*', self._output_dir_line_edit)
+ self.registerField('file*', self._file_line_edit)
- self.includeBaseCheckBox.setChecked(is_baseClass)
- self.includeBaseCheckBox.setEnabled(is_baseClass)
- self.baseIncludeLabel.setEnabled(is_baseClass)
- self.baseIncludeLineEdit.setEnabled(is_baseClass)
+ layout = QFormLayout(self)
+ layout.addRow(output_dir_label, output_dir_layout)
+ layout.addRow("&File name:", self._file_line_edit)
- if not is_baseClass:
- self.baseIncludeLineEdit.clear()
- elif QtCore.QRegExp('Q[A-Z].*').exactMatch(baseClass):
- self.baseIncludeLineEdit.setText('<' + baseClass + '>')
- else:
- self.baseIncludeLineEdit.setText('"' + baseClass.lower() + '.h"')
+ def initializePage(self):
+ class_name = self.field('className')
+ self._file_line_edit.setText(class_name.lower() + '.py')
+ self.set_output_dir(QDir.tempPath())
+ def set_output_dir(self, directory):
+ self._output_dir_line_edit.setText(QDir.toNativeSeparators(directory))
-class OutputFilesPage(QtWidgets.QWizardPage):
- def __init__(self, parent=None):
- super(OutputFilesPage, self).__init__(parent)
+ def output_dir(self):
+ return QDir.fromNativeSeparators(self._output_dir_line_edit.text())
- self.setTitle("Output Files")
- self.setSubTitle("Specify where you want the wizard to put the "
- "generated skeleton code.")
- self.setPixmap(QtWidgets.QWizard.LogoPixmap,
- QtGui.QPixmap(':/images/logo3.png'))
-
- outputDirLabel = QtWidgets.QLabel("&Output directory:")
- self.outputDirLineEdit = QtWidgets.QLineEdit()
- outputDirLabel.setBuddy(self.outputDirLineEdit)
-
- headerLabel = QtWidgets.QLabel("&Header file name:")
- self.headerLineEdit = QtWidgets.QLineEdit()
- headerLabel.setBuddy(self.headerLineEdit)
-
- implementationLabel = QtWidgets.QLabel("&Implementation file name:")
- self.implementationLineEdit = QtWidgets.QLineEdit()
- implementationLabel.setBuddy(self.implementationLineEdit)
-
- self.registerField('outputDir*', self.outputDirLineEdit)
- self.registerField('header*', self.headerLineEdit)
- self.registerField('implementation*', self.implementationLineEdit)
-
- layout = QtWidgets.QGridLayout()
- layout.addWidget(outputDirLabel, 0, 0)
- layout.addWidget(self.outputDirLineEdit, 0, 1)
- layout.addWidget(headerLabel, 1, 0)
- layout.addWidget(self.headerLineEdit, 1, 1)
- layout.addWidget(implementationLabel, 2, 0)
- layout.addWidget(self.implementationLineEdit, 2, 1)
- self.setLayout(layout)
+ def file_name(self):
+ return f"{self.output_dir()}/{self._file_line_edit.text()}"
- def initializePage(self):
- className = self.field('className')
- self.headerLineEdit.setText(className.lower() + '.h')
- self.implementationLineEdit.setText(className.lower() + '.cpp')
- self.outputDirLineEdit.setText(QtCore.QDir.toNativeSeparators(QtCore.QDir.tempPath()))
+ def _choose_output_dir(self):
+ directory = QFileDialog.getExistingDirectory(self, "Output Directory",
+ self.output_dir())
+ if directory:
+ self.set_output_dir(directory)
+ def validatePage(self):
+ """Ensure we do not overwrite existing files."""
+ name = self.file_name()
+ if QFileInfo.exists(name):
+ question = f'{name} already exists. Would you like to overwrite it?'
+ r = QMessageBox.question(self, 'File Exists', question)
+ if r != QMessageBox.Yes:
+ return False
+ return True
-class ConclusionPage(QtWidgets.QWizardPage):
+
+class ConclusionPage(QWizardPage):
def __init__(self, parent=None):
- super(ConclusionPage, self).__init__(parent)
+ super().__init__(parent)
self.setTitle("Conclusion")
- self.setPixmap(QtWidgets.QWizard.WatermarkPixmap,
- QtGui.QPixmap(':/images/watermark2.png'))
+ self.setPixmap(QWizard.WatermarkPixmap,
+ QPixmap(':/images/watermark1.png'))
- self.label = QtWidgets.QLabel()
+ self.label = QLabel()
self.label.setWordWrap(True)
- layout = QtWidgets.QVBoxLayout()
+ self._launch_check_box = QCheckBox("Launch")
+ self.registerField('launch', self._launch_check_box)
+
+ layout = QVBoxLayout(self)
layout.addWidget(self.label)
- self.setLayout(layout)
+ layout.addWidget(self._launch_check_box)
def initializePage(self):
- finishText = self.wizard().buttonText(QtWidgets.QWizard.FinishButton)
- finishText.replace('&', '')
- self.label.setText("Click %s to generate the class skeleton." % finishText)
+ finish_text = self.wizard().buttonText(QWizard.FinishButton)
+ finish_text = finish_text.replace('&', '')
+ self.label.setText(f"Click {finish_text} to generate the class skeleton.")
+ self._launch_check_box.setChecked(True)
if __name__ == '__main__':
-
- import sys
-
- app = QtWidgets.QApplication(sys.argv)
+ app = QApplication(sys.argv)
wizard = ClassWizard()
wizard.show()
- sys.exit(app.exec_())
+ sys.exit(app.exec())