forked from qt-creator/qt-creator
		
	Signed-off-by: Abhishek Patil <abhishek.patil@vcreatelogic.com> Merge-request: 145 Reviewed-by: con <qtc-committer@nokia.com>
		
			
				
	
	
		
			668 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			668 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| /*!
 | ||
|     \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<6C>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
 | ||
| 	
 | ||
| 	*/
 |