diff options
Diffstat (limited to 'doc/pluginhowto/project-file-wizard.qdoc')
-rw-r--r-- | doc/pluginhowto/project-file-wizard.qdoc | 667 |
1 files changed, 0 insertions, 667 deletions
diff --git a/doc/pluginhowto/project-file-wizard.qdoc b/doc/pluginhowto/project-file-wizard.qdoc deleted file mode 100644 index 621fd6ea475..00000000000 --- a/doc/pluginhowto/project-file-wizard.qdoc +++ /dev/null @@ -1,667 +0,0 @@ -/*! - \page project-file-wizard.html - \title 8. Project/File Wizards - - New projects in Qt Creator can be created by clicking on the "File -> New" menu item and selecting the required project - type. Shown below is the new project dialog box. - - \inlineimage qtc-newprojectdialog-8.png - - - In this chapter we will learn how to add new project types into the dialog box above. - - \section1 8.1 Core::IWizard interface - - Qt Creator provides a Core::IWizard interface that can be implemented to support new project types. The interface is - defined as follows in \bold {src/plugins/coreplugin/dialogs/iwizard.h}. - - \code - class CORE_EXPORT IWizard : public QObject - { - Q_OBJECT - - public: - enum Kind {FileWizard,ClassWizard,ProjectWizard}; - virtual Kind kind() const = 0; - virtual QIcon icon() const = 0; - virtual QString description() const = 0; - virtual QString name() const = 0; - virtual QString category() const = 0; - virtual QString trCategory() const = 0; - virtual QStringList runWizard(const QString &path, QWidget *parent) = 0; - }; - - \endcode - - Qt Creator supports the following types of new entities - \list - \o File - \o Class - \o Project - \endlist - - \bold {Core::IWizard} has to be implemented to support any of the above project types. - - \section2 8.1.1 Sample implementation of Core::IWizard - Let's implement the \bold {IWizard} interface to support a new project type called "Custom Project". The idea is to see the - new project type listed in the new project wizard that shows up on clicking "File -> New". - - \section3 Step 1: Implementing the Core::IWizard interface - Lets create a class called \bold {CustomProjectWizard} and subclass it from \bold {Core::IWizard}. - - \code - class CustomProjectWizard : public Core::IWizard - { - public: - CustomProjectWizard() { } - ~CustomProjectWizard() { } - Core::IWizard::Kind kind() const; - QIcon icon() const; - QString description() const; - QString name() const; - QString category() const; - QString trCategory() const; - QStringList runWizard(const QString &path, QWidget *parent); - }; - - \endcode - - Below we will discuss the implementation of each of the functions. - - \bold{The kind()} function should be implemented to return the type of "new" project we support in our implementation of - \bold {IWizard}. Valid values are \bold {FileWizard},\bold{ClassWizard} and \bold {ProjectWizard}. In our implementation we return - \bold{ProjectWizard}. - - \code - Core::IWizard::Kind CustomProjectWizard::kind() const - { - return IWizard::ProjectWizard; - } - \endcode - - The \bold{icon()} implementation must return an icon to use against the project type in the New project dialog box. In our - implementation we return the Qt Creator icon itself. - - \code - QIcon CustomProjectWizard::icon() const - { - return qApp->windowIcon(); - } - \endcode - - The \bold {description()},\bold {name()} and \bold {category()} methods must return some meta data of the new project/file/class - type we are providing in the \bold {IWizard} implementation. - - \code - QString CustomProjectWizard::description() const - { - return "A custom project"; - } - - QString CustomProjectWizard::name() const - { - return "CustomProject"; - } - - QString CustomProjectWizard::category() const - { - return "FooCompanyInc"; - } - \endcode - - The \bold{trCategory()} method should be implemented to return a translated category string. This is the name that is - shown on the "New.." dialog box. - - \code - QString CustomProjectWizard::trCategory() const - { - return tr("FooCompanyInc"); - } - \endcode - - If the user selects the "CustomProject" category supported by our implementation of \bold{IWizard} and selects Ok in the - "New.." dialog box; then the \bold{runWizard()} method is called. This method must be implemented to show a dialog box - or \bold{QWizard}, ask questions from the user about the new project/file/class being created and return a list of newly - created files. In our implementation of the \bold{IWizard} we will return an empty string list. - - \code - QStringList CustomProjectWizard::runWizard(const QString &path, QWidget *parent) - { - Q_UNUSED(path); - Q_UNUSED(parent); - QMessageBox::information(parent, "Custom Wizard Dialog", "Hi there!"); - return QStringList(); - } - \endcode - - \section3 Step 2: Providing the wizard from a plugin - We implement a custom-project plugin using the same means as described in Chapter 2. The only change is in the - \bold{initialize()} method implementation of the plugin. - - \code - bool CustomProjectPlugin::initialize(const QStringList& args, QString *errMsg) - { - Q_UNUSED(args); - Q_UNUSED(errMsg); - addAutoReleasedObject(new CustomProjectWizard); - return true; - } - \endcode - - - \section3 Step 3: Testing the plugin - Upon compiling the plugin and restarting Qt Creator, we can notice the new project type in the "New.." dialog box. Take - a look at the screenshot below. - - \inlineimage qtc-testplugin-8.png - - \section1 8.2 Predefined IWizard implementation - Core::BaseFileWizard - - Qt Creator's core provides a default implementation of the \bold{IWizard} interface in the form of the - \bold {Core::BaseFileWizard} class. This class implements provides default implementation of all the methods in the - \bold {IWizard} interface and adds some virtual methods of its own. To make use of the class, we need to subclass from it and - implement one or more methods. - - \section2 8.2.1 Core::GeneratedFile and Core::GeneratedFiles - - Normally a new wizard (\bold{IWizard} implementation) is implemented to allow the user to provide some hints and have - one or more files automatically generated. The \bold{Core::GeneratedFile} helps abstract each of the files that need - generation. We will learn later on that within subclasses of \bold{Core::BaseFileWizard}, we create an instance of - \bold{Core::GeneratedFile} for each file that is automatically generated. - - The \bold{Core::GeneratedFile} class is defined as follows in \bold{coreplugin/basefilewizard.h} - - \code - class GeneratedFile - { - public: - GeneratedFile(); - explicit GeneratedFile(const QString &path); - GeneratedFile(const GeneratedFile &); - GeneratedFile &operator=(const GeneratedFile &); - ~GeneratedFile(); - - QString path() const; - void setPath(const QString &p); - - QString contents() const; - void setContents(const QString &c); - - QString editorKind() const; - void setEditorKind(const QString &k); - - bool write(QString *errorMessage) const; - - private: - QSharedDataPointer<GeneratedFilePrivate> m_d; - }; - - typedef QList<GeneratedFile> GeneratedFiles; - - \endcode - - Files that need to be generated by subclasses of \bold {Core::BaseFileWizard} are represented by the - \bold {Core::GeneratedFile} class. The class contains three key properties of a file that needs generation - - \list 1 - \o Name of the file (with its absolute path). - \o The kind of editor needed for editing the file. Some valid values for editor kind are - \list a - \o \bold{CppEditor::Constants::CPPEDITOR_KIND} - \o \bold{GenericProjectManager::Constants::PROJECT_KIND} - \o \bold{Git::Constants:: GIT_COMMAND_LOG_EDITOR_KIND} - \o \bold {Git::Constants:: C_GIT_COMMAND_LOG_EDITOR} - \endlist - \o Contents of the file. - \endlist - - Suppose that we wanted to generate a C++ source file with the following contents - - \code - #include <iostream> - int main() - { - cout << "Hello World\n"; - return 0; - } - \endcode - - We would use \bold{Core::GeneratedFile} for generating the above contents as follows - \code - #include <coreplugin/basefilewizard.h> - #include <cppeditor/cppeditorconstants.h> - - Core::GeneratedFile genFile("C:/Path/To/Source.cpp"); - genFile.setEditorKind(CppEditor::Constants::CPPEDITOR_KIND); - genFile.setContents( - "#include <iostream>\n" - "\n" - "int main()\n" - "{\n" - " cout << \"Hello World\n\";\n" - " \n" - " return 0;\n" - "} - ); - genFile.write(); - - \endcode - - \section2 8.2.2 The "Item Model" class wizard - - Suppose that we wanted to provide a new class wizard that helps automatically generate the skeleton of an item model - based on few hints like - \list - \o Model Class Name - \o Base Class Name (can be \bold {QAbstractItemModel},\bold QAbstractListModel and - \bold{QAbstractTableModel}) - \o Header file name and - \o Source file name - \endlist - - Lets implement a plugin that will provide the new "Item Model" class wizard in Qt Creator. - - \section3 Step 1: Design the class wizard page - Lets design a simple page in Qt Designer that accepts hints as described above. - - \inlineimage qtc-designer-8.png - - - The design is saved as ModelNamePage.ui. - \section3 Step 2: Implement the class wizard page - - Lets import the UI in a Qt/C++ and provide easy to use methods to help fetch information from the page. First we design - a structure that captures all the "item model" class hints. - - \code - struct ModelClassParameters - { - QString className; - QString headerFile; - QString sourceFile; - QString baseClass; - QString path; - }; - - \endcode - - Next we declare a wizard page class that imports the UI designed in the previous step and provides methods to access - the hints provided by the user in the page. - - \code - #include <QWizardPage> - #include "ui_ModelNamePage.h" - class ModelNamePage : public QWizardPage - { - Q_OBJECT - - public: - ModelNamePage(QWidget* parent=0); - ~ModelNamePage(); - void setPath(const QString& path); - ModelClassParameters parameters() const; - private slots: - void on_txtModelClass_textEdited(const QString& txt); - - private: - Ui::ModelNamePage ui; - QString path; - }; - \endcode - - The constructor and destructor are straight forward and easy to understand. - - \code - ModelNamePage::ModelNamePage(QWidget* parent) - :QWizardPage(parent) - { - setTitle("Enter model class information"); - setSubTitle("The header and source file names will be derived from the class name"); - ui.setupUi(this); - } - - ModelNamePage::~ModelNamePage() - { - } - \endcode - The \bold{setPath()} method basically stores the path in the private variable. - - \code - void ModelNamePage::setPath(const QString& path) - { - this->path = path; - } - \endcode - - The \bold{on_txtModelClass_textEdited()} slot computes the header and source file names based on the - classname. - - \code - void ModelNamePage::on_txtModelClass_textEdited(const QString& txt) - { - ui.txtHeaderFile->setText(txt + ".h"); - ui.txtImplFile->setText(txt + ".cpp"); - } - \endcode - - Finally the \bold{parameters()} method returns all the hints entered by the user in a ModelClassParameters - instance. - - \code - ModelClassParameters ModelNamePage::parameters() const - { - ModelClassParameters params; - params.className = ui.txtModelClass->text(); - params.headerFile = ui.txtHeaderFile->text(); - - params.sourceFile = ui.txtImplFile->text(); - params.baseClass = ui.cmbBaseClass->currentText(); - params.path = path; - return params; - } - \endcode - - \section3 Step 3: Subclass Core::BaseFileWizard - - The\bold {Core::BaseFileWizard} class is defined as follows in \bold{coreplugin/basefilewizard.h} - - \code - class CORE_EXPORT BaseFileWizard : public IWizard - { - public: - virtual ~BaseFileWizard(); - - // IWizard - virtual Kind kind() const; - virtual QIcon icon() const; - virtual QString description() const; - virtual QString name() const; - virtual QString category() const; - virtual QString trCategory() const; - virtual QStringList runWizard(const QString &path, QWidget *parent); - - protected: - typedef QList<QWizardPage *> WizardPageList; - explicit BaseFileWizard(const BaseFileWizardParameters ¶meters,QObject *parent = 0); - - virtual QWizard *createWizardDialog(QWidget *parent,const QString &defaultPath, - const WizardPageList &extensionPages) const = 0; - - virtual GeneratedFiles generateFiles(const QWizard *w,QString *errorMessage) const = 0; - - virtual bool postGenerateFiles(const GeneratedFiles &l,QString *errorMessage); - }; - \endcode - - \underline {\bold{Note: Some methods from the actual BaseFileWizard class are not shown here.}} - - The \bold{BaseFileWizard} class implements the \bold{IWizard} interface and offers three new functions - - \list - \o \bold{createWizardDialog} - This function can be over-ridden by subclasses to provide a wizard that the - \bold{runWizard()} method is supposed to show. - \list - \o The \bold{parent} parameter should be used as the parent widget of the returned QWizard - \o The \bold{defaultPath} parameter should be the default location for generated files - \o The \bold{extensionPages} parameter lists out all the pages that should be shown in the wizard by default. - \endlist - \o \bold{generateFiles} - This method is called after the user is done with the wizard. Implementations of this - method must create the required files as instances of \bold{Core::GeneratedFile} class. - - \o \bold{postGenerateFiles} - This method is called after \bold{generateFiles()} returns. The default - implementation opens the newly generated files; however subclasses can choose to do anything they want. - \endlist - - We subclass the BaseFileWizard as follows for our "item model" wizard - - \code - #include <coreplugin/basefilewizard.h> - class ModelClassWizard : public Core::BaseFileWizard - { - Q_OBJECT - - public: - ModelClassWizard(const Core::BaseFileWizardParameters ¶meters, - QObject *parent = 0); - ~ModelClassWizard(); - - QWizard *createWizardDialog(QWidget *parent, - const QString &defaultPath, - - const WizardPageList &extensionPages) const; - - Core::GeneratedFiles generateFiles(const QWizard *w, - QString *errorMessage) const; - - private: - QString readFile(const QString& fileName, - const QMap<QString,QString>& replacementMap) const; - }; - - \endcode - - The constructor and destructor methods are straight forward and easy to understand. - - \code - ModelClassWizard::ModelClassWizard( - const Core::BaseFileWizardParameters ¶meters,QObject *parent) - : Core::BaseFileWizard(parameters, parent) - { - } - - ModelClassWizard::~ModelClassWizard() - { - } - \endcode - - The \bold{createWizardDialog()} method is implemented to create a \bold{QWizard} with its first page as the - \bold{ModelNamePage} class implemented step 2. Other default pages are added as usual. - - \code - QWizard* ModelClassWizard::createWizardDialog( - QWidget *parent, - const QString &defaultPath, - const WizardPageList &extensionPages) const - { - // Create a wizard - QWizard* wizard = new QWizard(parent); - wizard->setWindowTitle("Model Class Wizard"); - - // Make our page as first page - ModelNamePage* page = new ModelNamePage(wizard); - int pageId = wizard->addPage(page); - wizard->setProperty("_PageId_", pageId); - page->setPath(defaultPath); - - // Now add the remaining pages - foreach (QWizardPage *p, extensionPages) - wizard->addPage(p); - return wizard; - } - \endcode - - The \bold{readFile()} method is implemented to read a file and return its contents as a string. Before returning the file's - contents as string, the function uses the replacement table passed as second parameter to fix the string. - - \code - QString ModelClassWizard::readFile(const QString& fileName, const QMap<QString,QString>& - replacementMap) const - { - QFile file(fileName); - file.open(QFile::ReadOnly); - QString retStr = file.readAll(); - QMap<QString,QString>::const_iterator it = replacementMap.begin(); - QMap<QString,QString>::const_iterator end = replacementMap.end(); - - while(it != end) - { - retStr.replace(it.key(), it.value()); - ++it; - } - return retStr; - } - \endcode - - Suppose we have a file (\bold{sample.txt}) whose contents are as follows - - \code - #ifndef {{UPPER_CLASS_NAME}}_H - #define {{UPPER_CLASS_NAME}}_H - #include <{{BASE_CLASS_NAME}}> - struct {{CLASS_NAME}}Data; - - class {{CLASS_NAME}} : public {{BASE_CLASS_NAME}} - { - Q_OBJECT - - public: - {{CLASS_NAME}}(QObject* parent=0); - ~{{CLASS_NAME}}(); - int rowCount(const QModelIndex& parent) const; - QVariant data(const QModelIndex& index, int role) const; - - private: - {{CLASS_NAME}}Data* d; - }; - - #endif // {{UPPER_CLASS_NAME}}_H - \endcode - - Lets say we wanted to replace the hints in {{xyz}} with something more appropriate, we could use the following code - snippet. - - \code - QMap<QString,QString> replacementMap; - replacementMap["{{UPPER_CLASS_NAME}}"] = "LIST_MODEL"; - replacementMap["{{BASE_CLASS_NAME}}"] = "QAbstractListModel"; - replacementMap["{{CLASS_NAME}}"] = "ListModel"; - QString contents = readFile("Sample.txt", replacementTable); - \endcode - - When the above code is executed, the contents string will contain - - \code - #ifndef LIST_MODEL_H - #define LIST_MODEL_H - #include <QAbstractListModel> - struct ListModelData; - - class ListModel : public QAbstractListModel - { - Q_OBJECT - - public: - ListModel(QObject* parent=0); - ~ListModel(); - int rowCount(const QModelIndex& parent) const; - QVariant data(const QModelIndex& index, int role) const; - - private: - ListModelData* d; - }; - #endif // LIST_MODEL_H - \endcode - - Seems like magic isnt it? ?. We create similar "template" header and source files for item, list and table model classes - and create a resource for use in our project. - - Now, lets look at the implementation of the \bold{generateFiles()} method. This method basically creates two - \bold{Core::GeneratedFile} instances and populates them with appropriate data before returning them in a list. - - - \code - Core::GeneratedFiles ModelClassWizard::generateFiles( - const QWizard *w,QString *errorMessage) const - { - Q_UNUSED(errorMessage); - Core::GeneratedFiles ret; - int pageId = w->property("_PageId_").toInt(); - ModelNamePage* page = qobject_cast<ModelNamePage*>(w->page(pageId)); - - if(!page) - return ret; - ModelClassParameters params = page->parameters(); - QMap<QString,QString> replacementMap; - - replacementMap["{{UPPER_CLASS_NAME}}"] = params.className.toUpper(); - replacementMap["{{BASE_CLASS_NAME}}"] = params.baseClass; - replacementMap["{{CLASS_NAME}}"] = params.className; - replacementMap["{{CLASS_HEADER}}"] = QFileInfo(params.headerFile).fileName(); - - Core::GeneratedFile headerFile(params.path + "/" + params.headerFile); - headerFile.setEditorKind(CppEditor::Constants::CPPEDITOR_KIND); - - Core::GeneratedFile sourceFile(params.path + "/" + params.sourceFile); - sourceFile.setEditorKind(CppEditor::Constants::CPPEDITOR_KIND); - - if(params.baseClass == "QAbstractItemModel") - { - headerFile.setContents(readFile(":/CustomProject/ItemModelHeader", replacementMap) ); - sourceFile.setContents(readFile(":/CustomProject/ItemModelSource", replacementMap) ); - } - - else if(params.baseClass == "QAbstractTableModel") - { - headerFile.setContents(readFile(":/CustomProject/TableModelHeader", replacementMap) ); - sourceFile.setContents(readFile(":/CustomProject/TableModelSource", replacementMap) ); - } - - else if(params.baseClass == "QAbstractListModel") - { - headerFile.setContents(readFile(":/CustomProject/ListModelHeader", replacementMap) ); - sourceFile.setContents(readFile(":/CustomProject/ListModelSource", replacementMap) ); - } - - ret << headerFile << sourceFile; - return ret; - } - - \endcode - - \section3 Step 4: Implementing the plugin - - We implement the item model wizard plugin using the same means as described in Chapter 2. The only change is in the - \bold {initialize()} method implementation of the plugin. - - \code - bool ItemModelWizard::initialize(const QStringList& args, QString *errMsg) - { - Q_UNUSED(args); - Q_UNUSED(errMsg); - Core::BaseFileWizardParameters params; - params.setKind(Core::IWizard::ClassWizard); - params.setIcon(qApp->windowIcon()); - params.setDescription("Generates an item-model class"); - params.setName("Item Model"); - params.setCategory("FooCompany"); - params.setTrCategory(tr("FooCompany")); - addAutoReleasedObject(new ModelClassWizard(params, this)); - return true; - } - \endcode - - \section3 Step 5: Testing the plugin - - - Upon compiling the plugin and restarting Qt Creator, we can notice the new project type in the "New.." dialog box. The - following screenshots showcase the wizard that was just implemented. - - \inlineimage qtc-newitemmodel-8.png - - - Upon selecting the "Item Model" class wizard, we can see the ModelNamePage in a custom wizard. - - \inlineimage qtc-customwizardone-8.png - - - We enter the appropriate details and click "Next" Qt Creator then shows us a built-in page to allow addition of the - newly generated files into the current project. - - \inlineimage qtc-customwizardtwo-8.png - - - Upon clicking "Finish", we can notice the newly generated files in the editor. - - \inlineimage qtc-editor-8.png - - */ |