/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt VS Add-in.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
namespace Digia.Qt5ProjectLib
{
using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.VisualStudio.VCProjectEngine;
using EnvDTE;
#if VS2008
[ProgId("Digia.Qt5ProjectEngine90"), GuidAttribute("AAB67315-1130-4d99-B381-C66B1DDC931D")]
#elif VS2010
[ProgId("Digia.Qt5ProjectEngine100"), GuidAttribute("F964A720-1836-4387-8243-09640D1E18D8")]
#elif VS2012
[ProgId("Digia.Qt5ProjectEngine110"), GuidAttribute("105E7F0C-09AD-43F1-9EB2-5E448B1E696A")]
#elif VS2013
[ProgId("Digia.Qt5ProjectEngine120"), GuidAttribute("41FE76EE-9669-4B2C-AB6C-E135C3EB166D")]
#else
#error GUID must be specified for this Visual Studio version!
#endif
public class QtProjectEngine
{
private EnvDTE.Project pro = null;
private QtProject qtPro = null;
private const string commonError =
"You have to call CreateXProject(...) or UseSelectedProject(...) before calling this function";
public QtProjectEngine()
{
// does nothing, for now
}
#region helper functions
private uint GetBuildConfigFromName(string configName)
{
if (configName == "RELEASE")
return BuildConfig.Release;
else if (configName == "DEBUG")
return BuildConfig.Debug;
else if (configName == "BOTH")
return BuildConfig.Both;
return BuildConfig.Both; // fall back to both
}
private FakeFilter GetFakeFilterFromName(string filterName)
{
if (filterName == "QT_SOURCE_FILTER")
return Filters.SourceFiles();
else if (filterName == "QT_HEADER_FILTER")
return Filters.HeaderFiles();
else if (filterName == "QT_FORM_FILTER")
return Filters.FormFiles();
else if (filterName == "QT_RESOURCE_FILTER")
return Filters.ResourceFiles();
else if (filterName == "QT_TRANSLATION_FILTER")
return Filters.TranslationFiles();
else if (filterName == "QT_OTHER_FILTER")
return Filters.OtherFiles();
return null;
}
private QtModule GetQtModuleFromName(string module)
{
return QtModules.Instance.ModuleIdByName(module);
}
private void CreateProject(EnvDTE.DTE app, string proName,
string proPath, string slnName, bool exclusive, FakeFilter[] filters,
string qtVersion, string platformName)
{
QtVersionManager versionManager = QtVersionManager.The();
if (qtVersion == null)
qtVersion = versionManager.GetDefaultVersion();
if (qtVersion == null)
throw new QtVSException("Unable to find a Qt build!\r\n"
+ "To solve this problem specify a Qt build");
string solutionPath = "";
Solution newSolution = app.Solution;
if (platformName == null)
{
string tmpQtVersion = versionManager.GetSolutionQtVersion(newSolution);
qtVersion = tmpQtVersion != null ? tmpQtVersion : qtVersion;
try
{
VersionInformation vi = new VersionInformation(versionManager.GetInstallPath(qtVersion));
if (vi.is64Bit())
platformName = "x64";
else
platformName = "Win32";
}
catch (Exception e)
{
Messages.DisplayErrorMessage(e);
}
}
if (!string.IsNullOrEmpty(slnName) && (exclusive == true))
{
solutionPath = proPath.Substring(0, proPath.LastIndexOf("\\"));
newSolution.Create(solutionPath, slnName);
}
System.IO.Directory.CreateDirectory(proPath);
string templatePath = HelperFunctions.CreateProjectTemplateFile(filters, true, platformName);
pro = newSolution.AddFromTemplate(templatePath, proPath, proName, exclusive);
HelperFunctions.ReleaseProjectTemplateFile();
qtPro = QtProject.Create(pro);
QtVSIPSettings.SaveUicDirectory(pro, null);
QtVSIPSettings.SaveMocDirectory(pro, null);
QtVSIPSettings.SaveMocOptions(pro, null);
QtVSIPSettings.SaveRccDirectory(pro, null);
QtVSIPSettings.SaveLUpdateOnBuild(pro);
QtVSIPSettings.SaveLUpdateOptions(pro, null);
QtVSIPSettings.SaveLReleaseOptions(pro, null);
versionManager.SaveProjectQtVersion(pro, qtVersion);
qtPro.MarkAsQtProject("v1.0");
qtPro.AddDirectories();
if (!string.IsNullOrEmpty(slnName) && (exclusive == true))
newSolution.SaveAs(solutionPath + "\\" + slnName + ".sln");
}
#endregion
#region functions for creating projects
///
/// Creates an initializes a new qt library project. Call this function before calling other functions in this class.
///
/// The DTE object
/// Name of the project to create
/// The path to the new project
/// Name of solution to create (If this is empty it will create a solution with
/// the same name as the project)
/// true if the project should be opened in a new solution
/// true if the project should be created as a static library
public void CreateLibraryProject(EnvDTE.DTE app, string proName,
string proPath, string slnName, bool exclusive, bool staticLib, bool usePrecompiledHeaders)
{
FakeFilter[] filters = {Filters.SourceFiles(), Filters.HeaderFiles(),
Filters.FormFiles(), Filters.ResourceFiles(), Filters.GeneratedFiles()};
uint projType;
if (staticLib)
projType = TemplateType.StaticLibrary | TemplateType.GUISystem;
else
projType = TemplateType.DynamicLibrary | TemplateType.GUISystem;
CreateProject(app, proName, proPath, slnName, exclusive, filters, null, null);
qtPro.WriteProjectBasicConfigurations(projType, usePrecompiledHeaders);
qtPro.AddModule(QtModule.Main);
}
///
/// Creates an initializes a new qt console application project. Call this function before calling other functions in this class.
///
/// The DTE object
/// Name of the project to create
/// The path to the new project
/// Name of solution to create (If this is empty it will create a solution with
/// the same name as the project)
/// true if the project should be opened in a new solution
public void CreateConsoleProject(EnvDTE.DTE app, string proName,
string proPath, string slnName, bool exclusive, bool usePrecompiledHeaders)
{
FakeFilter[] filters = {Filters.SourceFiles(), Filters.HeaderFiles(),
Filters.ResourceFiles(), Filters.GeneratedFiles()};
const uint projType = TemplateType.Application | TemplateType.ConsoleSystem;
CreateProject(app, proName, proPath, slnName, exclusive, filters, null, null);
qtPro.WriteProjectBasicConfigurations(projType, usePrecompiledHeaders);
qtPro.AddModule(QtModule.Main);
}
///
/// Creates an initializes a new qt application project. Call this function before calling other functions in this class.
///
/// The DTE object
/// Name of the project to create
/// The path to the new project
/// Name of solution to create (If this is empty it will create a solution with
/// the same name as the project)
/// true if the project should be opened in a new solution
public void CreateApplicationProject(EnvDTE.DTE app, string proName,
string proPath, string slnName, bool exclusive, bool usePrecompiledHeaders)
{
FakeFilter[] filters = {Filters.SourceFiles(), Filters.HeaderFiles(),
Filters.FormFiles(), Filters.ResourceFiles(), Filters.GeneratedFiles()};
const uint projType = TemplateType.Application | TemplateType.GUISystem;
CreateProject(app, proName, proPath, slnName, exclusive, filters, null, null);
qtPro.WriteProjectBasicConfigurations(projType, usePrecompiledHeaders);
qtPro.AddModule(QtModule.Main);
}
///
/// Creates an initializes a new qt application project for Windows CE.
/// Call this function before calling other functions in this class.
///
/// The DTE object
/// Name of the project to create
/// The path to the new project
/// Name of solution to create (If this is empty it will create a solution with
/// the same name as the project)
/// true if the project should be opened in a new solution
public void CreateWinCEApplicationProject(EnvDTE.DTE app, string proName,
string proPath, string slnName, bool exclusive, string qtVersion, bool usePrecompiledHeaders)
{
const uint projType = TemplateType.Application | TemplateType.GUISystem | TemplateType.WinCEProject;
CreateWinCEProject(app, proName, proPath, slnName, exclusive, qtVersion, projType, usePrecompiledHeaders);
}
///
/// Creates an initializes a new qt library project for Windows CE.
/// Call this function before calling other functions in this class.
///
/// The DTE object
/// Name of the project to create
/// The path to the new project
/// Name of solution to create (If this is empty it will create a solution with
/// the same name as the project)
/// true if the project should be opened in a new solution
public void CreateWinCELibraryProject(EnvDTE.DTE app, string proName,
string proPath, string slnName, bool exclusive, string qtVersion, bool bStaticLib, bool usePrecompiledHeaders)
{
uint projType = TemplateType.GUISystem | TemplateType.WinCEProject;
if (bStaticLib)
projType |= TemplateType.StaticLibrary;
else
projType |= TemplateType.DynamicLibrary;
CreateWinCEProject(app, proName, proPath, slnName, exclusive, qtVersion, projType, usePrecompiledHeaders);
}
private void CreateWinCEProject(EnvDTE.DTE app, string proName, string proPath, string slnName,
bool exclusive, string qtVersion, uint projType, bool usePrecompiledHeaders)
{
FakeFilter[] filters = {Filters.SourceFiles(), Filters.HeaderFiles(),
Filters.FormFiles(), Filters.ResourceFiles(), Filters.GeneratedFiles()};
QtVersionManager versionManager = QtVersionManager.The();
if (qtVersion == null) qtVersion = versionManager.GetDefaultWinCEVersion();
VersionInformation qtVersionInfo = versionManager.GetVersionInfo(qtVersion);
string platformName = null;
try
{
platformName = qtVersionInfo.GetVSPlatformName();
}
catch
{
// fallback to some standard platform...
platformName = "Windows Mobile 5.0 Pocket PC SDK (ARMV4I)";
}
CreateProject(app, proName, proPath, slnName, exclusive, filters, qtVersion, platformName);
qtPro.WriteProjectBasicConfigurations(projType, usePrecompiledHeaders, qtVersionInfo);
qtPro.AddModule(QtModule.Main);
}
public void CreatePluginProject(EnvDTE.DTE app, string proName,
string proPath, string slnName, bool exclusive, bool usePrecompiledHeaders)
{
FakeFilter[] filters = {Filters.SourceFiles(), Filters.HeaderFiles(), Filters.GeneratedFiles()};
const uint projType = TemplateType.PluginProject | TemplateType.DynamicLibrary | TemplateType.GUISystem;
CreateProject(app, proName, proPath, slnName, exclusive, filters, null, null);
qtPro.WriteProjectBasicConfigurations(projType, usePrecompiledHeaders);
qtPro.AddModule(QtModule.Main);
qtPro.AddModule(QtModule.Designer);
}
#endregion
///
/// Adds a file to the project
///
/// file (result from CopyFileToProjectFolder)
/// the filter
/// can be one of the following: QT_SOURCE_FILTER, QT_HEADER_FILTER,
/// QT_FORM_FILTER, QT_RESOURCE_FILTER, QT_TRANSLATION_FILTER, QT_OTHER_FILTER
public VCFile AddFileToProject(string file, string filter)
{
if (qtPro == null)
throw new QtVSException(commonError);
qtPro.AdjustWhitespace(file);
return qtPro.AddFileToProject(file, GetFakeFilterFromName(filter));
}
///
/// Copy a file to the project folder.
///
/// full path to source file
/// destination file (relative to the location of the project)
/// full path to the destination file
public string CopyFileToProjectFolder(string srcFile, string destName)
{
if (qtPro == null)
throw new QtVSException(commonError);
return qtPro.CopyFileToProject(srcFile, destName);
}
public string CopyFileToFolder(string srcFile, string destFolder, string destName)
{
return QtProject.CopyFileToFolder(srcFile, destFolder, destName);
}
///
///
///
///
///
///
public string CreateQrcFile(string className, string destName)
{
if (qtPro == null)
throw new QtVSException(commonError);
return qtPro.CreateQrcFile(className, destName);
}
///
/// Adds a qt module to the project
///
/// the module to add
/// see QtModules.ModuleIdByName()
///
public void AddModule(string module)
{
if (qtPro == null)
throw new QtVSException(commonError);
qtPro.AddModule(GetQtModuleFromName(module));
}
///
/// Removes a qt module from the project
///
/// the module to remove
/// see QtModules.ModuleIdByName()
///
public void RemoveModule(string module)
{
if (qtPro == null)
throw new QtVSException(commonError);
qtPro.RemoveModule(GetQtModuleFromName(module));
}
///
/// Checks if an add-on qt module is installed
///
/// the module to find
///
public bool IsModuleInstalled(string moduleName)
{
QtVersionManager versionManager = QtVersionManager.The();
string qtVersion = versionManager.GetDefaultVersion();
if (qtVersion == null)
throw new QtVSException("Unable to find a Qt build!\r\n"
+ "To solve this problem specify a Qt build");
string install_path = versionManager.GetInstallPath(qtVersion);
if (moduleName.StartsWith("Qt"))
{
moduleName = "Qt5" + moduleName.Substring(2);
}
string full_path = install_path + "\\lib\\" + moduleName + ".lib";
System.IO.FileInfo fi = new System.IO.FileInfo(full_path);
return fi.Exists;
}
///
/// Adds a icon resource to the project
///
/// the icon file to add
/// true if everything is ok
public bool AddApplicationIcon(string iconFileName)
{
if (qtPro == null)
throw new QtVSException(commonError);
return qtPro.AddApplicationIcon(iconFileName);
}
///
/// Creates a new GUID and returns it as a string.
///
/// the new GUID
public string CreateNewGUID()
{
return System.Guid.NewGuid().ToString().ToUpper();
}
///
/// Returns the file name of a given file path.
///
/// can be relative or absolute
/// the file name
public string GetFileName(string filePath)
{
System.IO.FileInfo fi = new System.IO.FileInfo(filePath);
return fi.Name;
}
///
/// Replaces a token in a VCFile. The tokens are usually class names and file names.
///
/// the file in which to replace tokens
/// the token to replace
/// the replacement value
public void ReplaceTokenInFile(string file, string token, string replacement)
{
QtProject.ReplaceTokenInFile(file, token, replacement);
}
public void EnableSection(string file, string sectionName, bool enable)
{
QtProject.EnableSection(file, sectionName, enable);
}
///
/// Adds a ActiveQt build step to the project.
///
/// the version of the library
public void AddActiveQtBuildStep(string version)
{
if (qtPro == null)
throw new QtVSException(commonError);
qtPro.AddActiveQtBuildStep(version);
}
///
/// Adds a define to the config.
///
/// the define to add
/// the config (can be RELEASE, DEBUG or BOTH)
public void AddDefine(string define, string config)
{
if (qtPro == null)
throw new QtVSException(commonError);
qtPro.AddDefine(define, GetBuildConfigFromName(config));
}
///
/// The created project.
///
public EnvDTE.Project Project
{
get
{
if (qtPro == null)
throw new QtVSException(commonError);
return pro;
}
}
///
/// Finishes the creation of the qt project
///
public void Finish()
{
if (qtPro == null)
throw new QtVSException(commonError);
qtPro.Finish();
}
public void UseSelectedProject(EnvDTE.DTE app)
{
pro = HelperFunctions.GetSelectedQtProject(app);
if (pro == null)
throw new QtVSException("Can't find a selected project");
qtPro = QtProject.Create(pro);
}
public bool IsSelectedProjectQt(EnvDTE.DTE app)
{
pro = HelperFunctions.GetSelectedQtProject(app);
if (pro == null)
return false;
return true;
}
///
/// Returns the Windows CE Qt builds which are available.
///
/// List of string
public ArrayList GetQtWinCEVersions(EnvDTE.DTE dte)
{
ArrayList list = new ArrayList();
QtVersionManager vm = QtVersionManager.The();
foreach (string qtVersion in vm.GetVersions())
{
VersionInformation vi = vm.GetVersionInfo(qtVersion);
string platformName = GetWinCEPlatformName(qtVersion, vm);
if (vi.IsWinCEVersion() && HelperFunctions.IsPlatformAvailable(dte, platformName))
list.Add(qtVersion);
}
return list;
}
public string GetDefaultWinCEVersion()
{
QtVersionManager vm = QtVersionManager.The();
return vm.GetDefaultWinCEVersion();
}
public string GetWinCEPlatformName(string qtVersion)
{
return GetWinCEPlatformName(qtVersion, QtVersionManager.The());
}
private string GetWinCEPlatformName(string qtVersion, QtVersionManager versionManager)
{
VersionInformation vi = versionManager.GetVersionInfo(qtVersion);
try
{
return vi.GetVSPlatformName();
}
catch
{
return "(unknown platform)";
}
}
public string ShowOpenFolderDialog(string directory)
{
FolderBrowserDialog dia = new FolderBrowserDialog();
dia.Description = "Select a directory:";
dia.SelectedPath = directory;
if (dia.ShowDialog() == DialogResult.OK)
return dia.SelectedPath;
return directory;
}
public bool UsesPrecompiledHeaders()
{
if (qtPro == null)
throw new QtVSException(commonError);
return qtPro.UsesPrecompiledHeaders();
}
public string GetPrecompiledHeaderThrough()
{
if (qtPro == null)
throw new QtVSException(commonError);
return qtPro.GetPrecompiledHeaderThrough();
}
}
}