diff options
-rw-r--r-- | src/qtprojectlib/MsBuildProject.cs | 347 | ||||
-rw-r--r-- | src/qtprojectlib/ProjectImporter.cs | 22 | ||||
-rw-r--r-- | src/qtprojectlib/QtMsBuild.cs | 69 | ||||
-rw-r--r-- | src/qtprojectlib/QtProject.cs | 6 | ||||
-rw-r--r-- | src/qtprojectlib/QtProjectLib.csproj | 1 | ||||
-rw-r--r-- | src/qtvstools/QtMsBuildConverter.cs | 25 | ||||
-rw-r--r-- | src/qtvstools/QtProjectContextMenu.cs | 2 |
7 files changed, 429 insertions, 43 deletions
diff --git a/src/qtprojectlib/MsBuildProject.cs b/src/qtprojectlib/MsBuildProject.cs index d9040187..36f051f0 100644 --- a/src/qtprojectlib/MsBuildProject.cs +++ b/src/qtprojectlib/MsBuildProject.cs @@ -35,6 +35,9 @@ using System.Xml; using System.Xml.Linq; using QtProjectLib.QtMsBuild; using System.Text.RegularExpressions; +using Microsoft.Build.Construction; +using Microsoft.Build.Execution; +using Microsoft.Build.Evaluation; namespace QtProjectLib { @@ -72,6 +75,17 @@ namespace QtProjectLib } } + public string ProjectXml + { + get + { + var xml = this[Files.Project].xml; + if (xml == null) + return ""; + return xml.ToString(SaveOptions.None); + } + } + private static XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003"; public static MsBuildProject Load(string pathToProject) @@ -261,29 +275,237 @@ namespace QtProjectLib }); } + string AddGeneratedFilesPath(string includePathList) + { + HashSet<string> includes = new HashSet<string> { + QtVSIPSettings.GetMocDirectory(), + QtVSIPSettings.GetRccDirectory(), + QtVSIPSettings.GetUicDirectory(), + }; + foreach (var includePath in includePathList.Split(new char[] { ';' })) + includes.Add(includePath); + return string.Join<string>(";", includes); + } + + string CustomBuildMocInput(XElement cbt) + { + var commandLine = (string)cbt.Element(ns + "Command"); + Dictionary<QtMoc.Property, string> properties; + if (!QtMsBuildContainer.QtMocInstance.ParseCommandLine(commandLine, out properties)) + return (string)cbt.Attribute("Include"); + string ouputFile; + if (!properties.TryGetValue(QtMoc.Property.InputFile, out ouputFile)) + return (string)cbt.Attribute("Include"); + return ouputFile; + } + + void RemoveGeneratedFiles( + List<CustomBuildEval> cbEvals, + string configName, + string itemName, + IEnumerable<XElement> projectItems, + IEnumerable<XElement> filterItems) + { + //remove items with generated files + var cbEval = cbEvals + .Where(x => x.ProjectConfig == configName && x.Identity == itemName) + .FirstOrDefault(); + if (cbEval != null) { + var outputFiles = cbEval.Outputs.Split(new char[] { ';' }); + foreach (var outputFile in outputFiles) { + if (!string.IsNullOrEmpty(outputFile)) { + var outputItems = new List<XElement>(); + outputItems.AddRange(projectItems + .Where(x => HelperFunctions.PathEquals( + outputFile, (string)x.Attribute("Include")))); + outputItems.AddRange(filterItems + .Where(x => HelperFunctions.PathEquals( + outputFile, (string)x.Attribute("Include")))); + foreach (var item in outputItems) + item.Remove(); + } + } + } + } + public bool ConvertCustomBuildToQtMsBuild() { + var cbEvals = EvaluateCustomBuild(); + var qtMsBuild = new QtMsBuildContainer(new MsBuildConverterProvider()); qtMsBuild.BeginSetItemProperties(); - var configurations = this[Files.Project].xml + var configNames = this[Files.Project].xml .Elements(ns + "Project") .Elements(ns + "ItemGroup") .Elements(ns + "ProjectConfiguration") - .Select(x => x.Attribute("Include").Value); + .Select(x => (string)x.Attribute("Include")); - var mocCustomBuilds = GetCustomBuilds(QtMoc.ToolExecName); - var rccCustomBuilds = GetCustomBuilds(QtRcc.ToolExecName); - var uicCustomBuilds = GetCustomBuilds(QtUic.ToolExecName); + var projectItems = this[Files.Project].xml + .Elements(ns + "Project") + .Elements(ns + "ItemGroup") + .Elements() + .Where(x => ((string)x.Attribute("Include")) + .IndexOfAny(Path.GetInvalidPathChars()) == -1); + + + var filterItems = this[Files.Filters].xml + .Elements(ns + "Project") + .Elements(ns + "ItemGroup") + .Elements() + .Where(x => projectItems.Where(y => + ((string)x.Attribute("Include")).Equals((string)y.Attribute("Include"), + StringComparison.InvariantCultureIgnoreCase)).Any()); + + var cppIncludePaths = this[Files.Project].xml + .Elements(ns + "Project") + .Elements(ns + "ItemDefinitionGroup") + .Elements(ns + "ClCompile") + .Elements(ns + "AdditionalIncludeDirectories"); + + //add generated files path to C++ additional include dirs + foreach (var cppIncludePath in cppIncludePaths) + cppIncludePath.Value = AddGeneratedFilesPath((string)cppIncludePath); + + // replace each set of .moc.cbt custom build steps + // with a single .cpp custom build step + var mocCbtCustomBuilds = GetCustomBuilds(QtMoc.ToolExecName) + .Where(x => + ((string)x.Attribute("Include")).EndsWith(".moc.cbt", + StringComparison.InvariantCultureIgnoreCase)) + .GroupBy(cbt => CustomBuildMocInput(cbt)); + + List<XElement> cbtToRemove = new List<XElement>(); + foreach (var cbtGroup in mocCbtCustomBuilds) { + + //create new CustomBuild item for .cpp + var newCbt = new XElement(ns + "CustomBuild", + new XAttribute("Include", cbtGroup.Key), + new XElement(ns + "FileType", "Document")); + + //add properties from .moc.cbt items + List<string> cbtPropertyNames = new List<string> { + "AdditionalInputs", + "Command", + "Message", + "Outputs", + }; + foreach (var cbt in cbtGroup) { + var enabledProperties = cbt.Elements().Where(x => + cbtPropertyNames.Contains(x.Name.LocalName) + && !x.Parent.Elements(ns + "ExcludedFromBuild").Where(y => + (string)x.Attribute("Condition") == (string)y.Attribute("Condition")) + .Any()); + foreach (var property in enabledProperties) + newCbt.Add(new XElement(property)); + cbtToRemove.Add(cbt); + } + cbtGroup.First().AddBeforeSelf(newCbt); + + //remove ClCompile item (cannot have duplicate items) + var cppMocItems = this[Files.Project].xml + .Elements(ns + "Project") + .Elements(ns + "ItemGroup") + .Elements(ns + "ClCompile") + .Where(x => + cbtGroup.Key.Equals((string)x.Attribute("Include"), + StringComparison.InvariantCultureIgnoreCase)); + foreach (var cppMocItem in cppMocItems) + cppMocItem.Remove(); + + //change type of item in filter + cppMocItems = this[Files.Filters].xml + .Elements(ns + "Project") + .Elements(ns + "ItemGroup") + .Elements(ns + "ClCompile") + .Where(x => + cbtGroup.Key.Equals((string)x.Attribute("Include"), + StringComparison.InvariantCultureIgnoreCase)); + foreach (var cppMocItem in cppMocItems) + cppMocItem.Name = ns + "CustomBuild"; + } + + //remove .moc.cbt CustomBuild items + cbtToRemove.ForEach(x => x.Remove()); - if (!SetCommandLines(qtMsBuild, configurations, mocCustomBuilds, QtMoc.ItemTypeName)) + //convert moc custom build steps + var mocCustomBuilds = GetCustomBuilds(QtMoc.ToolExecName); + if (!SetCommandLines(qtMsBuild, configNames, mocCustomBuilds, QtMoc.ItemTypeName)) return false; + foreach (var qtMoc in mocCustomBuilds.Elements(ns + QtMoc.ItemTypeName)) { + var itemName = (string)qtMoc.Attribute("Include"); + var configName = (string)qtMoc.Attribute("ConfigName"); + + //remove items with generated files + RemoveGeneratedFiles(cbEvals, configName, itemName, projectItems, filterItems); + + //set properties + qtMsBuild.SetItemProperty(qtMoc, + QtMoc.Property.ExecutionDescription, "Moc'ing %(Identity)..."); + qtMsBuild.SetItemProperty(qtMoc, + QtMoc.Property.InputFile, "%(FullPath)"); + if (!HelperFunctions.IsSourceFile(itemName)) { + qtMsBuild.SetItemProperty(qtMoc, + QtMoc.Property.OutputFile, string.Format(@"{0}\moc_%(Filename).cpp", + QtVSIPSettings.GetMocDirectory())); + qtMsBuild.SetItemProperty(qtMoc, + QtMoc.Property.DynamicSource, "output"); + } else { + qtMsBuild.SetItemProperty(qtMoc, + QtMoc.Property.OutputFile, string.Format(@"{0}\%(Filename).moc", + QtVSIPSettings.GetMocDirectory())); + qtMsBuild.SetItemProperty(qtMoc, + QtMoc.Property.DynamicSource, "input"); + } + var includePath = qtMsBuild.GetPropertyChangedValue( + QtMoc.Property.IncludePath, itemName, configName); + if (!string.IsNullOrEmpty(includePath)) { + qtMsBuild.SetItemProperty(qtMoc, + QtMoc.Property.IncludePath, AddGeneratedFilesPath(includePath)); + } + } - if (!SetCommandLines(qtMsBuild, configurations, rccCustomBuilds, QtRcc.ItemTypeName)) + //convert rcc custom build steps + var rccCustomBuilds = GetCustomBuilds(QtRcc.ToolExecName); + if (!SetCommandLines(qtMsBuild, configNames, rccCustomBuilds, QtRcc.ItemTypeName)) return false; + foreach (var qtRcc in rccCustomBuilds.Elements(ns + QtRcc.ItemTypeName)) { + var itemName = (string)qtRcc.Attribute("Include"); + var configName = (string)qtRcc.Attribute("ConfigName"); + + //remove items with generated files + RemoveGeneratedFiles(cbEvals, configName, itemName, projectItems, filterItems); + + //set properties + qtMsBuild.SetItemProperty(qtRcc, + QtRcc.Property.ExecutionDescription, "Rcc'ing %(Identity)..."); + qtMsBuild.SetItemProperty(qtRcc, + QtRcc.Property.InputFile, "%(FullPath)"); + qtMsBuild.SetItemProperty(qtRcc, + QtRcc.Property.OutputFile, string.Format(@"{0}\qrc_%(Filename).cpp", + QtVSIPSettings.GetRccDirectory())); + } - if (!SetCommandLines(qtMsBuild, configurations, uicCustomBuilds, QtUic.ItemTypeName)) + //convert uic custom build steps + var uicCustomBuilds = GetCustomBuilds(QtUic.ToolExecName); + if (!SetCommandLines(qtMsBuild, configNames, uicCustomBuilds, QtUic.ItemTypeName)) return false; + foreach (var qtUic in uicCustomBuilds.Elements(ns + QtUic.ItemTypeName)) { + var itemName = (string)qtUic.Attribute("Include"); + var configName = (string)qtUic.Attribute("ConfigName"); + + //remove items with generated files + RemoveGeneratedFiles(cbEvals, configName, itemName, projectItems, filterItems); + + //set properties + qtMsBuild.SetItemProperty(qtUic, + QtUic.Property.ExecutionDescription, "Uic'ing %(Identity)..."); + qtMsBuild.SetItemProperty(qtUic, + QtUic.Property.InputFile, "%(FullPath)"); + qtMsBuild.SetItemProperty(qtUic, + QtUic.Property.OutputFile, string.Format(@"{0}\ui_%(Filename).h", + QtVSIPSettings.GetRccDirectory())); + } qtMsBuild.EndSetItemProperties(); @@ -294,6 +516,115 @@ namespace QtProjectLib return true; } + bool TryReplaceTextInPlace(ref string text, Regex findWhat, string newText) + { + var match = findWhat.Match(text); + if (!match.Success) + return false; + do { + text = text.Remove(match.Index, match.Length).Insert(match.Index, newText); + match = findWhat.Match(text, match.Index); + } while (match.Success); + + return true; + } + + void ReplaceText(XElement xElem, Regex findWhat, string newText) + { + var elemValue = (string)xElem; + if (!string.IsNullOrEmpty(elemValue) + && TryReplaceTextInPlace(ref elemValue, findWhat, newText)) { + xElem.Value = elemValue; + } + } + + void ReplaceText(XAttribute xAttr, Regex findWhat, string newText) + { + var attrValue = (string)xAttr; + if (!string.IsNullOrEmpty(attrValue) + && TryReplaceTextInPlace(ref attrValue, findWhat, newText)) { + xAttr.Value = attrValue; + } + } + + public void ReplacePath(string oldPath, string newPath) + { + var findWhat = new Regex(oldPath + .Replace("\\", "[\\\\\\/]") + .Replace(".", "\\.") + .Replace("$", "\\$"), + RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); + + foreach (var xElem in this[Files.Project].xml.Descendants()) { + if (!xElem.HasElements) + ReplaceText(xElem, findWhat, newPath); + foreach (var xAttr in xElem.Attributes()) + ReplaceText(xAttr, findWhat, newPath); + } + } + + class CustomBuildEval + { + public string ProjectConfig { get; set; } + public string Identity { get; set; } + public string AdditionalInputs { get; set; } + public string Outputs { get; set; } + public string Message { get; set; } + public string Command { get; set; } + } + + List<CustomBuildEval> EvaluateCustomBuild() + { + var eval = new List<CustomBuildEval>(); + var evaluateTarget = new XElement(ns + "Target", + new XAttribute("Name", "EvaluateCustomBuild"), + new XElement(ns + "PropertyGroup", + new XElement(ns + "CustomBuildEval", "@(CustomBuild->'" + + "{%(Identity)}" + + "{%(AdditionalInputs)}" + + "{%(Outputs)}" + + "{%(Message)}" + + "{%(Command)}')"))); + this[Files.Project].xml.Root.Add(evaluateTarget); + + var projRoot = ProjectRootElement.Create(this[Files.Project].xml.CreateReader()); + + var pattern = new Regex(@"{([^}]+)}{([^}]+)}{([^}]+)}{([^}]+)}{([^}]+)}"); + + var projConfigs = this[Files.Project].xml + .Elements(ns + "Project") + .Elements(ns + "ItemGroup") + .Elements(ns + "ProjectConfiguration"); + foreach (var projConfig in projConfigs) { + string configName = (string)projConfig.Attribute("Include"); + var properties = new Dictionary<string, string>(); + foreach (var configProp in projConfig.Elements()) + properties.Add(configProp.Name.LocalName, (string)configProp); + var projInst = new ProjectInstance(projRoot, properties, + null, new ProjectCollection()); + var buildRequest = new BuildRequestData( + projInst, new string[] { "EvaluateCustomBuild" }, + null, BuildRequestDataFlags.ProvideProjectStateAfterBuild); + var buildResult = BuildManager.DefaultBuildManager.Build( + new BuildParameters(), buildRequest); + string customBuildEval = buildResult.ProjectStateAfterBuild + .GetPropertyValue("CustomBuildEval"); + foreach (Match cbEval in pattern.Matches(customBuildEval)) { + eval.Add(new CustomBuildEval { + ProjectConfig = configName, + Identity = cbEval.Groups[1].Value, + AdditionalInputs = cbEval.Groups[2].Value, + Outputs = cbEval.Groups[3].Value, + Message = cbEval.Groups[4].Value, + Command = cbEval.Groups[5].Value, + }); + } + } + + evaluateTarget.Remove(); + return eval; + } + static Regex ConditionParser = new Regex(@"\'\$\(Configuration[^\)]*\)\|\$\(Platform[^\)]*\)\'\=\=\'([^\']+)\'"); diff --git a/src/qtprojectlib/ProjectImporter.cs b/src/qtprojectlib/ProjectImporter.cs index 246d3b0e..407af21d 100644 --- a/src/qtprojectlib/ProjectImporter.cs +++ b/src/qtprojectlib/ProjectImporter.cs @@ -205,29 +205,20 @@ namespace QtProjectLib private void ImportQMakeProject(FileInfo projectFile, VersionInformation vi) { - var sr = projectFile.OpenText(); - var content = sr.ReadToEnd(); - sr.Close(); - - var qtDir = ParseQtDirFromFileContent(content, vi); + var xmlProject = MsBuildProject.Load(projectFile.FullName); + var qtDir = ParseQtDirFromFileContent(xmlProject.ProjectXml, vi); if (!string.IsNullOrEmpty(qtDir)) { - content = content.Replace(qtDir, "$(QTDIR)\\", StringComparison.OrdinalIgnoreCase); + xmlProject.ReplacePath(qtDir, "$(QTDIR)\\"); // qmake tends to write relative and absolute paths into the .vcxproj file if (!Path.IsPathRooted(qtDir)) // if the project is on the same drive as Qt. - content = content.Replace(vi.qtDir + '\\', "$(QTDIR)\\", StringComparison.OrdinalIgnoreCase); - var sw = projectFile.CreateText(); - sw.Write(content); - sw.Flush(); - sw.Close(); + xmlProject.ReplacePath(vi.qtDir + '\\', "$(QTDIR)\\"); } else { Messages.PaneMessage(dteObject, SR.GetString("ImportProject_CannotFindQtDirectory", projectFile.Name)); } - - var xmlProject = MsBuildProject.Load(projectFile.FullName); + xmlProject.ReplacePath(projectFile.DirectoryName, "."); xmlProject.AddQtMsBuildReferences(); xmlProject.ConvertCustomBuildToQtMsBuild(); xmlProject.Save(); - } private static string ParseQtDirFromFileContent(string vcFileContent, VersionInformation vi) @@ -298,13 +289,10 @@ namespace QtProjectLib } qtProject.RemoveResFilesFromGeneratedFilesFilter(); - qtProject.RepairGeneratedFilesStructure(); qtProject.TranslateFilterNames(); QtVSIPSettings.SaveUicDirectory(qtProject.Project, QtVSIPSettings.GetUicDirectory()); - qtProject.UpdateUicSteps(".", false); // false is to not remove given path from includes QtVSIPSettings.SaveRccDirectory(qtProject.Project, QtVSIPSettings.GetRccDirectory()); - qtProject.RefreshRccSteps(); // collapse the generated files/resources filters afterwards qtProject.CollapseFilter(Filters.ResourceFiles().Name); diff --git a/src/qtprojectlib/QtMsBuild.cs b/src/qtprojectlib/QtMsBuild.cs index c82638e4..ff22e1f4 100644 --- a/src/qtprojectlib/QtMsBuild.cs +++ b/src/qtprojectlib/QtMsBuild.cs @@ -305,6 +305,69 @@ namespace QtProjectLib.QtMsBuild return true; } + string GetPropertyChangedValue( + string configName, + string itemTypeName, + string itemName, + string propertyName) + { + if (!pendingChanges) + return null; + + var change = new ItemPropertyChange + { + ConfigName = configName, + ItemTypeName = itemTypeName, + ItemName = itemName, + PropertyName = propertyName + }; + + var changes = itemPropertyChanges.Values + .SelectMany(x => x) + .Where(x => x.Matches(change)); + + if (!changes.Any()) + return null; + + return changes.First().PropertyValue; + } + + public string GetPropertyChangedValue( + QtMoc.Property property, + string itemName, + string configName) + { + return GetPropertyChangedValue( + configName, + QtMoc.ItemTypeName, + itemName, + property.ToString()); + } + + public string GetPropertyChangedValue( + QtRcc.Property property, + string itemName, + string configName) + { + return GetPropertyChangedValue( + configName, + QtRcc.ItemTypeName, + itemName, + property.ToString()); + } + + public string GetPropertyChangedValue( + QtUic.Property property, + string itemName, + string configName) + { + return GetPropertyChangedValue( + configName, + QtUic.ItemTypeName, + itemName, + property.ToString()); + } + public bool SetCommandLine(string itemType, object propertyStorage, string commandLine) { switch (itemType) { @@ -320,7 +383,7 @@ namespace QtProjectLib.QtMsBuild #region QtMoc static QtMoc qtMocInstance; - static QtMoc QtMocInstance + public static QtMoc QtMocInstance { get { @@ -366,7 +429,7 @@ namespace QtProjectLib.QtMsBuild #region QtRcc static QtRcc qtRccInstance; - static QtRcc QtRccInstance + public static QtRcc QtRccInstance { get { @@ -412,7 +475,7 @@ namespace QtProjectLib.QtMsBuild #region QtUic static QtUic qtUicInstance; - static QtUic QtUicInstance + public static QtUic QtUicInstance { get { diff --git a/src/qtprojectlib/QtProject.cs b/src/qtprojectlib/QtProject.cs index 1b715773..69d18b9a 100644 --- a/src/qtprojectlib/QtProject.cs +++ b/src/qtprojectlib/QtProject.cs @@ -3276,8 +3276,7 @@ namespace QtProjectLib var cur_platform = conf.Platform as VCPlatform; if (cur_platform.Name == activePlatformName) { var cur_solution = conf.ConfigurationName + "|" + cur_platform.Name; -#if VS2013 || VS2015 - // In VS2013/15, if the LocalDebuggerEnvironment property is defined, it + // If the LocalDebuggerEnvironment property is defined, it // will be stored in the .user file before the QTDIR property, which is an // error because there is a dependency. To work around this, first remove // the property and then add it after QTDIR is defined. @@ -3292,13 +3291,10 @@ namespace QtProjectLib propertyAccess.RemoveProperty( "LocalDebuggerEnvironment", cur_solution, "UserFile"); } -#endif propertyAccess.SetPropertyValue("QTDIR", cur_solution, "UserFile", qtDir); -#if VS2013 || VS2015 if (!string.IsNullOrEmpty(debuggerEnv)) propertyAccess.SetPropertyValue( "LocalDebuggerEnvironment", cur_solution, "UserFile", debuggerEnv); -#endif } } diff --git a/src/qtprojectlib/QtProjectLib.csproj b/src/qtprojectlib/QtProjectLib.csproj index f16ef51b..57e00af4 100644 --- a/src/qtprojectlib/QtProjectLib.csproj +++ b/src/qtprojectlib/QtProjectLib.csproj @@ -104,6 +104,7 @@ <EmbeddedResource Include="Resources\newitem_d.png" /> </ItemGroup> <ItemGroup> + <Reference Include="Microsoft.Build" /> <Reference Include="System.Xml.Linq" /> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> diff --git a/src/qtvstools/QtMsBuildConverter.cs b/src/qtvstools/QtMsBuildConverter.cs index d6eca649..f82dc8c7 100644 --- a/src/qtvstools/QtMsBuildConverter.cs +++ b/src/qtvstools/QtMsBuildConverter.cs @@ -121,30 +121,37 @@ namespace QtVsTools return ErrorMessage( string.Format(SR.GetString("ErrorConvertingProject"), project.Name)); var projectGuid = new Guid(vcProject.ProjectGUID); + var projectName = project.Name; try { if (solution.UnloadProject( ref projectGuid, (uint)_VSProjectUnloadStatus.UNLOADSTATUS_LoadPendingIfNeeded) != VSConstants.S_OK) return ErrorMessage( - string.Format(SR.GetString("ErrorConvertingProject"), project.Name)); + string.Format(SR.GetString("ErrorConvertingProject"), projectName)); } catch (Exception e) { return ErrorMessage(string.Format(SR.GetString("ErrorConvertingProject"), - string.Format("{0}\r\n{1}", project.Name, e.Message))); + string.Format("{0}\r\n{1}", projectName, e.Message))); } + var xmlProject = MsBuildProject.Load(pathToProject); - if (xmlProject == null) - return ErrorMessage( - string.Format(SR.GetString("ErrorConvertingProject"), project.Name)); - xmlProject.AddQtMsBuildReferences(); - xmlProject.ConvertCustomBuildToQtMsBuild(); - xmlProject.Save(); + bool ok = (xmlProject != null); + if (ok) + ok = xmlProject.AddQtMsBuildReferences(); + if (ok) + ok = xmlProject.ConvertCustomBuildToQtMsBuild(); + if (ok) + ok = xmlProject.Save(); try { solution.ReloadProject(ref projectGuid); } catch (Exception e) { return ErrorMessage( string.Format(SR.GetString("ErrorConvertingProject"), - string.Format("{0}\r\n{1}", project.Name, e.Message))); + string.Format("{0}\r\n{1}", projectName, e.Message))); + } + if (!ok) { + return ErrorMessage( + string.Format(SR.GetString("ErrorConvertingProject"), projectName)); } return true; } diff --git a/src/qtvstools/QtProjectContextMenu.cs b/src/qtvstools/QtProjectContextMenu.cs index 72e50032..a38c2f88 100644 --- a/src/qtvstools/QtProjectContextMenu.cs +++ b/src/qtvstools/QtProjectContextMenu.cs @@ -195,7 +195,7 @@ namespace QtVsTools case CommandId.ProjectConvertToQtMsBuild: { QtMsBuildConverter.ProjectToQtMsBuild( - HelperFunctions.GetSelectedQtProject(Vsix.Instance.Dte)); + HelperFunctions.GetSelectedProject(Vsix.Instance.Dte)); } break; case CommandId.ProjectAddNewQtClassProjectId: |