/**************************************************************************** ** ** 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 EnvDTE; using System; using System.IO; using System.Collections; using System.Collections.Generic; using System.Windows.Forms; using System.Text.RegularExpressions; using System.Xml; using Microsoft.VisualStudio.VCProjectEngine; /// /// QtProject holds the Qt specific properties for a Visual Studio project. /// There exists at most one QtProject per EnvDTE.Project. /// Use QtProject.Create to get the QtProject for a Project or VCProject. /// public class QtProject { private EnvDTE.DTE dte = null; private EnvDTE.Project envPro = null; private VCProject vcPro = null; private MocCmdChecker mocCmdChecker = null; private Array lastConfigurationRowNames = null; private static Dictionary instances = new Dictionary(); public static QtProject Create(VCProject vcProject) { return Create((EnvDTE.Project)vcProject.Object); } public static QtProject Create(EnvDTE.Project project) { QtProject qtProject = null; if (!instances.TryGetValue(project, out qtProject)) { qtProject = new QtProject(project); instances.Add(project, qtProject); } return qtProject; } public static void ClearInstances() { instances.Clear(); } private QtProject(EnvDTE.Project project) { if (project == null) throw new QtVSException(SR.GetString("QtProject_CannotConstructWithoutValidProject")); envPro = project; dte = envPro.DTE; vcPro = envPro.Object as VCProject; } public VCProject VCProject { get { return vcPro; } } public EnvDTE.Project Project { get { return envPro; } } public string ProjectDir { get { return vcPro.ProjectDirectory; } } /// /// Returns true if the ConfigurationRowNames have changed /// since the last evaluation of this property. /// public bool ConfigurationRowNamesChanged { get { bool ret = false; if (lastConfigurationRowNames == null) { lastConfigurationRowNames = envPro.ConfigurationManager.ConfigurationRowNames as Array; } else { Array currentConfigurationRowNames = envPro.ConfigurationManager.ConfigurationRowNames as Array; if (!HelperFunctions.ArraysEqual(lastConfigurationRowNames, currentConfigurationRowNames)) { lastConfigurationRowNames = currentConfigurationRowNames; ret = true; } } return ret; } } /// /// Returns the file name of the generated ui header file relative to /// the project directory. /// /// name of the ui file public string GetUiGeneratedFileName(string uiFile) { FileInfo fi = new FileInfo(uiFile); string file = fi.Name; if (fi.Extension == ".ui") { return QtVSIPSettings.GetUicDirectory(envPro) + "\\ui_" + file.Remove(file.Length-3, 3) + ".h"; } return null; } /// /// Returns the moc-generated file name for the given source or header file. /// /// header or source file in the project /// private static string GetMocFileName(string file) { FileInfo fi = new FileInfo(file); string name = fi.Name; if (HelperFunctions.HasHeaderFileExtension(fi.Name)) return "moc_" + name.Substring(0, name.LastIndexOf('.')) + ".cpp"; else if (HelperFunctions.HasSourceFileExtension(fi.Name)) return name.Substring(0, name.LastIndexOf('.')) + ".moc"; else return null; } /// /// Returns the file name of the generated moc file relative to the /// project directory. /// /// The directory of the moc file depends on the file configuration. /// Every appearance of "$(ConfigurationName)" in the path will be /// replaced by the value of configName. /// full file name of either the header or the source file /// file configuration /// private string GetRelativeMocFilePath(string file, string configName, string platformName) { string fileName = GetMocFileName(file); if (fileName == null) return null; string mocDir = QtVSIPSettings.GetMocDirectory(envPro, configName, platformName) + "\\" + fileName; if (HelperFunctions.IsAbsoluteFilePath(mocDir)) mocDir = HelperFunctions.GetRelativePath(vcPro.ProjectDirectory, mocDir); return mocDir; } /// /// Returns the file name of the generated moc file relative to the /// project directory. /// /// The returned file path may contain the macros $(ConfigurationName) and $(PlatformName). /// full file name of either the header or the source file /// private string GetRelativeMocFilePath(string file) { return GetRelativeMocFilePath(file, null, null); } public string QtPackageVersion() { if (vcPro == null) return null; return vcPro.keyword.Remove(0, Resources.qtProjectKeyword.Length); } /// /// Marks the specified project as a Qt project. /// /// project public void MarkAsQtProject(string version) { vcPro.keyword = Resources.qtProjectKeyword + version; } public void AddDefine(string define, uint bldConf) { foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); if (((!IsDebugConfiguration(config)) && ((bldConf & BuildConfig.Release) != 0)) || ((IsDebugConfiguration(config)) && ((bldConf & BuildConfig.Debug) != 0))) { compiler.AddPreprocessorDefinition(define); } } } public void AddModule(QtModule module) { if (HasModule(module)) return; QtVersionManager vm = QtVersionManager.The(); VersionInformation versionInfo = vm.GetVersionInfo(this.Project); if (versionInfo == null) versionInfo = vm.GetVersionInfo(vm.GetDefaultVersion()); foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); VCLinkerTool linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); QtModuleInfo info = QtModules.Instance.ModuleInformation(module); if (compiler != null) { foreach(string define in info.Defines) compiler.AddPreprocessorDefinition(define); string incPath = info.GetIncludePath(); if (!String.IsNullOrEmpty(incPath)) compiler.AddAdditionalIncludeDirectories(incPath); } if (linker != null) { List moduleLibs = info.GetLibs(IsDebugConfiguration(config), versionInfo); LinkerToolWrapper linkerWrapper = new LinkerToolWrapper(linker); List additionalDeps = linkerWrapper.AdditionalDependencies; bool dependenciesChanged = false; if (additionalDeps == null || additionalDeps.Count == 0) { additionalDeps = moduleLibs; dependenciesChanged = true; } else { foreach (string moduleLib in moduleLibs) if (!additionalDeps.Contains(moduleLib)) { additionalDeps.Add(moduleLib); dependenciesChanged = true; } } if (dependenciesChanged) linkerWrapper.AdditionalDependencies = additionalDeps; } #if ENABLE_WINCE if (info.HasDLL && config.DeploymentTool != null) AddDeploySettings(null, module, config, info, versionInfo); #endif } } public void RemoveModule(QtModule module) { foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); VCLinkerTool linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); QtModuleInfo info = QtModules.Instance.ModuleInformation(module); if (compiler != null) { foreach (string define in info.Defines) compiler.RemovePreprocessorDefinition(define); List additionalIncludeDirs = compiler.AdditionalIncludeDirectories; if (additionalIncludeDirs != null) { List lst = new List(additionalIncludeDirs); if (!String.IsNullOrEmpty(info.IncludePath)) { lst.Remove(info.IncludePath); lst.Remove('\"' + info.IncludePath + '\"'); } compiler.AdditionalIncludeDirectories = lst; } } if (linker != null && linker.AdditionalDependencies != null) { LinkerToolWrapper linkerWrapper = new LinkerToolWrapper(linker); QtVersionManager vm = QtVersionManager.The(); VersionInformation versionInfo = vm.GetVersionInfo(this.Project); if (versionInfo == null) versionInfo = vm.GetVersionInfo(vm.GetDefaultVersion()); List moduleLibs = info.GetLibs(IsDebugConfiguration(config), versionInfo); List additionalDependencies = linkerWrapper.AdditionalDependencies; bool dependenciesChanged = false; foreach (string moduleLib in moduleLibs) if (additionalDependencies.Remove(moduleLib)) dependenciesChanged = true; if (dependenciesChanged) linkerWrapper.AdditionalDependencies = additionalDependencies; } #if ENABLE_WINCE if (info.HasDLL && config.DeploymentTool != null) RemoveDeploySettings(null, module, config, info); #endif } } public void UpdateModules(VersionInformation oldVersion, VersionInformation newVersion) { foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { VCLinkerTool linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); if (linker != null) { if (oldVersion == null || oldVersion.IsWinCEVersion() != newVersion.IsWinCEVersion()) { LinkerToolWrapper linkerWrapper = new LinkerToolWrapper(linker); List additionalDependencies = linkerWrapper.AdditionalDependencies; List libsDesktop = new List(); List libsWinCE = new List(); foreach (QtModuleInfo module in QtModules.Instance.GetAvailableModuleInformation()) { if (HasModule(module.ModuleId)) { libsDesktop.AddRange(module.AdditionalLibraries); libsWinCE.AddRange(module.AdditionalLibrariesWinCE); } } List libsToAdd = null; List libsToRemove = null; if (newVersion.IsWinCEVersion()) { libsToAdd = libsWinCE; libsToRemove = libsDesktop; } else { libsToAdd = libsDesktop; libsToRemove = libsWinCE; } bool changed = false; foreach (string libToRemove in libsToRemove) { if (additionalDependencies.Remove(libToRemove)) changed = true; } foreach (string libToAdd in libsToAdd) { if (!additionalDependencies.Contains(libToAdd)) { additionalDependencies.Add(libToAdd); changed = true; } } if (changed) linkerWrapper.AdditionalDependencies = additionalDependencies; } #if ENABLE_WINCE if (newVersion.IsWinCEVersion() && newVersion.IsStaticBuild() && oldVersion != null && !(oldVersion.IsWinCEVersion() && oldVersion.IsStaticBuild()) && config.DeploymentTool != null) { RemoveQtDeploys(config); } #endif if (oldVersion == null || newVersion.IsStaticBuild() != oldVersion.IsStaticBuild()) { CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); if (newVersion.IsStaticBuild()) { if (compiler != null) compiler.RemovePreprocessorDefinition("QT_DLL"); } else { if (compiler != null) compiler.AddPreprocessorDefinition("QT_DLL"); } } #if ENABLE_WINCE if (newVersion.IsWinCEVersion() && !newVersion.IsStaticBuild() && (oldVersion == null || !(oldVersion.IsWinCEVersion() && !oldVersion.IsStaticBuild())) && config.DeploymentTool != null) { MatchCollection matches = Regex.Matches(linker.AdditionalDependencies, "Qt(\\S+)5\\.lib"); foreach (Match m in matches) { string moduleName = m.ToString().Substring(0, m.ToString().Length - 5); if (config.ConfigurationName.StartsWith("Debug")) moduleName = moduleName.Substring(0, moduleName.Length - 1); QtModule module = QtModules.Instance.ModuleIdByName(moduleName); AddDeploySettings(null, module, config, null, newVersion); } } #endif } } } public bool HasModule(QtModule module) { bool foundInIncludes = false; bool foundInLibs = false; QtVersionManager vm = QtVersionManager.The(); VersionInformation versionInfo = vm.GetVersionInfo(this.Project); if (versionInfo == null) versionInfo = vm.GetVersionInfo(vm.GetDefaultVersion()); foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); VCLinkerTool linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); QtModuleInfo info = QtModules.Instance.ModuleInformation(module); if (compiler != null) { string incPath = info.GetIncludePath(); if (String.IsNullOrEmpty(incPath)) break; if (compiler.GetAdditionalIncludeDirectories() == null) continue; string fixedIncludeDir = FixFilePathForComparison(incPath); string[] includeDirs = compiler.GetAdditionalIncludeDirectoriesList(); foreach (string dir in includeDirs) { if (FixFilePathForComparison(dir) == fixedIncludeDir) { foundInIncludes = true; break; } } } if (foundInIncludes) break; List libs = null; if (linker != null) { LinkerToolWrapper linkerWrapper = new LinkerToolWrapper(linker); libs = linkerWrapper.AdditionalDependencies; } if (libs != null) { foundInLibs = true; List moduleLibs = info.GetLibs(IsDebugConfiguration(config), versionInfo); foreach (string moduleLib in moduleLibs) { if (!libs.Contains(moduleLib)) { foundInLibs = false; break; } } } } return foundInIncludes || foundInLibs; } public void WriteProjectBasicConfigurations(uint type, bool usePrecompiledHeader) { WriteProjectBasicConfigurations(type, usePrecompiledHeader, null); } public void WriteProjectBasicConfigurations(uint type, bool usePrecompiledHeader, VersionInformation vi) { ConfigurationTypes configType = ConfigurationTypes.typeApplication; string targetExtension = ".exe"; string qtVersion = null; QtVersionManager vm = QtVersionManager.The(); if (vi == null) { qtVersion = vm.GetDefaultVersion(); vi = vm.GetVersionInfo(qtVersion); } switch (type & TemplateType.ProjectType) { case TemplateType.DynamicLibrary: configType = ConfigurationTypes.typeDynamicLibrary; targetExtension = ".dll"; break; case TemplateType.StaticLibrary: configType = ConfigurationTypes.typeStaticLibrary; targetExtension = ".lib"; break; } foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { config.ConfigurationType = configType; CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); VCLinkerTool linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); VCLibrarianTool librarian = (VCLibrarianTool)((IVCCollection)config.Tools).Item("VCLibrarianTool"); // for some stupid reason you have to set this for it to be updated... // the default value is the same... +platform now #if (VS2010 || VS2012 || VS2013) config.OutputDirectory = "$(SolutionDir)$(Platform)\\$(Configuration)\\"; #else config.OutputDirectory = "$(SolutionDir)$(PlatformName)\\$(ConfigurationName)"; #endif #if ENABLE_WINCE // This is mainly for Visual Studio consistency compared with a smartdevice MFC project. config.IntermediateDirectory = config.OutputDirectory; #endif // add some common defines compiler.SetPreprocessorDefinitions(vi.GetQMakeConfEntry("DEFINES").Replace(" ", ",")); if (!vi.IsStaticBuild()) { compiler.AddPreprocessorDefinition("QT_DLL"); } if (linker != null) { if (vi.IsWinCEVersion()) { linker.SubSystem = subSystemOption.subSystemNotSet; SetTargetMachine(linker, vi); } else { if ((type & TemplateType.ConsoleSystem) != 0) linker.SubSystem = subSystemOption.subSystemConsole; else linker.SubSystem = subSystemOption.subSystemWindows; } linker.OutputFile = "$(OutDir)\\$(ProjectName)" + targetExtension; linker.AdditionalLibraryDirectories = "$(QTDIR)\\lib"; if (vi.IsStaticBuild()) { linker.AdditionalDependencies = vi.GetQMakeConfEntry("QMAKE_LIBS_CORE"); if ((type & TemplateType.GUISystem) != 0) { linker.AdditionalDependencies += " " + vi.GetQMakeConfEntry("QMAKE_LIBS_GUI"); if (vi.IsWinCEVersion()) linker.AdditionalDependencies += " qmenu_wince.res"; } } } else { librarian.OutputFile = "$(OutDir)\\$(ProjectName)" + targetExtension; librarian.AdditionalLibraryDirectories = "$(QTDIR)\\lib"; } if ((type & TemplateType.GUISystem) != 0) compiler.SetAdditionalIncludeDirectories(QtVSIPSettings.GetUicDirectory(envPro) + ";"); if ((type & TemplateType.PluginProject) != 0) { compiler.AddPreprocessorDefinition("QT_PLUGIN"); } bool isDebugConfiguration = false; if (config.Name.StartsWith("Release")) { compiler.AddPreprocessorDefinition("QT_NO_DEBUG,NDEBUG"); compiler.SetDebugInformationFormat(debugOption.debugDisabled); compiler.SetRuntimeLibrary(runtimeLibraryOption.rtMultiThreadedDLL); } else if (config.Name.StartsWith("Debug")) { isDebugConfiguration = true; compiler.SetOptimization(optimizeOption.optimizeDisabled); compiler.SetDebugInformationFormat(debugOption.debugEnabled); compiler.SetRuntimeLibrary(runtimeLibraryOption.rtMultiThreadedDebugDLL); } compiler.AddAdditionalIncludeDirectories( ".;" + "$(QTDIR)\\include;" + QtVSIPSettings.GetMocDirectory(envPro)); compiler.SetTreatWChar_tAsBuiltInType(false); if (linker != null) linker.GenerateDebugInformation = isDebugConfiguration; #if ENABLE_WINCE if (vi.IsWinCEVersion()) { compiler.SetWarningLevel(warningLevelOption.warningLevel_3); compiler.SetBufferSecurityCheck(isDebugConfiguration); DeploymentToolWrapper deploymentTool = DeploymentToolWrapper.Create(config); if (deploymentTool != null) { deploymentTool.AddWinCEMSVCStandardLib(isDebugConfiguration, dte); string signatureFile = vi.GetSignatureFile(); if (signatureFile != null) { Object postBuildEventToolObj = ((IVCCollection)config.Tools).Item("VCPostBuildEventTool"); VCPostBuildEventTool postBuildEventTool = postBuildEventToolObj as VCPostBuildEventTool; if (postBuildEventTool != null) { string cmdline = postBuildEventTool.CommandLine; if (cmdline == null) cmdline = ""; if (cmdline.Length > 0) postBuildEventTool.CommandLine += "\n"; cmdline += "signtool sign /F " + signatureFile + " \"$(TargetPath)\""; postBuildEventTool.CommandLine = cmdline; } } } IVCCollection tools = ((IVCCollection)config.Tools); object cst = tools.Item("VCCodeSignTool"); if (cst != null) { Type t = cst.GetType(); object r = t.InvokeMember("ExecutionBucket", System.Reflection.BindingFlags.GetProperty, null, cst, null); if (r != null) config.ExcludeBuckets = r.ToString(); } } #endif if (usePrecompiledHeader) UsePrecompiledHeaders(config); } if ((type & TemplateType.PluginProject) != 0) MarkAsDesignerPluginProject(); } public void MarkAsDesignerPluginProject() { Project.Globals["IsDesignerPlugin"] = true.ToString(); if (!Project.Globals.get_VariablePersists("IsDesignerPlugin")) Project.Globals.set_VariablePersists("IsDesignerPlugin", true); } public bool AddApplicationIcon(string iconFileName) { string projectName = vcPro.ItemName; string iconFile = vcPro.ProjectDirectory + "\\" + projectName + ".ico"; string rcFile = vcPro.ProjectDirectory + "\\" + projectName + ".rc"; try { if (!File.Exists(iconFile)) { File.Copy(iconFileName, iconFile); FileAttributes attribs = File.GetAttributes(iconFile); File.SetAttributes(iconFile, attribs & (~FileAttributes.ReadOnly)); } StreamWriter sw = null; if (!File.Exists(rcFile)) { sw = new StreamWriter(File.Create(rcFile)); sw.WriteLine("IDI_ICON1\t\tICON\t\tDISCARDABLE\t\"" + projectName + ".ico\"" + sw.NewLine); sw.Close(); } } catch (System.Exception e) { Messages.DisplayErrorMessage(e); return false; } vcPro.AddFile(rcFile); return true; } /// /// This function adds a uic4 build step to a given file. /// /// file public void AddUic4BuildStep(VCFile file) { try { string uiFile = this.GetUiGeneratedFileName(file.FullPath); string uiBaseName = file.Name.Remove(file.Name.LastIndexOf('.')); string uiFileMacro = uiFile.Replace(uiBaseName, ProjectMacros.Name); bool uiFileExists = GetFileFromProject(uiFile) != null; foreach (VCFileConfiguration config in (IVCCollection)file.FileConfigurations) { VCCustomBuildTool tool = HelperFunctions.GetCustomBuildTool(config); if (tool != null) { tool.AdditionalDependencies = Resources.uic4Command; tool.Description = "Uic'ing " + ProjectMacros.FileName + "..."; tool.Outputs = "\"" + uiFileMacro + "\""; tool.CommandLine = "\"" + Resources.uic4Command + "\" -o \"" + uiFileMacro + "\" \"" + ProjectMacros.Path + "\""; } VCConfiguration conf = config.ProjectConfiguration as VCConfiguration; CompilerToolWrapper compiler = CompilerToolWrapper.Create(conf); if (compiler != null && !uiFileExists) { string uiDir = QtVSIPSettings.GetUicDirectory(envPro); if (compiler.GetAdditionalIncludeDirectories().IndexOf(uiDir) < 0) compiler.AddAdditionalIncludeDirectories(uiDir); } } if (!uiFileExists) AddFileInFilter(Filters.GeneratedFiles(), uiFile); } catch { throw new QtVSException(SR.GetString("QtProject_CannotAddUicStep", file.FullPath)); } } /// /// Surrounds the argument by double quotes. /// Makes sure, that the trailing double quote is not escaped by a backslash. /// Such an escaping backslash may also appear as a macro value. /// private static string SafelyQuoteCommandLineArgument(string arg) { arg = "\"" + arg; if (arg.EndsWith("\\")) arg += "."; // make sure, that we don't escape the trailing double quote else if (arg.EndsWith(")")) arg += "\\."; // macro value could end with backslash. That would escape the trailing double quote. arg += "\""; return arg; } public string GetDefines(VCFileConfiguration conf) { List defineList = CompilerToolWrapper.Create(conf).PreprocessorDefinitions; VCConfiguration projectConfig = conf.ProjectConfiguration as VCConfiguration; defineList.AddRange(CompilerToolWrapper.Create(projectConfig).PreprocessorDefinitions); IVCCollection propertySheets = projectConfig.PropertySheets as IVCCollection; if (propertySheets != null) foreach (VCPropertySheet sheet in propertySheets) defineList.AddRange(GetDefinesFromPropertySheet(sheet)); string preprocessorDefines = ""; List alreadyAdded = new List(); Regex rxp = new Regex(@"\s|(\$\()"); foreach (string define in defineList) { if (!alreadyAdded.Contains(define)) { bool mustSurroundByDoubleQuotes = rxp.IsMatch(define); // Yes, a preprocessor definition can contain spaces or a macro name. // Example: PROJECTDIR=$(InputDir) if (mustSurroundByDoubleQuotes) { preprocessorDefines += " "; preprocessorDefines += SafelyQuoteCommandLineArgument("-D" + define); } else { preprocessorDefines += " -D" + define; } alreadyAdded.Add(define); } } return preprocessorDefines; } private List GetDefinesFromPropertySheet(VCPropertySheet sheet) { List defines = CompilerToolWrapper.Create(sheet).PreprocessorDefinitions; IVCCollection propertySheets = sheet.PropertySheets as IVCCollection; if (propertySheets != null) foreach (VCPropertySheet subSheet in propertySheets) defines.AddRange(GetDefinesFromPropertySheet(subSheet)); return defines; } private string GetIncludes(VCFileConfiguration conf) { List includeList = GetIncludesFromCompilerTool(CompilerToolWrapper.Create(conf)); VCConfiguration projectConfig = conf.ProjectConfiguration as VCConfiguration; includeList.AddRange(GetIncludesFromCompilerTool(CompilerToolWrapper.Create(projectConfig))); IVCCollection propertySheets = projectConfig.PropertySheets as IVCCollection; if (propertySheets != null) foreach (VCPropertySheet sheet in propertySheets) includeList.AddRange(GetIncludesFromPropertySheet(sheet)); string includes = ""; List alreadyAdded = new List(); foreach (string include in includeList) { if (!alreadyAdded.Contains(include)) { string incl = HelperFunctions.NormalizeRelativeFilePath(include); if (incl.Length > 0) { string cmdline = " "; cmdline += SafelyQuoteCommandLineArgument("-I" + incl); includes += cmdline; } alreadyAdded.Add(include); } } return includes; } private List GetIncludesFromPropertySheet(VCPropertySheet sheet) { List includeList = GetIncludesFromCompilerTool(CompilerToolWrapper.Create(sheet)); IVCCollection propertySheets = sheet.PropertySheets as IVCCollection; if (propertySheets != null) foreach (VCPropertySheet subSheet in propertySheets) includeList.AddRange(GetIncludesFromPropertySheet(subSheet)); return includeList; } private static List GetIncludesFromCompilerTool(CompilerToolWrapper compiler) { try { if (compiler.GetAdditionalIncludeDirectories() != null && compiler.GetAdditionalIncludeDirectories().Length > 0) { string[] includes = compiler.GetAdditionalIncludeDirectoriesList(); return new List(includes); } } catch { } return new List(); } private static bool IsDebugConfiguration(VCConfiguration conf) { VCLinkerTool linker = (VCLinkerTool)((IVCCollection)conf.Tools).Item("VCLinkerTool"); if (linker != null && linker.GenerateDebugInformation == true) return true; return false; } private string GetPCHMocOptions(VCFile file, CompilerToolWrapper compiler) { // As .moc files are included, we should not add anything there if (!HelperFunctions.HasHeaderFileExtension(file.Name)) return ""; string additionalMocOptions = "\"-f" + compiler.GetPrecompiledHeaderThrough().Replace('\\', '/') + "\" "; //Get mocDir without .\\ at the beginning of it string mocDir = QtVSIPSettings.GetMocDirectory(envPro); if (mocDir.StartsWith(".\\")) mocDir = mocDir.Substring(2); //Get the absolute path mocDir = vcPro.ProjectDirectory + mocDir; string relPathToFile = HelperFunctions.GetRelativePath(mocDir, file.FullPath).Replace('\\', '/'); additionalMocOptions += "\"-f" + relPathToFile + "\""; return additionalMocOptions; } /// /// Adds a moc step to a given file for this project. /// /// file public void AddMocStep(VCFile file) { try { string mocFileName = GetMocFileName(file.FullPath); if (mocFileName == null) return; bool hasDifferentMocFilePerConfig = QtVSIPSettings.HasDifferentMocFilePerConfig(envPro); bool hasDifferentMocFilePerPlatform = QtVSIPSettings.HasDifferentMocFilePerPlatform(envPro); bool mocableIsCPP = mocFileName.ToLower().EndsWith(".moc"); #if (VS2010 || VS2012 || VS2013) // Fresh C++ headers don't have a usable custom build tool. We must set the item type first. if (!mocableIsCPP && file.ItemType != "CustomBuild") file.ItemType = "CustomBuild"; #endif foreach (VCFileConfiguration config in (IVCCollection)file.FileConfigurations) { VCConfiguration vcConfig = config.ProjectConfiguration as VCConfiguration; VCPlatform platform = vcConfig.Platform as VCPlatform; string platformName = platform.Name; string mocRelPath = GetRelativeMocFilePath(file.FullPath, vcConfig.ConfigurationName, platformName); string subfilterName = null; if (mocRelPath.Contains(vcConfig.ConfigurationName)) subfilterName = vcConfig.ConfigurationName; if (mocRelPath.Contains(platformName)) { if (subfilterName != null) subfilterName += '_'; subfilterName += platformName; } VCFile mocFile = GetFileFromProject(mocRelPath); if (mocFile == null) { FileInfo fi = new FileInfo(this.VCProject.ProjectDirectory + "\\" + mocRelPath); if (!fi.Directory.Exists) fi.Directory.Create(); mocFile = AddFileInSubfilter(Filters.GeneratedFiles(), subfilterName, mocRelPath); #if (VS2010 || VS2012 || VS2013) if (mocFileName.ToLower().EndsWith(".moc")) { ProjectItem mocFileItem = mocFile.Object as ProjectItem; if (mocFileItem != null) HelperFunctions.EnsureCustomBuildToolAvailable(mocFileItem); } #endif } if (mocFile == null) throw new QtVSException(SR.GetString("QtProject_CannotAddMocStep", file.FullPath)); VCCustomBuildTool tool = null; string fileToMoc = null; if (!mocableIsCPP) { tool = HelperFunctions.GetCustomBuildTool(config); fileToMoc = ProjectMacros.Path; } else { VCFileConfiguration mocConf = GetVCFileConfigurationByName(mocFile, vcConfig.Name); tool = HelperFunctions.GetCustomBuildTool(mocConf); fileToMoc = HelperFunctions.GetRelativePath(vcPro.ProjectDirectory, file.FullPath); } if (tool == null) throw new QtVSException(SR.GetString("QtProject_CannotFindCustomBuildTool", file.FullPath)); if (hasDifferentMocFilePerPlatform && hasDifferentMocFilePerConfig) { foreach (VCFileConfiguration mocConf in (IVCCollection)mocFile.FileConfigurations) { VCConfiguration projectCfg = mocConf.ProjectConfiguration as VCConfiguration; if (projectCfg.Name != vcConfig.Name || (IsMoccedFileIncluded(file) && !mocableIsCPP)) { if (!mocConf.ExcludedFromBuild) mocConf.ExcludedFromBuild = true; } else { if (mocConf.ExcludedFromBuild != config.ExcludedFromBuild) mocConf.ExcludedFromBuild = config.ExcludedFromBuild; } } } else if (hasDifferentMocFilePerPlatform) { foreach (VCFileConfiguration mocConf in (IVCCollection)mocFile.FileConfigurations) { VCConfiguration projectCfg = mocConf.ProjectConfiguration as VCConfiguration; VCPlatform mocConfPlatform = projectCfg.Platform as VCPlatform; if (projectCfg.ConfigurationName != vcConfig.ConfigurationName) continue; bool exclude = mocConfPlatform.Name != platformName || (IsMoccedFileIncluded(file) && !mocableIsCPP); if (exclude) { if (mocConf.ExcludedFromBuild != exclude) mocConf.ExcludedFromBuild = exclude; } else { if (mocConf.ExcludedFromBuild != config.ExcludedFromBuild) mocConf.ExcludedFromBuild = config.ExcludedFromBuild; } } } else if (hasDifferentMocFilePerConfig) { foreach (VCFileConfiguration mocConf in (IVCCollection)mocFile.FileConfigurations) { VCConfiguration projectCfg = mocConf.ProjectConfiguration as VCConfiguration; VCPlatform mocConfPlatform = projectCfg.Platform as VCPlatform; if (platformName != mocConfPlatform.Name) continue; if (projectCfg.Name != vcConfig.Name || (IsMoccedFileIncluded(file) && !mocableIsCPP)) { if (!mocConf.ExcludedFromBuild) mocConf.ExcludedFromBuild = true; } else { if (mocConf.ExcludedFromBuild != config.ExcludedFromBuild) mocConf.ExcludedFromBuild = config.ExcludedFromBuild; } } } else { VCFileConfiguration moccedFileConfig = GetVCFileConfigurationByName(mocFile, config.Name); if (moccedFileConfig != null) { VCFile cppFile = GetCppFileForMocStep(file); if (cppFile != null && IsMoccedFileIncluded(cppFile)) { if (!moccedFileConfig.ExcludedFromBuild) { moccedFileConfig.ExcludedFromBuild = true; } } else if (moccedFileConfig.ExcludedFromBuild != config.ExcludedFromBuild) moccedFileConfig.ExcludedFromBuild = config.ExcludedFromBuild; } } string dps = tool.AdditionalDependencies; if (dps.IndexOf("\"" + Resources.moc4Command + "\"") < 0) { if (dps.Length > 0 && !dps.EndsWith(";")) dps += ";"; tool.AdditionalDependencies = dps + "\"" + Resources.moc4Command + "\";" + fileToMoc; } tool.Description = "Moc'ing " + file.Name + "..."; string inputMocFile = ProjectMacros.Path; if (mocableIsCPP) inputMocFile = file.RelativePath; string output = tool.Outputs; string outputMocFile = ""; string outputMocMacro = ""; string baseFileName = file.Name.Remove(file.Name.LastIndexOf('.')); string pattern = "(\"(.*\\\\" + mocFileName + ")\"|(\\S*" + mocFileName + "))"; System.Text.RegularExpressions.Regex regExp = new Regex(pattern); MatchCollection matchList = regExp.Matches(tool.Outputs.Replace(ProjectMacros.Name, baseFileName)); if (matchList.Count > 0) { if (matchList[0].Length > 0) { outputMocFile = matchList[0].ToString(); } else if (matchList[1].Length > 1) { outputMocFile = matchList[1].ToString(); } if (outputMocFile.StartsWith("\"")) outputMocFile = outputMocFile.Substring(1); if (outputMocFile.EndsWith("\"")) outputMocFile = outputMocFile.Substring(0, outputMocFile.Length-1); string outputMocPath = Path.GetDirectoryName(outputMocFile); string stringToReplace = Path.GetFileName(outputMocFile); outputMocMacro = outputMocPath + "\\" + stringToReplace.Replace(baseFileName, ProjectMacros.Name); } else { outputMocFile = GetRelativeMocFilePath(file.FullPath); string outputMocPath = Path.GetDirectoryName(outputMocFile); string stringToReplace = Path.GetFileName(outputMocFile); outputMocMacro = outputMocPath + "\\" + stringToReplace.Replace(baseFileName, ProjectMacros.Name); if (output.Length > 0 && !output.EndsWith(";")) output += ";"; tool.Outputs = output + "\"" + outputMocMacro + "\""; } string newCmdLine = "\"" + Resources.moc4Command + "\" " + QtVSIPSettings.GetMocOptions(envPro) + " \"" + inputMocFile + "\" -o \"" + outputMocMacro + "\""; // Tell moc to include the PCH header if we are using precompiled headers in the project CompilerToolWrapper compiler = CompilerToolWrapper.Create(vcConfig); if (compiler.GetUsePrecompiledHeader() != pchOption.pchNone) { newCmdLine += " " + GetPCHMocOptions(file, compiler); } QtVersionManager versionManager = QtVersionManager.The(); VersionInformation versionInfo = new VersionInformation(versionManager.GetInstallPath(envPro)); bool mocSupportsIncludes = (versionInfo.qtMajor == 4 && versionInfo.qtMinor >= 2) || versionInfo.qtMajor >= 5; string strDefinesIncludes = ""; VCFile cppPropertyFile; if (!mocableIsCPP) cppPropertyFile = GetCppFileForMocStep(file); else cppPropertyFile = GetCppFileForMocStep(mocFile); VCFileConfiguration defineIncludeConfig; if (cppPropertyFile != null) defineIncludeConfig = GetVCFileConfigurationByName(cppPropertyFile, config.Name); else // No file specific defines/includes but at least the project defines/includes are added defineIncludeConfig = config; strDefinesIncludes += GetDefines(defineIncludeConfig); strDefinesIncludes += GetIncludes(defineIncludeConfig); int cmdLineLength = newCmdLine.Length + strDefinesIncludes.Length + 1; if (cmdLineLength > HelperFunctions.GetMaximumCommandLineLength() && mocSupportsIncludes) { // Command line is too long. We must use an options file. string mocIncludeCommands = ""; string mocIncludeFile = "\"" + outputMocFile + ".inc\""; string redirectOp = " > "; int maxCmdLineLength = HelperFunctions.GetMaximumCommandLineLength() - (mocIncludeFile.Length + 1); string[] options = strDefinesIncludes.Split(' '); int i = options.Length - 1; for (; i >= 0; --i) { if (options[i].Length == 0) continue; mocIncludeCommands += "echo " + options[i] + redirectOp + mocIncludeFile + "\r\n"; cmdLineLength -= options[i].Length + 1; if (cmdLineLength < maxCmdLineLength) break; if (i == options.Length - 1) // first loop redirectOp = " >> "; } strDefinesIncludes = "@" + mocIncludeFile; for (int k = 0; k < i; ++k) if (options[k].Length > 0) strDefinesIncludes += " " + options[k]; newCmdLine = mocIncludeCommands + newCmdLine + " " + strDefinesIncludes; } else { newCmdLine = newCmdLine + " " + strDefinesIncludes; } if (tool.CommandLine.Trim().Length > 0) { string cmdLine = tool.CommandLine; // remove the moc option file commands { Regex rex = new Regex("^echo.+[.](moc|cpp)[.]inc\"\r\n", RegexOptions.Multiline); cmdLine = rex.Replace(cmdLine, ""); } Match m = System.Text.RegularExpressions.Regex.Match(cmdLine, @"(\S*moc.exe|""\S+:\\\.*moc.exe"")"); if (m.Success) { int start = m.Index; int end = cmdLine.IndexOf("&&", start); int a = cmdLine.IndexOf("\r\n", start); if ((a > -1 && a < end) || (end < 0 && a > -1)) end = a; if (end < 0) end = cmdLine.Length; tool.CommandLine = cmdLine.Replace(cmdLine.Substring(start, end - start), newCmdLine); } else { tool.CommandLine = cmdLine + "\r\n" + newCmdLine; } } else { tool.CommandLine = newCmdLine; } } } catch { throw new QtVSException(SR.GetString("QtProject_CannotAddMocStep", file.FullPath)); } } /// /// Helper function for AddMocStep. /// /// header or source file name /// True, if the file contains an include of the /// corresponding moc_xxx.cpp file. False in all other cases public bool IsMoccedFileIncluded(VCFile file) { bool isHeaderFile = HelperFunctions.HasHeaderFileExtension(file.FullPath); if (isHeaderFile || HelperFunctions.HasSourceFileExtension(file.FullPath)) { string srcName; if (isHeaderFile) srcName = file.FullPath.Substring(0, file.FullPath.LastIndexOf(".")) + ".cpp"; else srcName = file.FullPath; VCFile f = GetFileFromProject(srcName); CxxStreamReader sr = null; if (f != null) { try { string strLine; sr = new CxxStreamReader(f.FullPath); string baseName = file.Name.Substring(0, file.Name.LastIndexOf(".")); while ((strLine = sr.ReadLine()) != null) { if (strLine.IndexOf("#include \"moc_" + baseName + ".cpp\"") != -1 || strLine.IndexOf("#include ") != -1) { sr.Close(); return true; } } sr.Close(); } catch (System.Exception) { // do nothing if (sr != null) sr.Close(); return false; } } } return false; } public bool HasMocStep(VCFile file) { return HasMocStep(file, null); } public bool HasMocStep(VCFile file, string mocOutDir) { if (HelperFunctions.HasHeaderFileExtension(file.Name)) { return CheckForCommand(file, "moc.exe"); } else if (HelperFunctions.HasSourceFileExtension(file.Name)) { foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { string mocFileName = ""; if (mocOutDir == null) { VCPlatform platform = config.Platform as VCPlatform; mocFileName = GetRelativeMocFilePath(file.Name, config.ConfigurationName, platform.Name); } else { string fileName = GetMocFileName(file.FullPath); if (fileName != null) { mocOutDir = mocOutDir.Replace("$(ConfigurationName)", config.ConfigurationName); VCPlatform platform = config.Platform as VCPlatform; mocOutDir = mocOutDir.Replace("$(PlatformName)", platform.Name); mocFileName = mocOutDir + "\\" + fileName; } } VCFile mocFile = GetFileFromProject(mocFileName); if (mocFileName != null) return CheckForCommand(mocFile, Resources.moc4Command); } } return false; } public static bool HasUicStep(VCFile file) { return CheckForCommand(file, Resources.uic4Command); } private static bool CheckForCommand(VCFile file, string cmd) { if (file == null) return false; foreach (VCFileConfiguration config in (IVCCollection)file.FileConfigurations) { VCCustomBuildTool tool = HelperFunctions.GetCustomBuildTool(config); if (tool == null) return false; if (tool.CommandLine != null && tool.CommandLine.Contains(cmd)) return true; } return false; } public void RefreshRccSteps() { Messages.PaneMessage(dte, "\r\n=== Update rcc steps ==="); List files = GetResourceFiles(); VCFilter vcFilter = FindFilterFromGuid(Filters.GeneratedFiles().UniqueIdentifier); if (vcFilter != null) { IVCCollection filterFiles = (IVCCollection)vcFilter.Files; List filesToDelete = new List(); foreach (VCFile rmFile in filterFiles) { if (rmFile.Name.ToLower().StartsWith("qrc_")) filesToDelete.Add(rmFile); } foreach (VCFile rmFile in filesToDelete) { RemoveFileFromFilter(rmFile, vcFilter); HelperFunctions.DeleteEmptyParentDirs(rmFile); } } foreach (VCFile file in files) { Messages.PaneMessage(dte, "Update rcc step for " + file.Name + "."); RccOptions options = new RccOptions(envPro, file); UpdateRccStep(file, options); } Messages.PaneMessage(dte, "\r\n=== " + files.Count.ToString() + " rcc steps updated. ===\r\n"); } public void RefreshRccSteps(string oldRccDir) { RefreshRccSteps(); UpdateCompilerIncludePaths(oldRccDir, QtVSIPSettings.GetRccDirectory(envPro)); } public void UpdateRccStep(string fileName, RccOptions rccOpts) { VCFile file = (VCFile)((IVCCollection)vcPro.Files).Item(fileName); UpdateRccStep(file, rccOpts); } public void UpdateRccStep(VCFile qrcFile, RccOptions rccOpts) { VCProject vcpro = (VCProject)qrcFile.project; EnvDTE.DTE dteObject = ((EnvDTE.Project)vcpro.Object).DTE; QtProject qtPro = QtProject.Create(vcpro); QrcParser parser = new QrcParser(qrcFile.FullPath); string filesInQrcFile = ProjectMacros.Path; if (parser.parse()) { FileInfo fi = new FileInfo(qrcFile.FullPath); string qrcDir = fi.Directory.FullName + "\\"; foreach (QrcPrefix prfx in parser.Prefixes) { foreach (QrcItem itm in prfx.Items) { string relativeQrcItemPath = HelperFunctions.GetRelativePath(this.vcPro.ProjectDirectory, qrcDir + itm.Path); filesInQrcFile += ";" + relativeQrcItemPath; try { VCFile addedFile = qtPro.AddFileInFilter(Filters.ResourceFiles(), relativeQrcItemPath, true); QtProject.ExcludeFromAllBuilds(addedFile); } catch { /* it's not possible to add all kinds of files */ } } } } string nameOnly = HelperFunctions.RemoveFileNameExtension(new FileInfo(qrcFile.FullPath)); string qrcCppFile = QtVSIPSettings.GetRccDirectory(envPro) + "\\" + "qrc_" + nameOnly + ".cpp"; try { foreach (VCFileConfiguration vfc in (IVCCollection)qrcFile.FileConfigurations) { RccOptions rccOptsCfg = rccOpts; string cmdLine = ""; VCCustomBuildTool cbt = HelperFunctions.GetCustomBuildTool(vfc); cbt.AdditionalDependencies = filesInQrcFile; cbt.Description = "Rcc'ing " + ProjectMacros.FileName + "..."; cbt.Outputs = qrcCppFile.Replace(nameOnly, ProjectMacros.Name); cmdLine += "\"" + Resources.rcc4Command + "\"" + " -name \"" + ProjectMacros.Name + "\""; if (rccOptsCfg == null) rccOptsCfg = HelperFunctions.ParseRccOptions(cbt.CommandLine, qrcFile); if (rccOptsCfg.CompressFiles) { cmdLine += " -threshold " + rccOptsCfg.CompressThreshold.ToString(); cmdLine += " -compress " + rccOptsCfg.CompressLevel.ToString(); } else { cmdLine += " -no-compress"; } cmdLine += " \"" + ProjectMacros.Path + "\" -o " + cbt.Outputs; cbt.CommandLine = cmdLine; } AddFileInFilter(Filters.GeneratedFiles(), qrcCppFile, true); } catch(System.Exception /*e*/) { Messages.PaneMessage(dteObject, "*** WARNING (RCC): Couldn't add rcc step"); } } public void RemoveRccStep(VCFile file) { if (file == null) return; try { string relativeQrcFilePath = file.RelativePath; FileInfo qrcFileInfo = new FileInfo(ProjectDir + "\\" + relativeQrcFilePath); if (qrcFileInfo.Exists) { RccOptions opts = new RccOptions(Project, file); string qrcCppFile = QtVSIPSettings.GetRccDirectory(envPro) + "\\" + opts.OutputFileName; VCFile generatedFile = GetFileFromProject(qrcCppFile); if (generatedFile != null) RemoveFileFromFilter(generatedFile, Filters.GeneratedFiles()); } } catch (System.Exception e) { Messages.DisplayWarningMessage(e); } } static public void ExcludeFromAllBuilds(VCFile file) { if (file == null) return; foreach (VCFileConfiguration conf in (IVCCollection)file.FileConfigurations) if (!conf.ExcludedFromBuild) conf.ExcludedFromBuild = true; } /// /// Removes the custom build step of a given file. /// /// file public void RemoveMocStep(VCFile file) { try { if (!HasMocStep(file)) return; if (HelperFunctions.HasHeaderFileExtension(file.Name)) { foreach (VCFileConfiguration config in (IVCCollection)file.FileConfigurations) { VCCustomBuildTool tool = HelperFunctions.GetCustomBuildTool(config); if (tool == null) continue; string cmdLine = tool.CommandLine; if (cmdLine.Length > 0) { Regex rex = new Regex(@"(\S*moc.exe|""\S+:\\\.*moc.exe"")"); while (true) { Match m = rex.Match(cmdLine); if (!m.Success) break; int start = m.Index; int end = cmdLine.IndexOf("&&", start); int a = cmdLine.IndexOf("\r\n", start); if ((a > -1 && a < end) || (end < 0 && a > -1)) end = a; if (end < 0) end = cmdLine.Length; cmdLine = cmdLine.Remove(start, end - start).Trim(); if (cmdLine.StartsWith("&&")) cmdLine = cmdLine.Remove(0, 2).Trim(); } tool.CommandLine = cmdLine; } Regex reg = new Regex("Moc'ing .+\\.\\.\\."); string addDepends = tool.AdditionalDependencies; addDepends = System.Text.RegularExpressions.Regex.Replace(addDepends, @"(\S*moc.exe|""\S+:\\\.*moc.exe"")", ""); addDepends = addDepends.Replace(file.RelativePath, ""); tool.AdditionalDependencies = ""; tool.Description = reg.Replace(tool.Description, ""); tool.Description = tool.Description.Replace("MOC " + file.Name, ""); string baseFileName = file.Name.Remove(file.Name.LastIndexOf('.')); string pattern = "(\"(.*\\\\" + GetMocFileName(file.FullPath) + ")\"|(\\S*" + GetMocFileName(file.FullPath) + "))"; string outputMocFile = null; System.Text.RegularExpressions.Regex regExp = new Regex(pattern); tool.Outputs = tool.Outputs.Replace(ProjectMacros.Name, baseFileName); MatchCollection matchList = regExp.Matches(tool.Outputs); if (matchList.Count > 0) { if (matchList[0].Length > 0) { outputMocFile = matchList[0].ToString(); } else if (matchList[1].Length > 1) { outputMocFile = matchList[1].ToString(); } } tool.Outputs = System.Text.RegularExpressions.Regex.Replace(tool.Outputs, pattern, "", RegexOptions.Multiline|RegexOptions.IgnoreCase); tool.Outputs = System.Text.RegularExpressions.Regex.Replace(tool.Outputs, @"\s*;\s*;\s*", ";", RegexOptions.Multiline); tool.Outputs = System.Text.RegularExpressions.Regex.Replace(tool.Outputs, @"(^\s*;|\s*;\s*$)", "", RegexOptions.Multiline); if (outputMocFile != null) { if (outputMocFile.StartsWith("\"")) outputMocFile = outputMocFile.Substring(1); if (outputMocFile.EndsWith("\"")) outputMocFile = outputMocFile.Substring(0, outputMocFile.Length-1); outputMocFile = outputMocFile.Replace("$(ConfigurationName)", config.Name.Substring(0, config.Name.IndexOf('|'))); outputMocFile = outputMocFile.Replace("$(PlatformName)", config.Name.Remove(0, config.Name.IndexOf('|') + 1)); } VCFile mocFile = GetFileFromProject(outputMocFile); if (mocFile != null) RemoveFileFromFilter(mocFile, Filters.GeneratedFiles()); } } else { if (QtVSIPSettings.HasDifferentMocFilePerConfig(envPro) || QtVSIPSettings.HasDifferentMocFilePerPlatform(envPro)) { foreach (VCFileConfiguration config in (IVCCollection)file.FileConfigurations) { string mocFileName = GetMocFileName(file.Name); VCFile mocFile = GetGeneratedMocFile(mocFileName, config); if (mocFile != null) RemoveFileFromFilter(mocFile, Filters.GeneratedFiles()); } } else { string mocFileName = GetMocFileName(file.Name); VCFile mocFile = GetGeneratedMocFile(mocFileName, null); if (mocFile != null) RemoveFileFromFilter(mocFile, Filters.GeneratedFiles()); } } } catch { throw new QtVSException(SR.GetString("QtProject_CannotRemoveMocStep", file.FullPath)); } } public void RemoveUiHeaderFile(VCFile file) { if (file == null) return; try { string headerFile = GetUiGeneratedFileName(file.Name); VCFile hFile = GetFileFromProject(headerFile); if (hFile != null) RemoveFileFromFilter(hFile, Filters.GeneratedFiles()); } catch (System.Exception e) { Messages.DisplayWarningMessage(e); } } public void RemoveUic4BuildStep(VCFile file) { if (file == null) return; foreach (VCFileConfiguration config in (IVCCollection)file.FileConfigurations) { VCCustomBuildTool tool = HelperFunctions.GetCustomBuildTool(config); tool.AdditionalDependencies = ""; tool.Description = ""; tool.CommandLine = ""; tool.Outputs = ""; } RemoveUiHeaderFile(file); } public List GetResourceFiles() { List qrcFiles = new List(); foreach (VCFile f in (IVCCollection)VCProject.Files) { if (f.Extension == ".qrc") qrcFiles.Add(f); } return qrcFiles; } /// /// Returns the file if it can be found, otherwise null. /// /// filter name /// relative file path to the project /// public VCFile GetFileFromFilter(FakeFilter filter, string fileName) { VCFilter vcfilter = FindFilterFromGuid(filter.UniqueIdentifier); // try with name as well if (vcfilter == null) vcfilter = FindFilterFromName(filter.Name); if (vcfilter == null) return null; try { FileInfo fi = null; if (Path.IsPathRooted(fileName)) fi = new FileInfo(fileName); else fi = new FileInfo(ProjectDir + "\\" + fileName); if (fi == null) return null; foreach (VCFile file in (IVCCollection)vcfilter.Files) { if (file.MatchName(fi.FullName, true)) return file; } } catch {} return null; } /// /// Returns the file (VCFile) specified by the file name from a given /// project. /// /// project /// file name (relative path) /// public VCFile GetFileFromProject(string fileName) { return GetFileFromProject(fileName, true); } public VCFile GetFileFromProject(string fileName, bool beStrict) { VCFile vcfile = null; fileName = HelperFunctions.NormalizeRelativeFilePath(fileName); string nf = fileName; if (!HelperFunctions.IsAbsoluteFilePath(fileName)) nf = HelperFunctions.NormalizeFilePath(vcPro.ProjectDirectory + "\\" + fileName); nf = nf.ToLower(); foreach (VCFile f in (IVCCollection)vcPro.Files) { if (f.FullPath.ToLower() == nf) return f; } if (beStrict || vcfile != null) return vcfile; FileInfo fi = new FileInfo(fileName); foreach (VCFile f in (IVCCollection)vcPro.Files) { if (f.Name.ToLower() == fi.Name.ToLower()) return f; } return null; } /// /// Returns the files (List) specified by the file name from a given /// project. /// /// project /// file name (relative path) /// public System.Collections.Generic.List GetFilesFromProject(string fileName) { System.Collections.Generic.List tmpList = new System.Collections.Generic.List(); fileName = HelperFunctions.NormalizeRelativeFilePath(fileName); FileInfo fi = new FileInfo(fileName); foreach (VCFile f in (IVCCollection)vcPro.Files) { if (f.Name.ToLower() == fi.Name.ToLower()) tmpList.Add(f); } return tmpList; } public System.Collections.Generic.List GetAllFilesFromFilter(VCFilter filter) { System.Collections.Generic.List tmpList = new System.Collections.Generic.List(); foreach (VCFile f in (IVCCollection)filter.Files) { tmpList.Add(f); } foreach (VCFilter subfilter in (IVCCollection)filter.Filters) foreach (VCFile file in GetAllFilesFromFilter(subfilter)) tmpList.Add(file); return tmpList; } /// /// Adds a file to a filter. If the filter doesn't exist yet, it /// will be created. (Doesn't check for duplicates) /// /// fake filter /// relative file name /// A VCFile object of the added file. public VCFile AddFileInFilter(FakeFilter filter, string fileName) { return AddFileInFilter(filter, fileName, false); } public void RemoveItem(ProjectItem item) { foreach (ProjectItem tmpFilter in this.Project.ProjectItems) { if (tmpFilter.Name == item.Name) { tmpFilter.Remove(); return; } foreach (ProjectItem tmpItem in tmpFilter.ProjectItems) if (tmpItem.Name == item.Name) { tmpItem.Remove(); return; } } } /// /// Adds a file to a filter. If the filter doesn't exist yet, it /// will be created. /// /// fake filter /// relative file name /// true if we don't want duplicated files /// A VCFile object of the added file. public VCFile AddFileInFilter(FakeFilter filter, string fileName, bool checkForDuplicates) { return AddFileInSubfilter(filter, null, fileName, checkForDuplicates); } public VCFile AddFileInSubfilter(FakeFilter filter, string subfilterName, string fileName) { return AddFileInSubfilter(filter, subfilterName, fileName, false); } public VCFile AddFileInSubfilter(FakeFilter filter, string subfilterName, string fileName, bool checkForDuplicates) { try { VCFilter vfilt = FindFilterFromGuid(filter.UniqueIdentifier); if (vfilt == null) { if (!vcPro.CanAddFilter(filter.Name)) { // check if user already created this filter... then add guid vfilt = FindFilterFromName(filter.Name); if (vfilt == null) throw new QtVSException(SR.GetString("QtProject_CannotAddFilter", filter.Name)); } else { vfilt = (VCFilter)vcPro.AddFilter(filter.Name); } vfilt.UniqueIdentifier = filter.UniqueIdentifier; vfilt.Filter = filter.Filter; vfilt.ParseFiles = filter.ParseFiles; } if (!string.IsNullOrEmpty(subfilterName)) { string lowerSubFilterName = subfilterName.ToLower(); bool subfilterFound = false; foreach (VCFilter subfilt in vfilt.Filters as IVCCollection) { if (subfilt.Name.ToLower() == lowerSubFilterName) { vfilt = subfilt; subfilterFound = true; break; } } if (subfilterFound) { // Do filter names differ in upper/lower case? if (subfilterName != vfilt.Name) { try { // Try to rename the filter for aesthetic reasons. vfilt.Name = subfilterName; } catch { // Renaming didn't work. We don't care. } } } if (!subfilterFound) { if (!vfilt.CanAddFilter(subfilterName)) { throw new QtVSException(SR.GetString("QtProject_CannotAddFilter", filter.Name)); } else { vfilt = (VCFilter)vfilt.AddFilter(subfilterName); } vfilt.Filter = "cpp;moc"; vfilt.SourceControlFiles = false; } } if (checkForDuplicates) { // check if file exists in filter already VCFile vcFile = GetFileFromFilter(filter, fileName); if (vcFile != null) return vcFile; } if (vfilt.CanAddFile(fileName)) return (VCFile)(vfilt.AddFile(fileName)); else throw new QtVSException(SR.GetString("QtProject_CannotAddFile", fileName)); } catch { throw new QtVSException(SR.GetString("QtProject_CannotAddFile", fileName)); } } /// /// Removes a file from the filter. /// This file will be deleted! /// /// project /// file public void RemoveFileFromFilter(VCFile file, FakeFilter filter) { try { VCFilter vfilt = FindFilterFromGuid(filter.UniqueIdentifier); if (vfilt == null) vfilt = FindFilterFromName(filter.Name); if (vfilt == null) return; RemoveFileFromFilter(file, vfilt); } catch { throw new QtVSException(SR.GetString("QtProject_CannotRemoveFile", file.Name)); } } /// /// Removes a file from the filter. /// This file will be deleted! /// /// project /// file public void RemoveFileFromFilter(VCFile file, VCFilter filter) { try { filter.RemoveFile(file); FileInfo fi = new FileInfo(file.FullPath); if (fi.Exists) fi.Delete(); } catch { } IVCCollection subfilters = (IVCCollection)filter.Filters; for (int i = subfilters.Count; i > 0; i--) { try { VCFilter subfilter = (VCFilter)subfilters.Item(i); RemoveFileFromFilter(file, subfilter); } catch { } } } public void MoveFileToDeletedFolder(VCFile vcfile) { FileInfo srcFile = new FileInfo(vcfile.FullPath); if (!srcFile.Exists) return; string destFolder = vcPro.ProjectDirectory + "\\Deleted\\"; string destName = destFolder + vcfile.Name.Replace(".","_") + ".bak"; int fileNr = 0; try { if (!Directory.Exists(destFolder)) Directory.CreateDirectory(destFolder); while(File.Exists(destName)) { fileNr++; destName = destName.Substring(0,destName.LastIndexOf(".")) + ".b"; if (fileNr>9) destName += fileNr.ToString(); else destName += "0" + fileNr.ToString(); } srcFile.MoveTo(destName); } catch(System.Exception e) { Messages.DisplayWarningMessage(e, SR.GetString("QtProject_DeletedFolderFullOrProteced")); } } public VCFilter FindFilterFromName(string filtername) { try { foreach (VCFilter vcfilt in (IVCCollection)vcPro.Filters) { if (vcfilt.Name.ToLower() == filtername.ToLower()) { return vcfilt; } } return null; } catch { throw new QtVSException(SR.GetString("QtProject_CannotFindFilter")); } } public VCFilter FindFilterFromGuid(string filterguid) { try { foreach (VCFilter vcfilt in (IVCCollection)vcPro.Filters) { if (vcfilt.UniqueIdentifier != null && vcfilt.UniqueIdentifier.ToLower() == filterguid.ToLower()) { return vcfilt; } } return null; } catch { throw new QtVSException(SR.GetString("QtProject_CannotFindFilter")); } } public VCFilter AddFilterToProject(FakeFilter filter) { try { VCFilter vfilt = FindFilterFromGuid(filter.UniqueIdentifier); if (vfilt == null) { if (!vcPro.CanAddFilter(filter.Name)) { vfilt = FindFilterFromName(filter.Name); if (vfilt == null) throw new QtVSException(SR.GetString("QtProject_ProjectCannotAddFilter", filter.Name)); } else { vfilt = (VCFilter)vcPro.AddFilter(filter.Name); } vfilt.UniqueIdentifier = filter.UniqueIdentifier; vfilt.Filter = filter.Filter; vfilt.ParseFiles = filter.ParseFiles; } return vfilt; } catch { throw new QtVSException(SR.GetString("QtProject_ProjectCannotAddResourceFilter")); } } public void AddDirectories() { try { // resource directory FileInfo fi = new FileInfo(envPro.FullName); DirectoryInfo dfi = new DirectoryInfo(fi.DirectoryName + "\\" + Resources.resourceDir); dfi.Create(); // generated files directory dfi = new DirectoryInfo(fi.DirectoryName + "\\" + Resources.generatedFilesDir); dfi.Create(); } catch { throw new QtVSException(SR.GetString("QtProject_CannotCreateResourceDir")); } AddFilterToProject(Filters.ResourceFiles()); } public void Finish() { try { EnvDTE.Window solutionExplorer = dte.Windows.Item(Constants.vsWindowKindSolutionExplorer); if (solutionExplorer != null) { EnvDTE.UIHierarchy hierarchy = (EnvDTE.UIHierarchy)solutionExplorer.Object; EnvDTE.UIHierarchyItems projects = hierarchy.UIHierarchyItems.Item(1).UIHierarchyItems; foreach (EnvDTE.UIHierarchyItem itm in projects) { if (itm.Name == envPro.Name) { foreach (EnvDTE.UIHierarchyItem i in itm.UIHierarchyItems) { if (i.Name == Filters.GeneratedFiles().Name) i.UIHierarchyItems.Expanded = false; } break; } } } } catch {} } public bool IsDesignerPluginProject() { bool b = false; if (Project.Globals.get_VariablePersists("IsDesignerPlugin")) { string s = (string)Project.Globals["IsDesignerPlugin"]; try { b = bool.Parse(s); } catch {} } return b; } /// /// Adds a file to a specified filter in a project. /// /// VCProject /// full name of the file to add /// name of the file in the project (relative to the project directory) /// filter /// VCFile public VCFile AddFileToProject(string destName, FakeFilter filter) { VCFile file = null; if (filter != null) file = AddFileInFilter(filter, destName); else file = (VCFile)vcPro.AddFile(destName); if (file == null) return null; if (HelperFunctions.HasHeaderFileExtension(file.Name)) { foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); if (compiler == null) continue; string[] paths = compiler.GetAdditionalIncludeDirectoriesList(); FileInfo fi = new FileInfo(file.FullPath); string relativePath = HelperFunctions.GetRelativePath(this.ProjectDir, fi.Directory.ToString()); string fixedRelativePath = FixFilePathForComparison(relativePath); bool pathFound = false; foreach (string p in paths) { if (FixFilePathForComparison(p) == fixedRelativePath) { pathFound = true; break; } } if (!pathFound) compiler.AddAdditionalIncludeDirectories(relativePath); } } return file; } /// /// adjusts the whitespaces, tabs in the given file according to VS settings /// /// public void AdjustWhitespace(string file) { // only replace whitespaces in known types if (!HelperFunctions.HasSourceFileExtension(file) && !HelperFunctions.HasHeaderFileExtension(file) && !file.EndsWith(".ui")) return; try { EnvDTE.Properties prop = dte.get_Properties("TextEditor", "C/C++"); long tabSize = Convert.ToInt64(prop.Item("TabSize").Value); bool insertTabs = Convert.ToBoolean(prop.Item("InsertTabs").Value); string oldValue = insertTabs ? " " : "\t"; string newValue = insertTabs ? "\t" : GetWhitespaces(tabSize); List list = new List(); StreamReader reader = new StreamReader(file); string line = reader.ReadLine(); while (line != null) { if (line.StartsWith(oldValue)) line = line.Replace(oldValue, newValue); list.Add(line); line = reader.ReadLine(); } reader.Close(); StreamWriter writer = new StreamWriter(file); foreach (string l in list) writer.WriteLine(l); writer.Close(); } catch (Exception e) { Messages.DisplayErrorMessage(SR.GetString("QtProject_CannotAdjustWhitespaces", e.ToString())); } } private static string GetWhitespaces(long size) { string whitespaces = null; for (long i = 0; i < size; ++i) { whitespaces += " "; } return whitespaces; } /// /// Copy a file to the projects folder. Does not add the file to the project. /// /// full name of the file to add /// name of the file in the project (relative to the project directory) /// full name of the destination file public string CopyFileToProject(string srcFile, string destName) { return CopyFileToFolder(srcFile, vcPro.ProjectDirectory, destName); } public static string CopyFileToFolder(string srcFile, string destFolder, string destName) { string fullDestName = destFolder + "\\" + destName; FileInfo fi = new FileInfo(fullDestName); bool replace = true; if (File.Exists(fullDestName)) { if (DialogResult.No == MessageBox.Show(SR.GetString("QtProject_FileExistsInProjectFolder", destName) , Resources.msgBoxCaption, MessageBoxButtons.YesNo, MessageBoxIcon.Question)) { replace = false; } } if (replace) { if (!fi.Directory.Exists) fi.Directory.Create(); File.Copy(srcFile, fullDestName, true); FileAttributes attribs = File.GetAttributes(fullDestName); File.SetAttributes(fullDestName, attribs & (~FileAttributes.ReadOnly)); } return fi.FullName; } public static void ReplaceTokenInFile(string file, string token, string replacement) { string text; try { StreamReader reader = new StreamReader(file); text = reader.ReadToEnd(); reader.Close(); } catch(System.Exception e) { Messages.DisplayErrorMessage( SR.GetString("QtProject_CannotReplaceTokenRead", token, replacement, e.ToString())); return; } try { if (token.ToUpper() == "%PRE_DEF%" && !Char.IsLetter(replacement[0])) replacement = "_" + replacement; text = text.Replace(token, replacement); StreamWriter writer = new StreamWriter(file); writer.Write(text); writer.Close(); } catch(System.Exception e) { Messages.DisplayErrorMessage( SR.GetString("QtProject_CannotReplaceTokenWrite", token, replacement, e.ToString())); } } public void RepairGeneratedFilesStructure() { DeleteGeneratedFiles(); foreach (VCFile file in (IVCCollection)vcPro.Files) { if (!HelperFunctions.HasHeaderFileExtension(file.Name) && !HelperFunctions.HasSourceFileExtension(file.Name)) continue; if (HelperFunctions.HasQObjectDeclaration(file)) { RemoveMocStep(file); AddMocStep(file); } } } public void TranslateFilterNames() { IVCCollection filters = vcPro.Filters as IVCCollection; if (filters == null) return; foreach (VCFilter filter in filters) { if (filter.Name == "Form Files") filter.Name = Filters.FormFiles().Name; if (filter.Name == "Generated Files") filter.Name = Filters.GeneratedFiles().Name; if (filter.Name == "Header Files") filter.Name = Filters.HeaderFiles().Name; if (filter.Name == "Resource Files") filter.Name = Filters.ResourceFiles().Name; if (filter.Name == "Source Files") filter.Name = Filters.SourceFiles().Name; } } public string CreateQrcFile(string className, string destName) { string fullDestName = vcPro.ProjectDirectory + "\\" + destName; if (!File.Exists(fullDestName)) { FileStream s = File.Open(fullDestName, FileMode.CreateNew); if (s.CanWrite) { StreamWriter sw = new StreamWriter(s); sw.WriteLine(""); sw.WriteLine(" "); sw.WriteLine(" "); sw.WriteLine(""); sw.Close(); } s.Close(); FileAttributes attribs = File.GetAttributes(fullDestName); File.SetAttributes(fullDestName, attribs & (~FileAttributes.ReadOnly)); } FileInfo fi = new FileInfo(fullDestName); return fi.FullName; } public static void EnableSection(string file, string sectionName, bool enable) { string text = ""; bool firstLine = true; try { StreamReader reader = new StreamReader(file); string line = reader.ReadLine(); bool skip = false; while (line != null) { if (line.StartsWith("#Begin_" + sectionName)) { skip = !enable; } else if (line.StartsWith("#End_" + sectionName)) { skip = false; } else if (!skip) { if (firstLine) { text = line; firstLine = false; } else { text += "\r\n" + line; } } line = reader.ReadLine(); } reader.Close(); } catch(System.Exception e) { Messages.DisplayErrorMessage(SR.GetString("QtProject_CannotEnableSectionRead", sectionName, e.ToString())); return; } try { StreamWriter writer = new StreamWriter(file); writer.Write(text); writer.Close(); } catch(System.Exception e) { Messages.DisplayErrorMessage(SR.GetString("QtProject_CannotEnableSectionWrite", sectionName, e.ToString())); } } public void AddActiveQtBuildStep(string version) { foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { string idlFile = "\"$(IntDir)/" + envPro.Name + ".idl\""; string tblFile = "\"$(IntDir)/" + envPro.Name + ".tlb\""; VCPostBuildEventTool tool = (VCPostBuildEventTool)((IVCCollection)config.Tools).Item("VCPostBuildEventTool"); string idc = "$(QTDIR)\\bin\\idc.exe \"$(TargetPath)\" /idl " + idlFile + " -version " + version; string midl = "midl " + idlFile + " /tlb " + tblFile; string idc2 = "$(QTDIR)\\bin\\idc.exe \"$(TargetPath)\" /tlb " + tblFile; string idc3 = "$(QTDIR)\\bin\\idc.exe \"$(TargetPath)\" /regserver"; tool.CommandLine = idc + "\r\n" + midl + "\r\n" + idc2 + "\r\n" + idc3; tool.Description = ""; VCLinkerTool linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); VCLibrarianTool librarian = (VCLibrarianTool)((IVCCollection)config.Tools).Item("VCLibrarianTool"); if (linker != null) { linker.Version = version; linker.ModuleDefinitionFile = envPro.Name + ".def"; } else { librarian.ModuleDefinitionFile = envPro.Name + ".def"; } } } private void UpdateCompilerIncludePaths(string oldDir, string newDir) { string fixedOldDir = FixFilePathForComparison(oldDir); string[] dirs = new string[] { FixFilePathForComparison(QtVSIPSettings.GetUicDirectory(envPro)), FixFilePathForComparison(QtVSIPSettings.GetMocDirectory(envPro)), FixFilePathForComparison(QtVSIPSettings.GetRccDirectory(envPro))}; bool oldDirIsUsed = false; foreach (string dir in dirs) { if (dir == fixedOldDir) { oldDirIsUsed = true; break; } } List incList = new List(); foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); if (compiler == null) continue; List paths = compiler.AdditionalIncludeDirectories; if (paths.Count == 0) continue; if (!oldDirIsUsed) for (int i = paths.Count - 1; i >= 0; --i) if (FixFilePathForComparison(paths[i]) == fixedOldDir) paths.RemoveAt(i); incList.Clear(); foreach (string path in paths) { string tmp = HelperFunctions.NormalizeRelativeFilePath(path); if (tmp.Length > 0 && !incList.Contains(tmp)) incList.Add(tmp); } bool alreadyThere = false; string fixedNewDir = FixFilePathForComparison(newDir); foreach (string include in incList) { if (FixFilePathForComparison(include) == fixedNewDir) { alreadyThere = true; break; } } if (!alreadyThere) incList.Add(HelperFunctions.NormalizeRelativeFilePath(newDir)); compiler.AdditionalIncludeDirectories = incList; } } private static string FixFilePathForComparison(string path) { path = HelperFunctions.NormalizeRelativeFilePath(path); return path.ToLower(); } public void UpdateUicSteps(string oldUicDir, bool update_inc_path) { Messages.PaneMessage(dte, "\r\n=== Update uic steps ==="); VCFilter vcFilter = FindFilterFromGuid(Filters.GeneratedFiles().UniqueIdentifier); if (vcFilter != null) { IVCCollection filterFiles = (IVCCollection)vcFilter.Files; for (int i = filterFiles.Count; i > 0; i--) { VCFile file = (VCFile)filterFiles.Item(i); if (file.Name.ToLower().StartsWith("ui_")) { RemoveFileFromFilter(file, vcFilter); HelperFunctions.DeleteEmptyParentDirs(file); } } } int updatedFiles = 0; int j = 0; VCFile[] files = new VCFile[((IVCCollection)vcPro.Files).Count]; foreach (VCFile file in (IVCCollection)vcPro.Files) { files[j++] = file; } foreach (VCFile file in files) { if (file.Name.EndsWith(".ui") && !IsUic3File(file)) { AddUic4BuildStep(file); Messages.PaneMessage(dte, "Update uic step for " + file.Name + "."); ++updatedFiles; } } if (update_inc_path) { UpdateCompilerIncludePaths(oldUicDir, QtVSIPSettings.GetUicDirectory(envPro)); } Messages.PaneMessage(dte, "\r\n=== " + updatedFiles.ToString() + " uic steps updated. ===\r\n"); } private static bool IsUic3File(VCFile file) { foreach (VCFileConfiguration config in (IVCCollection)file.FileConfigurations) { VCCustomBuildTool tool = HelperFunctions.GetCustomBuildTool(config); if (tool == null) return false; if (tool.CommandLine.IndexOf("uic3.exe") > -1) return true; } return false; } public bool UsePrecompiledHeaders(VCConfiguration config) { CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); return UsePrecompiledHeaders(compiler); } private bool UsePrecompiledHeaders(CompilerToolWrapper compiler) { try { compiler.SetUsePrecompiledHeader(pchOption.pchUseUsingSpecific); string pcHeaderThrough = GetPrecompiledHeaderThrough(); if (string.IsNullOrEmpty(pcHeaderThrough)) pcHeaderThrough = "stdafx.h"; compiler.SetPrecompiledHeaderThrough(pcHeaderThrough); string pcHeaderFile = GetPrecompiledHeaderFile(); if (string.IsNullOrEmpty(pcHeaderFile)) pcHeaderFile = ".\\$(ConfigurationName)/" + Project.Name + ".pch"; compiler.SetPrecompiledHeaderFile(pcHeaderFile); return true; } catch { return false; } } public bool UsesPrecompiledHeaders() { foreach (VCConfiguration config in vcPro.Configurations as IVCCollection) { if (!UsesPrecompiledHeaders(config)) return false; } return true; } public static bool UsesPrecompiledHeaders(VCConfiguration config) { CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); return UsesPrecompiledHeaders(compiler); } private static bool UsesPrecompiledHeaders(CompilerToolWrapper compiler) { try { if (compiler.GetUsePrecompiledHeader() != pchOption.pchNone) return true; } catch { } return false; } public string GetPrecompiledHeaderThrough() { foreach (VCConfiguration config in vcPro.Configurations as IVCCollection) { string header = GetPrecompiledHeaderThrough(config); if (header != null) return header; } return null; } public static string GetPrecompiledHeaderThrough(VCConfiguration config) { CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); return GetPrecompiledHeaderThrough(compiler); } private static string GetPrecompiledHeaderThrough(CompilerToolWrapper compiler) { try { string header = compiler.GetPrecompiledHeaderThrough(); if (!string.IsNullOrEmpty(header)) return header.ToLower(); } catch { } return null; } public string GetPrecompiledHeaderFile() { foreach (VCConfiguration config in vcPro.Configurations as IVCCollection) { string file = GetPrecompiledHeaderFile(config); if (!string.IsNullOrEmpty(file)) return file; } return null; } public static string GetPrecompiledHeaderFile(VCConfiguration config) { CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); return GetPrecompiledHeaderFile(compiler); } private static string GetPrecompiledHeaderFile(CompilerToolWrapper compiler) { try { string file = compiler.GetPrecompiledHeaderFile(); if (!string.IsNullOrEmpty(file)) return file; } catch { } return null; } public static void SetPCHOption(VCFile vcFile, pchOption option) { foreach (VCFileConfiguration config in vcFile.FileConfigurations as IVCCollection) { CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); compiler.SetUsePrecompiledHeader(option); } } private static VCFileConfiguration GetVCFileConfigurationByName(VCFile file, string configName) { foreach (VCFileConfiguration cfg in (IVCCollection)file.FileConfigurations) { if (cfg.Name == configName) return cfg; } return null; } /// /// Searches for the generated file inside the "Generated Files" filter. /// The function looks for the given filename and uses the fileConfig's /// ConfigurationName and Platform if moc directory contains $(ConfigurationName) /// and/or $(PlatformName). /// Otherwise it just uses the "Generated Files" filter /// /// /// /// private VCFile GetGeneratedMocFile(string fileName, VCFileConfiguration fileConfig) { if (QtVSIPSettings.HasDifferentMocFilePerConfig(envPro) || QtVSIPSettings.HasDifferentMocFilePerPlatform(envPro)) { VCConfiguration projectConfig = (VCConfiguration)fileConfig.ProjectConfiguration; string configName = projectConfig.ConfigurationName; string platformName = ((VCPlatform)projectConfig.Platform).Name; VCFilter generatedFiles = FindFilterFromGuid(Filters.GeneratedFiles().UniqueIdentifier); if (generatedFiles == null) return null; foreach (VCFilter filt in (IVCCollection)generatedFiles.Filters) if (filt.Name == configName + "_" + platformName || filt.Name == configName || filt.Name == platformName) foreach (VCFile filtFile in (IVCCollection)filt.Files) if (filtFile.FullPath.EndsWith(fileName)) return filtFile; //If a project from the an AddIn prior to 1.1.0 was loaded, the generated files are located directly //in the generated files filter. string relativeMocPath = QtVSIPSettings.GetMocDirectory(envPro, configName, platformName) + '\\' + fileName; //Remove .\ at the beginning of the mocPath if (relativeMocPath.StartsWith(".\\")) relativeMocPath = relativeMocPath.Remove(0, 2); foreach (VCFile filtFile in (IVCCollection)generatedFiles.Files) if (filtFile.FullPath.EndsWith(relativeMocPath, StringComparison.OrdinalIgnoreCase)) return filtFile; } else { VCFilter generatedFiles = FindFilterFromGuid(Filters.GeneratedFiles().UniqueIdentifier); foreach (VCFile filtFile in (IVCCollection)generatedFiles.Files) if (filtFile.FullPath.EndsWith('\\' + fileName)) return filtFile; } return null; } public void RefreshMocSteps() { foreach (VCFile vcfile in (IVCCollection)vcPro.Files) { RefreshMocStep(vcfile, false); } } public void RefreshMocStep(VCFile vcfile) { RefreshMocStep(vcfile, true); } /// /// Updates the moc command line for the given header or source file /// containing the Q_OBJECT macro. /// If the function is called from a property change for a single file /// (singleFile = true) we may have to look for the according header /// file and refresh the moc step for this file, if it contains Q_OBJECT. /// /// private void RefreshMocStep(VCFile vcfile, bool singleFile) { bool isHeaderFile = HelperFunctions.HasHeaderFileExtension(vcfile.FullPath); if (!isHeaderFile && !HelperFunctions.HasSourceFileExtension(vcfile.FullPath)) return; if (mocCmdChecker == null) mocCmdChecker = new MocCmdChecker(); foreach (VCFileConfiguration config in (IVCCollection)vcfile.FileConfigurations) { try { VCCustomBuildTool tool = null; VCFile mocable = null; if (isHeaderFile) { mocable = vcfile; tool = HelperFunctions.GetCustomBuildTool(config); } else { string mocFileName = GetMocFileName(vcfile.FullPath); VCFile mocFile = GetGeneratedMocFile(mocFileName, config); if (mocFile != null) { VCFileConfiguration mocFileConfig = GetVCFileConfigurationByName(mocFile, config.Name); tool = HelperFunctions.GetCustomBuildTool(mocFileConfig); mocable = mocFile; } // It is possible that the function was called from a source file's property change, it is possible that // we have to obtain the tool from the according header file if (tool == null && singleFile) { string headerName = vcfile.FullPath.Remove(vcfile.FullPath.LastIndexOf('.')) + ".h"; mocFileName = GetMocFileName(headerName); mocFile = GetGeneratedMocFile(mocFileName, config); if (mocFile != null) { mocable = GetFileFromProject(headerName); VCFileConfiguration customBuildConfig = GetVCFileConfigurationByName(mocable, config.Name); tool = HelperFunctions.GetCustomBuildTool(customBuildConfig); } } } if (tool == null || tool.CommandLine.ToLower().IndexOf("moc.exe") == -1) continue; VCFile srcMocFile = GetSourceFileForMocStep(mocable); VCFile cppFile = GetCppFileForMocStep(mocable); if (srcMocFile == null) continue; bool mocableIsCPP = (srcMocFile == cppFile); string pchParameters = null; VCFileConfiguration cppConfig = GetVCFileConfigurationByName(cppFile, config.Name); CompilerToolWrapper compiler = CompilerToolWrapper.Create(cppConfig); if (compiler.GetUsePrecompiledHeader() != pchOption.pchNone) pchParameters = GetPCHMocOptions(srcMocFile, compiler); string outputFileName = QtVSIPSettings.GetMocDirectory(envPro) + "\\"; if (mocableIsCPP) { outputFileName += ProjectMacros.Name; outputFileName += ".moc"; } else { outputFileName += "moc_"; outputFileName += ProjectMacros.Name; outputFileName += ".cpp"; } string newCmdLine = mocCmdChecker.NewCmdLine(tool.CommandLine, GetIncludes(cppConfig), GetDefines(cppConfig), QtVSIPSettings.GetMocOptions(envPro), srcMocFile.RelativePath, pchParameters, outputFileName); // The tool's command line automatically gets a trailing "\r\n". // We have to remove it to make the check below work. string origCommandLine = tool.CommandLine; if (origCommandLine.EndsWith("\r\n")) origCommandLine = origCommandLine.Substring(0, origCommandLine.Length - 2); if (newCmdLine != null && newCmdLine != origCommandLine) { // We have to delete the old moc file in order to trigger custom build step. string configName = config.Name.Remove(config.Name.IndexOf("|")); string platformName = config.Name.Substring(config.Name.IndexOf("|") + 1); string projectPath = envPro.FullName.Remove(envPro.FullName.LastIndexOf('\\')); string mocRelPath = GetRelativeMocFilePath(srcMocFile.FullPath, configName, platformName); string mocPath = Path.Combine(projectPath, mocRelPath); if (File.Exists(mocPath)) File.Delete(mocPath); tool.CommandLine = newCmdLine; } } catch { Messages.PaneMessage(dte, "ERROR: failed to refresh moc step for " + vcfile.ItemName); } } } public void OnExcludedFromBuildChanged(VCFile vcFile, VCFileConfiguration vcFileCfg) { // Update the ExcludedFromBuild flags of the mocced file // according to the ExcludedFromBuild flag of the mocable source file. string moccedFileName = GetMocFileName(vcFile.Name); if (string.IsNullOrEmpty(moccedFileName)) return; VCFile moccedFile = GetGeneratedMocFile(moccedFileName, vcFileCfg); if (moccedFile != null) { VCFile cppFile = null; if (HelperFunctions.HasHeaderFileExtension(vcFile.Name)) cppFile = GetCppFileForMocStep(vcFile); VCFileConfiguration moccedFileConfig = GetVCFileConfigurationByName(moccedFile, vcFileCfg.Name); if (moccedFileConfig != null) { if (cppFile != null && IsMoccedFileIncluded(cppFile)) { if (!moccedFileConfig.ExcludedFromBuild) { moccedFileConfig.ExcludedFromBuild = true; } } else if (moccedFileConfig.ExcludedFromBuild != vcFileCfg.ExcludedFromBuild) moccedFileConfig.ExcludedFromBuild = vcFileCfg.ExcludedFromBuild; } } } /// /// Helper function for RefreshMocStep. /// /// /// private VCFile GetSourceFileForMocStep(VCFile file) { if (HelperFunctions.HasHeaderFileExtension(file.Name)) return file; string fileName = file.Name; if (fileName.ToLower().EndsWith(".moc")) { fileName = fileName.Substring(0, fileName.Length - 4) + ".cpp"; if (fileName.Length > 0) { foreach (VCFile f in (IVCCollection)vcPro.Files) { if (f.FullPath.ToLower().EndsWith("\\" + fileName.ToLower())) return f; } } } return null; } /// /// Helper function for Refresh/UpdateMocStep. /// /// /// private VCFile GetCppFileForMocStep(VCFile file) { string fileName = null; if (HelperFunctions.HasHeaderFileExtension(file.Name) || file.Name.EndsWith(".moc")) fileName = file.Name.Remove(file.Name.LastIndexOf('.')) + ".cpp"; if (fileName != null && fileName.Length > 0) { foreach (VCFile f in (IVCCollection)vcPro.Files) { if (f.FullPath.ToLower().EndsWith("\\" + fileName.ToLower())) return f; } } return null; } public void UpdateMocSteps(string oldMocDir) { Messages.PaneMessage(dte, "\r\n=== Update moc steps ==="); List orgFiles = new List(); List abandonedMocFiles = new List(); VCFilter vcFilter = FindFilterFromGuid(Filters.GeneratedFiles().UniqueIdentifier); if (vcFilter != null) { List generatedFiles = GetAllFilesFromFilter(vcFilter); for (int i = generatedFiles.Count - 1; i >= 0; i--) { VCFile file = generatedFiles[i]; string fileName = null; if (file.Name.ToLower().StartsWith("moc_")) { fileName = file.Name.Substring(4, file.Name.Length - 8) + ".h"; } else if (file.Name.ToLower().EndsWith(".moc")) { fileName = file.Name.Substring(0, file.Name.Length - 4) + ".cpp"; } if (fileName != null) { bool found = false; foreach (VCFile f in (IVCCollection)vcPro.Files) { if (f.FullPath.ToLower().EndsWith("\\" + fileName.ToLower())) { if (!orgFiles.Contains(f) && HasMocStep(f, oldMocDir)) orgFiles.Add(f); RemoveFileFromFilter(file, vcFilter); HelperFunctions.DeleteEmptyParentDirs(file); found = true; break; } } if (!found) { // We can't find foo.h for moc_foo.cpp or // we can't find foo.cpp for foo.moc, thus we put the // filename moc_foo.cpp / foo.moc into an error list. abandonedMocFiles.Add(file.Name); } } } } UpdateCompilerIncludePaths(oldMocDir, QtVSIPSettings.GetMocDirectory(envPro)); foreach (VCFile file in orgFiles) { try { RemoveMocStep(file); AddMocStep(file); } catch (QtVSException e) { Messages.PaneMessage(dte, e.Message); continue; } Messages.PaneMessage(dte, "Moc step updated successfully for " + file.Name + "."); } foreach (string s in abandonedMocFiles) Messages.PaneMessage(dte, "Moc step update failed for " + s + ". Reason: Could not determine source file for moccing."); Messages.PaneMessage(dte, "\r\n=== Moc steps updated. Successful: " + orgFiles.Count.ToString() + " Failed: " + abandonedMocFiles.Count.ToString() + " ===\r\n"); CleanupFilter(vcFilter); } private void Clean() { SolutionConfigurations solutionConfigs = envPro.DTE.Solution.SolutionBuild.SolutionConfigurations; List> backup = new List>(); foreach (SolutionConfiguration config in solutionConfigs) { SolutionContexts solutionContexts = config.SolutionContexts; if (solutionContexts == null) continue; foreach (SolutionContext context in solutionContexts) { backup.Add(new KeyValuePair(context, context.ShouldBuild)); if (envPro.FullName.Contains(context.ProjectName) && context.PlatformName == envPro.ConfigurationManager.ActiveConfiguration.PlatformName) context.ShouldBuild = true; else context.ShouldBuild = false; } } envPro.DTE.Solution.SolutionBuild.Clean(true); foreach (KeyValuePair item in backup) item.Key.ShouldBuild = item.Value; } private void CleanupFilter(VCFilter filter) { IVCCollection subFilters = filter.Filters as IVCCollection; if (subFilters == null) return; for (int i = subFilters.Count; i > 0; i--) { VCFilter subFilter = subFilters.Item(i)as VCFilter; IVCCollection subFilterFilters = subFilter.Filters as IVCCollection; if (subFilterFilters == null) continue; CleanupFilter(subFilter); bool filterOrFileFound = false; foreach (object itemObject in subFilter.Items as IVCCollection) { if (itemObject is VCFilter || itemObject is VCFile) { filterOrFileFound = true; break; } } if (!filterOrFileFound) { filter.RemoveFilter(subFilter); } } } /// /// Changes the Qt version of this project. /// /// the current Qt version /// the new Qt version we want to change to /// is set to true if a new Project object has been created /// true, if the operation performed successfully public bool ChangeQtVersion(string oldVersion, string newVersion, ref bool newProjectCreated) { newProjectCreated = false; QtVersionManager versionManager = QtVersionManager.The(); VersionInformation viOld = versionManager.GetVersionInfo(oldVersion); VersionInformation viNew = versionManager.GetVersionInfo(newVersion); string vsPlatformNameOld = null; if (viOld != null) vsPlatformNameOld = viOld.GetVSPlatformName(); string vsPlatformNameNew = viNew.GetVSPlatformName(); bool bRefreshMocSteps = (vsPlatformNameNew != vsPlatformNameOld); try { if (vsPlatformNameOld != vsPlatformNameNew) { if (!SelectSolutionPlatform(vsPlatformNameNew) || !HasPlatform(vsPlatformNameNew)) { CreatePlatform(vsPlatformNameOld, vsPlatformNameNew, viOld, viNew, ref newProjectCreated); bRefreshMocSteps = false; UpdateMocSteps(QtVSIPSettings.GetMocDirectory(envPro)); } } ConfigurationManager configManager = envPro.ConfigurationManager; if (configManager.ActiveConfiguration.PlatformName != vsPlatformNameNew) { string projectName = envPro.FullName; envPro.Save(null); dte.Solution.Remove(envPro); envPro = dte.Solution.AddFromFile(projectName, false); dte = envPro.DTE; vcPro = envPro.Object as VCProject; } } catch { Messages.DisplayErrorMessage(SR.GetString("CannotChangeQtVersion")); return false; } // We have to delete the generated files because of // major differences between the platforms or Qt-Versions. if (vsPlatformNameOld != vsPlatformNameNew || viOld.qtPatch != viNew.qtPatch || viOld.qtMinor != viNew.qtMinor || viOld.qtMajor != viNew.qtMajor) { DeleteGeneratedFiles(); Clean(); } if (bRefreshMocSteps) RefreshMocSteps(); SetQtEnvironment(newVersion); UpdateModules(viOld, viNew); versionManager.SaveProjectQtVersion(envPro, newVersion, vsPlatformNameNew); return true; } public bool HasPlatform(string platformName) { foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { VCPlatform platform = (VCPlatform)config.Platform; if (platform.Name == platformName) { return true; } } return false; } public bool SelectSolutionPlatform(string platformName) { foreach (SolutionConfiguration solutionCfg in dte.Solution.SolutionBuild.SolutionConfigurations) { SolutionContexts contexts = solutionCfg.SolutionContexts; for (int i = 1; i <= contexts.Count; ++i) { SolutionContext ctx = null; try { ctx = contexts.Item(i); } catch (System.ArgumentException) { // This may happen if we encounter an unloaded project. continue; } if (ctx.PlatformName == platformName && solutionCfg.Name == dte.Solution.SolutionBuild.ActiveConfiguration.Name) { solutionCfg.Activate(); return true; } } } return false; } public void RemovePlatform(string platformName) { try { ConfigurationManager cfgMgr = envPro.ConfigurationManager; cfgMgr.DeletePlatform(platformName); } catch { } } public void CreatePlatform(string oldPlatform, string newPlatform, VersionInformation viOld, VersionInformation viNew, ref bool newProjectCreated) { try { ConfigurationManager cfgMgr = envPro.ConfigurationManager; cfgMgr.AddPlatform(newPlatform, oldPlatform, true); vcPro.AddPlatform(newPlatform); newProjectCreated = false; } catch { // That stupid ConfigurationManager can't handle platform names // containing dots (e.g. "Windows Mobile 5.0 Pocket PC SDK (ARMV4I)") // So we have to do it the nasty way... string projectFileName = envPro.FullName; envPro.Save(null); dte.Solution.Remove(envPro); AddPlatformToVCProj(projectFileName, oldPlatform, newPlatform); envPro = dte.Solution.AddFromFile(projectFileName, false); vcPro = (VCProject)envPro.Object; newProjectCreated = true; } // update the platform settings foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { VCPlatform vcplatform = (VCPlatform)config.Platform; if (vcplatform.Name == newPlatform) { if (viOld != null) RemovePlatformDependencies(config, viOld); SetupConfiguration(config, viNew); } } SelectSolutionPlatform(newPlatform); } public static void RemovePlatformDependencies(VCConfiguration config, VersionInformation viOld) { CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); SimpleSet minuend = new SimpleSet(compiler.PreprocessorDefinitions); SimpleSet subtrahend = new SimpleSet(viOld.GetQMakeConfEntry("DEFINES").Split(new char[] { ' ', '\t' })); compiler.SetPreprocessorDefinitions(minuend.Minus(subtrahend).JoinElements(',')); } public void SetupConfiguration(VCConfiguration config, VersionInformation viNew) { bool isWinPlatform = (!viNew.IsWinCEVersion()); CompilerToolWrapper compiler = CompilerToolWrapper.Create(config); SimpleSet ppdefs = new SimpleSet(compiler.PreprocessorDefinitions); ICollection newPPDefs = viNew.GetQMakeConfEntry("DEFINES").Split(new char[] { ' ', '\t' }); compiler.SetPreprocessorDefinitions(ppdefs.Union(newPPDefs).JoinElements(',')); #if ENABLE_WINCE // search prepocessor definitions for Qt modules and add deployment settings if (!isWinPlatform) { DeploymentToolWrapper deploymentTool = DeploymentToolWrapper.Create(config); if (deploymentTool != null) { deploymentTool.Clear(); deploymentTool.AddWinCEMSVCStandardLib(IsDebugConfiguration(config), dte); List availableQtModules = QtModules.Instance.GetAvailableModuleInformation(); foreach (string s in ppdefs.Elements) { foreach (QtModuleInfo moduleInfo in availableQtModules) { if (moduleInfo.Defines.Contains(s)) AddDeploySettings(deploymentTool, moduleInfo.ModuleId, config, null, viNew); } } } } #endif VCLinkerTool linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); if (linker == null) return; if (isWinPlatform) linker.SubSystem = subSystemOption.subSystemWindows; else linker.SubSystem = subSystemOption.subSystemNotSet; SetTargetMachine(linker, viNew); } #if ENABLE_WINCE private void AddDeploySettings(DeploymentToolWrapper deploymentTool, QtModule module, VCConfiguration config, QtModuleInfo moduleInfo, VersionInformation versionInfo) { // for static Qt builds it doesn't make sense // to add deployment settings for Qt modules if (versionInfo.IsStaticBuild()) return; if (moduleInfo == null) moduleInfo = QtModules.Instance.ModuleInformation(module); if (moduleInfo == null || !moduleInfo.HasDLL) return; if (deploymentTool == null) deploymentTool = DeploymentToolWrapper.Create(config); if (deploymentTool == null) return; string destDir = deploymentTool.RemoteDirectory; const string qtSrcDir = "$(QTDIR)\\lib"; string filename = moduleInfo.GetDllFileName(IsDebugConfiguration(config)); if (deploymentTool.GetAdditionalFiles().IndexOf(filename) < 0) deploymentTool.Add(filename, qtSrcDir, destDir); // add dependent modules foreach (QtModule dependentModule in moduleInfo.dependentModules) AddDeploySettings(deploymentTool, dependentModule, config, null, versionInfo); } private void RemoveDeploySettings(DeploymentToolWrapper deploymentTool, QtModule module, VCConfiguration config, QtModuleInfo moduleInfo) { if (moduleInfo == null) moduleInfo = QtModules.Instance.ModuleInformation(module); if (deploymentTool == null) deploymentTool = DeploymentToolWrapper.Create(config); if (deploymentTool == null) return; string destDir = deploymentTool.RemoteDirectory; const string qtSrcDir = "$(QTDIR)\\lib"; string filename = moduleInfo.GetDllFileName(IsDebugConfiguration(config)); if (deploymentTool.GetAdditionalFiles().IndexOf(filename) >= 0) deploymentTool.Remove(filename, qtSrcDir, destDir); // remove dependent modules foreach (QtModule dependentModule in moduleInfo.dependentModules) { if (!HasModule(dependentModule)) RemoveDeploySettings(deploymentTool, dependentModule, config, null); } } private static void RemoveQtDeploys(VCConfiguration config) { DeploymentToolWrapper deploymentTool = DeploymentToolWrapper.Create(config); if (deploymentTool == null) return; string additionalFiles = deploymentTool.GetAdditionalFiles(); additionalFiles = Regex.Replace(additionalFiles, "Qt[^\\|]*\\|[^\\|]*\\|[^\\|]*\\|[^;^$]*[;$]{0,1}", ""); if (additionalFiles.EndsWith(";")) additionalFiles = additionalFiles.Substring(0, additionalFiles.Length - 1); deploymentTool.SetAdditionalFiles(additionalFiles); } #endif private void DeleteGeneratedFiles() { FakeFilter genFilter = Filters.GeneratedFiles(); VCFilter genVCFilter = FindFilterFromGuid(genFilter.UniqueIdentifier); if (genVCFilter == null) return; bool error = false; error = DeleteFilesFromFilter(genVCFilter); if (error) Messages.PaneMessage(dte, SR.GetString("DeleteGeneratedFilesError")); } private bool DeleteFilesFromFilter(VCFilter filter) { bool error = false; foreach (VCFile f in filter.Files as IVCCollection) { try { FileInfo fi = new FileInfo(f.FullPath); if (fi.Exists) fi.Delete(); HelperFunctions.DeleteEmptyParentDirs(fi.Directory.ToString()); } catch { error = true; } } foreach (VCFilter filt in filter.Filters as IVCCollection) if (DeleteFilesFromFilter(filt)) error = true; return error; } public void RemoveGeneratedFiles(string fileName) { FileInfo fi = new FileInfo(fileName); int lastIndex = fileName.LastIndexOf(fi.Extension); string baseName = fi.Name.Remove(lastIndex, fi.Extension.Length); string delName = null; if (HelperFunctions.HasHeaderFileExtension(fileName)) delName = "moc_" + baseName + ".cpp"; else if (HelperFunctions.HasSourceFileExtension(fileName) && !fileName.ToLower().StartsWith("moc_")) delName = baseName + ".moc"; else if (fileName.ToLower().EndsWith(".ui")) delName = "ui_" + baseName + ".h"; else if (fileName.ToLower().EndsWith(".qrc")) delName = "qrc_" + baseName + ".cpp"; if (delName != null) { foreach (VCFile delFile in GetFilesFromProject(delName)) RemoveFileFromFilter(delFile, Filters.GeneratedFiles()); } } public void RemoveResFilesFromGeneratedFilesFilter() { List filesToRemove = new List(); VCFilter generatedFiles = FindFilterFromGuid(Filters.GeneratedFiles().UniqueIdentifier); if (generatedFiles == null) return; foreach (VCFile filtFile in (IVCCollection)generatedFiles.Files) if (filtFile.FullPath.ToLower().EndsWith(".res")) filesToRemove.Add(filtFile); foreach (VCFile resFile in filesToRemove) resFile.Remove(); } static private void AddPlatformToVCProj(string projectFileName, string oldPlatformName, string newPlatformName) { string tempFileName = Path.GetTempFileName(); FileInfo fi = new FileInfo(projectFileName); fi.CopyTo(tempFileName, true); XmlDocument myXmlDocument = new XmlDocument(); myXmlDocument.Load(tempFileName); AddPlatformToVCProj(myXmlDocument, oldPlatformName, newPlatformName); myXmlDocument.Save(projectFileName); fi = new FileInfo(tempFileName); fi.Delete(); } static private void AddPlatformToVCProj(XmlDocument doc, string oldPlatformName, string newPlatformName) { XmlNode vsProj = doc.DocumentElement.SelectSingleNode("/VisualStudioProject"); XmlNode platforms = vsProj.SelectSingleNode("Platforms"); if (platforms == null) { platforms = doc.CreateElement("Platforms"); vsProj.AppendChild(platforms); } XmlNode platform = platforms.SelectSingleNode("Platform[@Name='" + newPlatformName + "']"); if (platform == null) { platform = doc.CreateElement("Platform"); ((XmlElement)platform).SetAttribute("Name", newPlatformName); platforms.AppendChild(platform); } XmlNode configurations = vsProj.SelectSingleNode("Configurations"); XmlNodeList cfgList = configurations.SelectNodes("Configuration[@Name='Debug|" + oldPlatformName + "'] | " + "Configuration[@Name='Release|" + oldPlatformName + "']"); foreach (XmlNode oldCfg in cfgList) { XmlElement newCfg = (XmlElement)oldCfg.Clone(); newCfg.SetAttribute("Name", oldCfg.Attributes["Name"].Value.Replace(oldPlatformName, newPlatformName)); configurations.AppendChild(newCfg); } const string fileCfgPath = "Files/Filter/File/FileConfiguration"; XmlNodeList fileCfgList = vsProj.SelectNodes(fileCfgPath + "[@Name='Debug|" + oldPlatformName + "'] | " + fileCfgPath + "[@Name='Release|" + oldPlatformName + "']"); foreach (XmlNode oldCfg in fileCfgList) { XmlElement newCfg = (XmlElement)oldCfg.Clone(); newCfg.SetAttribute("Name", oldCfg.Attributes["Name"].Value.Replace(oldPlatformName, newPlatformName)); oldCfg.ParentNode.AppendChild(newCfg); } } static private void SetTargetMachine(VCLinkerTool linker, VersionInformation versionInfo) { String qMakeLFlagsWindows = versionInfo.GetQMakeConfEntry("QMAKE_LFLAGS_WINDOWS"); Regex rex = new Regex("/MACHINE:(\\S+)"); Match match = rex.Match(qMakeLFlagsWindows); if (match.Success) { linker.TargetMachine = HelperFunctions.TranslateMachineType(match.Groups[1].Value); } else { string platformName = versionInfo.GetVSPlatformName(); if (platformName == "Win32") linker.TargetMachine = machineTypeOption.machineX86; else if (platformName == "x64") linker.TargetMachine = machineTypeOption.machineAMD64; else linker.TargetMachine = machineTypeOption.machineNotSet; } String subsystemOption = ""; String linkerOptions = linker.AdditionalOptions; if (linkerOptions == null) linkerOptions = ""; rex = new Regex("(/SUBSYSTEM:\\S+)"); match = rex.Match(qMakeLFlagsWindows); if (match.Success) subsystemOption = match.Groups[1].Value; match = rex.Match(linkerOptions); if (match.Success) { linkerOptions = rex.Replace(linkerOptions, subsystemOption); } else { if (linkerOptions.Length > 0) linkerOptions += " "; linkerOptions += subsystemOption; } linker.AdditionalOptions = linkerOptions; } public VCConfiguration GetActiveVCConfiguration() { string activeConfigName = Project.ConfigurationManager.ActiveConfiguration.ConfigurationName; return (VCConfiguration)((IVCCollection)VCProject.Configurations).Item(activeConfigName); } public void CollapseFilter(string filterName) { UIHierarchy solutionExplorer = (UIHierarchy)dte.Windows.Item(Constants.vsext_wk_SProjectWindow).Object; if (solutionExplorer.UIHierarchyItems.Count == 0) return; dte.SuppressUI = true; UIHierarchyItem projectItem = FindProjectHierarchyItem(solutionExplorer); if (projectItem != null) { HelperFunctions.CollapseFilter(projectItem, solutionExplorer, filterName); } dte.SuppressUI = false; } private UIHierarchyItem FindProjectHierarchyItem(UIHierarchy hierarchy) { if (hierarchy.UIHierarchyItems.Count == 0) return null; UIHierarchyItem solution = hierarchy.UIHierarchyItems.Item(1); UIHierarchyItem projectItem = null; foreach (UIHierarchyItem solutionItem in solution.UIHierarchyItems) { projectItem = FindProjectHierarchyItem(solutionItem); if (projectItem != null) break; } return projectItem; } private UIHierarchyItem FindProjectHierarchyItem(UIHierarchyItem root) { UIHierarchyItem projectItem = null; try { if (root.Name == envPro.Name) return root; #if VS2005 bool expansionState = root.UIHierarchyItems.Expanded; #endif foreach (UIHierarchyItem childItem in root.UIHierarchyItems) { projectItem = FindProjectHierarchyItem(childItem); if (projectItem != null) break; } #if VS2005 root.UIHierarchyItems.Expanded = expansionState; #endif } catch { } return projectItem; } /// /// Gets the Qt version of the project /// public string GetQtVersion() { return QtVersionManager.The().GetProjectQtVersion(envPro); } /// /// Sets the Qt environment for the project's Qt version. /// public void SetQtEnvironment() { SetQtEnvironment(QtVersionManager.The().GetProjectQtVersion(envPro)); } /// /// Sets the Qt environment for the given Qt version. /// public void SetQtEnvironment(string qtVersion) { SetQtEnvironment(qtVersion, ""); } /// /// Sets the Qt environment for the given Qt version. /// public void SetQtEnvironment(string qtVersion, string solutionConfig) { if (string.IsNullOrEmpty(qtVersion)) return; string qtDir = null; if (qtVersion != "$(QTDIR)") qtDir = QtVersionManager.The().GetInstallPath(qtVersion); HelperFunctions.SetEnvironmentVariableEx("QTDIR", qtDir); #if (VS2010 || VS2012 || VS2013) try { var propertyAccess = (IVCBuildPropertyStorage)vcPro; VCProject vcprj = envPro.Object as VCProject; // Get platform name from given solution configuration // or if not available take the active configuration String activePlatformName = ""; if (solutionConfig == null || solutionConfig.Length == 0) { // First get active configuration cause not given as parameter EnvDTE.Configuration activeConf = envPro.ConfigurationManager.ActiveConfiguration; solutionConfig = activeConf.ConfigurationName + "|" + activeConf.PlatformName; activePlatformName = activeConf.PlatformName; } else { activePlatformName = solutionConfig.Split('|')[1]; } // Find all configurations for platform and set property for all of them // This is to get QTDIR property set for all configurations same time so // we can be sure it is set and is equal between debug and release foreach (VCConfiguration conf in vcprj.Configurations as IVCCollection) { VCPlatform cur_platform = conf.Platform as VCPlatform; if (cur_platform.Name == activePlatformName) { string cur_solution = conf.ConfigurationName + "|" + cur_platform.Name; propertyAccess.SetPropertyValue("QTDIR", cur_solution, "UserFile", qtDir); } } } catch (Exception) { Messages.PaneMessage(envPro.DTE, SR.GetString("QtProject_CannotAccessUserFile", vcPro.ItemName)); } #endif HelperFunctions.SetDebuggingEnvironment(envPro); } } }