/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ using EnvDTE; using Microsoft.VisualStudio.VCProjectEngine; using System; using System.Collections.Generic; using System.IO; using System.Windows.Forms; namespace QtVsTools.Core { public class ProjectImporter { private DTE dteObject; const string projectFileExtension = ".vcxproj"; public ProjectImporter(DTE dte) { dteObject = dte; } public void ImportProFile(string qtVersion) { FileDialog toOpen = new OpenFileDialog(); toOpen.FilterIndex = 1; toOpen.CheckFileExists = true; toOpen.Title = SR.GetString("ExportProject_SelectQtProjectToAdd"); toOpen.Filter = "Qt Project files (*.pro)|*.pro|All files (*.*)|*.*"; if (DialogResult.OK != toOpen.ShowDialog()) return; var mainInfo = new FileInfo(toOpen.FileName); if (HelperFunctions.IsSubDirsFile(mainInfo.FullName)) { // we use the safe way. Make the user close the existing solution manually if ((!string.IsNullOrEmpty(dteObject.Solution.FullName)) || (HelperFunctions.ProjectsInSolution(dteObject).Count > 0)) { if (MessageBox.Show(SR.GetString("ExportProject_SubdirsProfileSolutionClose"), SR.GetString("OpenSolution"), MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK) { dteObject.Solution.Close(true); } else { return; } } ImportSolution(mainInfo, qtVersion); } else { ImportProject(mainInfo, qtVersion); } } private void ImportSolution(FileInfo mainInfo, string qtVersion) { var versionInfo = QtVersionManager.The().GetVersionInfo(qtVersion); var VCInfo = RunQmake(mainInfo, ".sln", true, versionInfo); if (null == VCInfo) return; ImportQMakeSolution(VCInfo, versionInfo); try { if (CheckQtVersion(versionInfo)) { dteObject.Solution.Open(VCInfo.FullName); if (qtVersion != null) { QtVersionManager.The().SaveSolutionQtVersion(dteObject.Solution, qtVersion); foreach (var prj in HelperFunctions.ProjectsInSolution(dteObject)) { QtVersionManager.The().SaveProjectQtVersion(prj, qtVersion); var qtPro = QtProject.Create(prj); qtPro.SetQtEnvironment(); ApplyPostImportSteps(qtPro); } } } Messages.Print("--- (Import): Finished opening " + VCInfo.Name); } catch (Exception e) { Messages.DisplayCriticalErrorMessage(e); } } public void ImportProject(FileInfo mainInfo, string qtVersion) { var versionInfo = QtVersionManager.The().GetVersionInfo(qtVersion); var VCInfo = RunQmake(mainInfo, projectFileExtension, false, versionInfo); if (null == VCInfo) return; ImportQMakeProject(VCInfo, versionInfo); try { if (CheckQtVersion(versionInfo)) { // no need to add the project again if it's already there... if (!HelperFunctions.IsProjectInSolution(dteObject, VCInfo.FullName)) { try { dteObject.Solution.AddFromFile(VCInfo.FullName, false); } catch (Exception /*exception*/) { Messages.Print("--- (Import): Generated project could not be loaded."); Messages.Print("--- (Import): Please look in the output above for errors and warnings."); return; } Messages.Print("--- (Import): Added " + VCInfo.Name + " to Solution"); } else { Messages.Print("Project already in Solution"); } Project pro = null; foreach (var p in HelperFunctions.ProjectsInSolution(dteObject)) { if (p.FullName.ToLower() == VCInfo.FullName.ToLower()) { pro = p; break; } } if (pro != null) { var qtPro = QtProject.Create(pro); qtPro.SetQtEnvironment(); var platformName = versionInfo.GetVSPlatformName(); if (qtVersion != null) QtVersionManager.The().SaveProjectQtVersion(pro, qtVersion, platformName); if (!qtPro.SelectSolutionPlatform(platformName) || !qtPro.HasPlatform(platformName)) { var newProject = false; qtPro.CreatePlatform("Win32", platformName, null, versionInfo, ref newProject); if (!qtPro.SelectSolutionPlatform(platformName)) Messages.Print("Can't select the platform " + platformName + "."); } // try to figure out if the project is a plugin project try { var activeConfig = pro.ConfigurationManager.ActiveConfiguration.ConfigurationName; var config = (VCConfiguration)((IVCCollection)qtPro.VCProject.Configurations).Item(activeConfig); if (config.ConfigurationType == ConfigurationTypes.typeDynamicLibrary) { var compiler = CompilerToolWrapper.Create(config); var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); if (compiler.GetPreprocessorDefinitions().IndexOf("QT_PLUGIN", StringComparison.Ordinal) > -1 && compiler.GetPreprocessorDefinitions().IndexOf("QDESIGNER_EXPORT_WIDGETS", StringComparison.Ordinal) > -1 && compiler.GetAdditionalIncludeDirectories().IndexOf("QtDesigner", StringComparison.Ordinal) > -1 && linker.AdditionalDependencies.IndexOf("QtDesigner", StringComparison.Ordinal) > -1) { qtPro.MarkAsDesignerPluginProject(); } } } catch (Exception) { } qtPro.SetQtEnvironment(); ApplyPostImportSteps(qtPro); } } } catch (Exception e) { Messages.DisplayCriticalErrorMessage(SR.GetString("ExportProject_ProjectOrSolutionCorrupt", e.ToString())); } } private void ImportQMakeSolution(FileInfo solutionFile, VersionInformation vi) { var projects = ParseProjectsFromSolution(solutionFile); foreach (var project in projects) { var projectInfo = new FileInfo(project); ImportQMakeProject(projectInfo, vi); } } private static List ParseProjectsFromSolution(FileInfo solutionFile) { var sr = solutionFile.OpenText(); var content = sr.ReadToEnd(); sr.Close(); var projects = new List(); var index = content.IndexOf(projectFileExtension, StringComparison.Ordinal); while (index != -1) { var startIndex = content.LastIndexOf('\"', index, index) + 1; var endIndex = content.IndexOf('\"', index); projects.Add(content.Substring(startIndex, endIndex - startIndex)); content = content.Substring(endIndex); index = content.IndexOf(projectFileExtension, StringComparison.Ordinal); } return projects; } private void ImportQMakeProject(FileInfo projectFile, VersionInformation vi) { var xmlProject = MsBuildProject.Load(projectFile.FullName); xmlProject.ReplacePath(vi.qtDir, "$(QTDIR)"); xmlProject.ReplacePath(projectFile.DirectoryName, "."); bool ok = xmlProject.AddQtMsBuildReferences(); if (ok) ok = xmlProject.ConvertCustomBuildToQtMsBuild(); if (ok) ok = xmlProject.EnableMultiProcessorCompilation(); if (ok) { string versionWin10SDK = HelperFunctions.GetWindows10SDKVersion(); if (!string.IsNullOrEmpty(versionWin10SDK)) ok = xmlProject.SetDefaultWindowsSDKVersion(versionWin10SDK); } if (ok) ok = xmlProject.UpdateProjectFormatVersion(); if (!ok) { Messages.Print( SR.GetString("ImportProject_CannotConvertProject", projectFile.Name)); } xmlProject.Save(); // Initialize Qt variables xmlProject.BuildTarget("QtVarsDesignTime"); } private static void ApplyPostImportSteps(QtProject qtProject) { qtProject.RemoveResFilesFromGeneratedFilesFilter(); qtProject.TranslateFilterNames(); // collapse the generated files/resources filters afterwards qtProject.CollapseFilter(Filters.ResourceFiles().Name); qtProject.CollapseFilter(Filters.GeneratedFiles().Name); try { // save the project after modification qtProject.Project.Save(null); } catch { /* ignore */ } } private FileInfo RunQmake(FileInfo mainInfo, string ext, bool recursive, VersionInformation vi) { var name = mainInfo.Name.Remove(mainInfo.Name.IndexOf('.')); var VCInfo = new FileInfo(mainInfo.DirectoryName + "\\" + name + ext); if (!VCInfo.Exists || DialogResult.Yes == MessageBox.Show(SR.GetString("ExportProject_ProjectExistsRegenerateOrReuse", VCInfo.Name), SR.GetString("ProjectExists"), MessageBoxButtons.YesNo, MessageBoxIcon.Question)) { Messages.Print("--- (Import): Generating new project of " + mainInfo.Name + " file"); var waitDialog = WaitDialog.Start( "Open Qt Project File", "Generating Visual Studio project...", delay: 2); var qmake = new QMakeImport(vi, mainInfo.FullName, recursive, dteObject); int exitCode = qmake.Run(setVCVars: true); waitDialog.Stop(); if (exitCode == 0) return VCInfo; } return null; } private static bool CheckQtVersion(VersionInformation vi) { if (!vi.qt5Version) { Messages.DisplayWarningMessage(SR.GetString("ExportProject_EditProjectFileManually")); return false; } return true; } } }