/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ using Microsoft.Internal.VisualStudio.PlatformUI; using Microsoft.VisualStudio.OLE.Interop; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.TemplateWizard; using QtVsTools.Core; using QtVsTools.VisualStudio; using System.Collections.Generic; using System.IO; using System.Linq; namespace QtVsTools.Wizards.ClassWizard { public class CoreClassWizard : IClassWizard { public WizardResult Run(EnvDTE.DTE dte, string name, string location) { ThreadHelper.ThrowIfNotOnUIThread(); var serviceProvider = new ServiceProvider(dte as IServiceProvider); var iVsUIShell = VsServiceProvider.GetService(); iVsUIShell.EnableModeless(0); try { System.IntPtr hwnd; iVsUIShell.GetDialogOwnerHwnd(out hwnd); try { if (string.IsNullOrEmpty(name)) name = @"QtClass"; data.ClassName = name; data.BaseClass = @"QObject"; data.ConstructorSignature = "QObject *parent"; data.InsertQObjectMacro = true; data.ClassHeaderFile = name + @".h"; data.ClassSourceFile = name + @".cpp"; var wizard = new WizardWindow(new List { new WizardIntroPage { Data = data, Header = @"Welcome to the Qt Class Wizard", Message = @"This wizard will add a new Qt class to your project. The " + @"wizard creates a .h and .cpp file." + System.Environment.NewLine + System.Environment.NewLine + "To continue, click Next.", PreviousButtonEnabled = false, NextButtonEnabled = true, FinishButtonEnabled = false, CancelButtonEnabled = true }, new CoreClassPage { Data = data, Header = @"Welcome to the Qt Class Wizard", Message = @"This wizard will add a new Qt class to your project. The " + @"wizard creates a .h and .cpp file.", PreviousButtonEnabled = true, NextButtonEnabled = false, FinishButtonEnabled = true, CancelButtonEnabled = true } }) { Title = @"Qt Class Wizard" }; WindowHelper.ShowModal(wizard, hwnd); if (!wizard.DialogResult.HasValue || !wizard.DialogResult.Value) throw new System.Exception("Unexpected wizard return value."); var array = data.ClassName.Split(new[] { "::" }, System .StringSplitOptions.RemoveEmptyEntries); data.ClassName = array.LastOrDefault(); string nsBegin = string.Empty, nsEnd = string.Empty; for (var i = 0; i < array.Length - 1; ++i) { nsBegin += "namespace " + array[i] + " {\r\n"; nsEnd = "} // namespace " + array[i] + "\r\n" + nsEnd; } var pro = HelperFunctions.GetSelectedQtProject(dte); if (pro == null) throw new QtVSException("Can't find a selected project"); var qtProject = QtProject.Create(pro); var hppFile = AddProjectItemHpp(location); ReplaceNamespaceToken(hppFile, nsBegin, nsEnd); qtProject.AdjustWhitespace(hppFile); qtProject.AddFileToProject(hppFile, Filters.HeaderFiles()); VsShellUtilities.OpenDocument(serviceProvider, hppFile); var pch = string.Empty; if (qtProject.UsesPrecompiledHeaders()) pch = qtProject.GetPrecompiledHeaderThrough(); var cppFile = AddProjectItemCpp(location, pch); ReplaceNamespaceToken(cppFile, nsBegin, nsEnd); qtProject.AdjustWhitespace(cppFile); qtProject.AddFileToProject(cppFile, Filters.SourceFiles()); VsShellUtilities.OpenDocument(serviceProvider, cppFile); } catch (QtVSException exception) { Messages.DisplayErrorMessage(exception.Message); throw; // re-throw, but keep the original exception stack intact } } catch { throw new WizardBackoutException(); } finally { iVsUIShell.EnableModeless(1); } return WizardResult.Finished; } private readonly WizardData data = new WizardData { DefaultModules = new List { @"QtCore" } }; private static void ReplaceNamespaceToken(string file, string nsBegin, string nsEnd) { if (!string.IsNullOrEmpty(nsBegin)) nsBegin += System.Environment.NewLine; QtProject.ReplaceTokenInFile(file, "%NAMESPACE_BEGIN%", nsBegin); if (!string.IsNullOrEmpty(nsEnd)) nsEnd = System.Environment.NewLine + nsEnd; QtProject.ReplaceTokenInFile(file, "%NAMESPACE_END%", nsEnd); } private string AddProjectItemHpp(string location) { var hppFile = Path.GetTempFileName(); using (var tmp = new StreamWriter(hppFile)) { tmp.Write("#pragma once\r\n\r\n" + "%BASECLASSINCLUDE%%NAMESPACE_BEGIN%class %CLASS%%BASEDECL%\r\n" + "{%Q_OBJECT%\r\n" + "public:\r\n" + " %CLASS%(%CTORSIG%);\r\n" + " ~%CLASS%();\r\n" + "};\r\n" + "%NAMESPACE_END%"); } hppFile = QtProject.CopyFileToFolder(hppFile, location, data.ClassHeaderFile); QtProject.ReplaceTokenInFile(hppFile, "%CLASS%", data.ClassName); QtProject.ReplaceTokenInFile(hppFile, "%BASECLASS%", data.BaseClass); if (string.IsNullOrEmpty(data.BaseClass)) { QtProject.ReplaceTokenInFile(hppFile, "%BASEDECL%", string.Empty); QtProject.ReplaceTokenInFile(hppFile, "%BASECLASSINCLUDE%", string.Empty); QtProject.ReplaceTokenInFile(hppFile, "%Q_OBJECT%", string.Empty); QtProject.ReplaceTokenInFile(hppFile, "%CTORSIG%", string.Empty); } else { QtProject.ReplaceTokenInFile(hppFile, "%BASEDECL%", " : public " + data.BaseClass); QtProject.ReplaceTokenInFile(hppFile, "%BASECLASSINCLUDE%", "#include <" + data.BaseClass + ">\r\n\r\n"); if (data.InsertQObjectMacro) QtProject.ReplaceTokenInFile(hppFile, "%Q_OBJECT%", "\r\n\tQ_OBJECT\r\n"); QtProject.ReplaceTokenInFile(hppFile, "%CTORSIG%", data.ConstructorSignature); } return hppFile; } private string AddProjectItemCpp(string location, string pch) { var cppFile = Path.GetTempFileName(); using (var tmp = new StreamWriter(cppFile)) { tmp.Write("#include \"%INCLUDE%\"\r\n\r\n" + "%NAMESPACE_BEGIN%%CLASS%::%CLASS%(%CTORSIG%)%BASECLASS%\r\n" + "{\r\n}\r\n\r\n" + "%CLASS%::~%CLASS%()\r\n" + "{\r\n}\r\n" + "%NAMESPACE_END%"); } cppFile = QtProject.CopyFileToFolder(cppFile, location, data.ClassSourceFile); if (!string.IsNullOrEmpty(pch)) QtProject.ReplaceTokenInFile(cppFile, "%INCLUDE%", pch + "\"\r\n#include \"%INCLUDE%"); QtProject.ReplaceTokenInFile(cppFile, "%INCLUDE%", data.ClassHeaderFile); QtProject.ReplaceTokenInFile(cppFile, "%CLASS%", data.ClassName); QtProject.ReplaceTokenInFile(cppFile, "%BASECLASS%", string.IsNullOrEmpty(data .ConstructorSignature) ? "" : "\r\n : " + data.BaseClass + "(parent)"); QtProject.ReplaceTokenInFile(cppFile, "%CTORSIG%", data.ConstructorSignature); return cppFile; } } }