| | |
| | | /****************************************************************************
|
| | | **
|
| | | ** Copyright (C) 2016 The Qt Company Ltd.
|
| | | ** Copyright (C) 2022 The Qt Company Ltd.
|
| | | ** Contact: https://www.qt.io/licensing/
|
| | | **
|
| | | ** This file is part of the Qt VS Tools.
|
| | |
| | | **
|
| | | ****************************************************************************/
|
| | |
|
| | | using Microsoft.VisualStudio.VCProjectEngine;
|
| | | using Microsoft.Win32;
|
| | | using System;
|
| | | using System.Collections;
|
| | | using System.Collections.Generic;
|
| | | using System.IO;
|
| | | using System.Linq;
|
| | | using System.Threading;
|
| | | using QtVsTools.VisualStudio;
|
| | | using EnvDTE;
|
| | | using Microsoft.VisualStudio.Shell;
|
| | | using Microsoft.VisualStudio.VCProjectEngine;
|
| | | using Microsoft.Win32;
|
| | |
|
| | | namespace QtVsTools.Core
|
| | | {
|
| | |
| | | public class QtVersionManager
|
| | | {
|
| | | private static QtVersionManager instance;
|
| | | private string regVersionPath;
|
| | | private string strVersionKey;
|
| | | private readonly string regVersionPath;
|
| | | private readonly string strVersionKey;
|
| | | private Hashtable versionCache;
|
| | |
|
| | | protected QtVersionManager()
|
| | | {
|
| | | strVersionKey = "Versions";
|
| | | regVersionPath = Resources.registryVersionPath;
|
| | | RefreshVersionNames();
|
| | | }
|
| | |
|
| | | void RefreshVersionNames()
|
| | | {
|
| | | var rootKeyPath = "SOFTWARE\\" + Resources.registryRootPath;
|
| | | try {
|
| | | using (var rootKey = Registry.CurrentUser.OpenSubKey(rootKeyPath, true))
|
| | | using (var versionsKey = rootKey.OpenSubKey(strVersionKey, true)) {
|
| | | versionsKey.SetValue("VersionNames", string.Join(";", GetVersions()));
|
| | | }
|
| | | private static readonly EventWaitHandle packageInit = new EventWaitHandle(false, EventResetMode.ManualReset);
|
| | | private static EventWaitHandle packageInitDone = null;
|
| | |
|
| | | } catch (Exception e) {
|
| | | Messages.Print(
|
| | | e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace);
|
| | | }
|
| | | }
|
| | |
|
| | | static EventWaitHandle
|
| | | packageInit = new EventWaitHandle(false, EventResetMode.ManualReset),
|
| | | packageInitDone = null;
|
| | |
|
| | | static public QtVersionManager The(EventWaitHandle initDone = null)
|
| | | public static QtVersionManager The(EventWaitHandle initDone = null)
|
| | | {
|
| | | if (initDone == null) {
|
| | | packageInit.WaitOne();
|
| | |
| | |
|
| | | public VersionInformation GetVersionInfo(string name)
|
| | | {
|
| | | if (name == "$(DefaultQtVersion)")
|
| | | name = GetDefaultVersion();
|
| | | if (name == null)
|
| | | return null;
|
| | | if (name == "$(DefaultQtVersion)")
|
| | | name = GetDefaultVersion();
|
| | | if (versionCache == null)
|
| | | versionCache = new Hashtable();
|
| | |
|
| | |
| | |
|
| | | public VersionInformation GetVersionInfo(EnvDTE.Project project)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | | return GetVersionInfo(GetProjectQtVersion(project));
|
| | | }
|
| | |
|
| | | public void ClearVersionCache()
|
| | | {
|
| | | if (versionCache != null)
|
| | | versionCache.Clear();
|
| | | }
|
| | |
|
| | | public string[] GetVersions()
|
| | |
| | | if (qtDir == null)
|
| | | return null;
|
| | |
|
| | | qtDir = qtDir.ToLower();
|
| | | var versions = GetVersions();
|
| | | foreach (var version in versions) {
|
| | | var installPath = GetInstallPath(version);
|
| | | if (installPath == null)
|
| | | continue;
|
| | | if (installPath.ToLower() == qtDir)
|
| | | if (installPath.Equals(qtDir, StringComparison.OrdinalIgnoreCase))
|
| | | return version;
|
| | | }
|
| | |
|
| | |
| | | /// <summary>
|
| | | /// Check if all Qt versions are valid and readable.
|
| | | /// </summary>
|
| | | /// Also sets the default Qt version to the newest version, if needed.
|
| | | /// <param name="errorMessage"></param>
|
| | | /// <returns>true, if we found an invalid version</returns>
|
| | | public bool HasInvalidVersions(out string errorMessage)
|
| | | /// <returns>true, if there are one or more invalid Qt version</returns>
|
| | | public bool HasInvalidVersions(out string errorMessage, out bool defaultVersionInvalid)
|
| | | {
|
| | | var validVersions = new Dictionary<string, QtConfig>();
|
| | | var invalidVersions = new List<string>();
|
| | | var defaultVersion = GetDefaultVersionString();
|
| | | defaultVersionInvalid = string.IsNullOrEmpty(defaultVersion);
|
| | |
|
| | | foreach (var v in GetVersions()) {
|
| | | if (v == "$(DefaultQtVersion)")
|
| | | continue;
|
| | |
|
| | | var vPath = GetInstallPath(v);
|
| | | if (string.IsNullOrEmpty(vPath)) {
|
| | | invalidVersions.Add(v);
|
| | | continue;
|
| | | }
|
| | |
|
| | | if (vPath.StartsWith("SSH:") || vPath.StartsWith("WSL:"))
|
| | | continue;
|
| | |
|
| | | var qmakePath = Path.Combine(vPath, "bin", "qmake.exe");
|
| | | if (!File.Exists(qmakePath))
|
| | | qmakePath = Path.Combine(vPath, "qmake.exe");
|
| | | if (!File.Exists(qmakePath)) {
|
| | | invalidVersions.Add(v);
|
| | | continue;
|
| | | }
|
| | |
|
| | | validVersions[v] = new QtConfig(vPath);
|
| | | }
|
| | |
|
| | | if (invalidVersions.Count > 0) {
|
| | | errorMessage = "These Qt version are inaccessible:\n";
|
| | | foreach (var invalidVersion in invalidVersions)
|
| | | errorMessage += invalidVersion + " in " + GetInstallPath(invalidVersion) + "\n";
|
| | | errorMessage += "Make sure that you have read access to all files in your Qt directories.";
|
| | |
|
| | | // Is the default Qt version invalid?
|
| | | var isDefaultQtVersionInvalid = false;
|
| | | var defaultQtVersionName = GetDefaultVersion();
|
| | | if (string.IsNullOrEmpty(defaultQtVersionName)) {
|
| | | isDefaultQtVersionInvalid = true;
|
| | | } else {
|
| | | foreach (var name in invalidVersions) {
|
| | | if (name == defaultQtVersionName) {
|
| | | isDefaultQtVersionInvalid = true;
|
| | | break;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | // find the newest valid Qt version that can be used as default version
|
| | | if (isDefaultQtVersionInvalid && validVersions.Count > 0) {
|
| | | QtConfig defaultQtVersionConfig = null;
|
| | | foreach (var vNameConfig in validVersions) {
|
| | | var vName = vNameConfig.Key;
|
| | | var v = vNameConfig.Value;
|
| | | if (defaultQtVersionConfig == null) {
|
| | | defaultQtVersionConfig = v;
|
| | | defaultQtVersionName = vName;
|
| | | continue;
|
| | | }
|
| | | if (defaultQtVersionConfig.VersionMajor < v.VersionMajor ||
|
| | | (defaultQtVersionConfig.VersionMajor == v.VersionMajor && (defaultQtVersionConfig.VersionMinor < v.VersionMinor ||
|
| | | (defaultQtVersionConfig.VersionMinor == v.VersionMinor && defaultQtVersionConfig.VersionPatch < v.VersionPatch)))) {
|
| | | defaultQtVersionConfig = v;
|
| | | defaultQtVersionName = vName;
|
| | | }
|
| | | }
|
| | | if (defaultQtVersionConfig != null)
|
| | | SaveDefaultVersion(defaultQtVersionName);
|
| | | }
|
| | |
|
| | | return true;
|
| | | }
|
| | | errorMessage = null;
|
| | | return false;
|
| | | foreach (var version in GetVersions()) {
|
| | | if (version == "$(DefaultQtVersion)")
|
| | | continue;
|
| | |
|
| | | var path = GetInstallPath(version);
|
| | | if (path != null && (path.StartsWith("SSH:") || path.StartsWith("WSL:")))
|
| | | continue;
|
| | |
|
| | | if (string.IsNullOrEmpty(path) || !QMake.Exists(path)) {
|
| | | errorMessage += version + " in " + path + "\n";
|
| | | defaultVersionInvalid |= version == defaultVersion;
|
| | | }
|
| | |
|
| | | if (!string.IsNullOrEmpty(errorMessage)) {
|
| | | errorMessage = "These Qt version are inaccessible:\n"
|
| | | + errorMessage
|
| | | + "Make sure that you have read access to all files in your Qt directories.";
|
| | | }
|
| | | }
|
| | | return errorMessage != null;
|
| | | }
|
| | |
|
| | | public void SetLatestQtVersionAsDefault()
|
| | | {
|
| | | var validVersions = new Dictionary<string, Version>();
|
| | | foreach (var version in GetVersions()) {
|
| | | if (version == "$(DefaultQtVersion)")
|
| | | continue;
|
| | |
|
| | | var path = GetInstallPath(version);
|
| | | if (!string.IsNullOrEmpty(path) && QMake.Exists(path))
|
| | | validVersions[version] = new Version(new QtConfig(path).VersionString);
|
| | | }
|
| | |
|
| | | if (validVersions.Count <= 0)
|
| | | return;
|
| | |
|
| | | var defaultName = "";
|
| | | Version defaultVersion = null;
|
| | | foreach (var tmp in validVersions) {
|
| | | var version = tmp.Value;
|
| | | if (defaultVersion == null || defaultVersion < version) {
|
| | | defaultName = tmp.Key;
|
| | | defaultVersion = version;
|
| | | }
|
| | | }
|
| | | SaveDefaultVersion(defaultName);
|
| | | }
|
| | |
|
| | | public string GetInstallPath(string version)
|
| | |
| | | return Environment.GetEnvironmentVariable("QTDIR");
|
| | |
|
| | | var key = root.OpenSubKey("SOFTWARE\\" + Resources.registryRootPath, false);
|
| | | if (key == null)
|
| | | return null;
|
| | | var versionKey = key.OpenSubKey(strVersionKey + "\\" + version, false);
|
| | | if (versionKey == null)
|
| | | return null;
|
| | | return (string)versionKey.GetValue("InstallDir");
|
| | | var versionKey = key?.OpenSubKey(strVersionKey + "\\" + version, false);
|
| | | return versionKey?.GetValue("InstallDir") as string;
|
| | | }
|
| | |
|
| | | public string GetInstallPath(EnvDTE.Project project)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var version = GetProjectQtVersion(project);
|
| | | if (version == "$(DefaultQtVersion)")
|
| | | version = GetDefaultVersion();
|
| | |
| | | versionKey.SetValue("InstallDir", dir);
|
| | | }
|
| | | }
|
| | | RefreshVersionNames();
|
| | | return true;
|
| | | }
|
| | |
|
| | |
| | | return;
|
| | | key.DeleteSubKey(versionName);
|
| | | key.Close();
|
| | | RefreshVersionNames();
|
| | | }
|
| | |
|
| | | private bool IsVersionAvailable(string version)
|
| | | internal bool IsVersionAvailable(string version)
|
| | | {
|
| | | var versionAvailable = false;
|
| | | var versions = GetVersions();
|
| | |
| | |
|
| | | public bool SaveProjectQtVersion(EnvDTE.Project project, string version)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | | return SaveProjectQtVersion(project, version, project.ConfigurationManager.ActiveConfiguration.PlatformName);
|
| | | }
|
| | |
|
| | | public bool SaveProjectQtVersion(EnvDTE.Project project, string version, string platform)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (!IsVersionAvailable(version) && version != "$(DefaultQtVersion)")
|
| | | return false;
|
| | |
|
| | | if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings) {
|
| | | var vcPro = project.Object as VCProject;
|
| | | if (vcPro == null)
|
| | |
| | |
|
| | | public string GetProjectQtVersion(EnvDTE.Project project)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | EnvDTE.Configuration config = null;
|
| | | try {
|
| | | config = project.ConfigurationManager.ActiveConfiguration;
|
| | |
| | | }
|
| | |
|
| | | if (version == null)
|
| | | version = GetSolutionQtVersion(project.DTE.Solution);
|
| | | version = Legacy.QtVersionManager.GetSolutionQtVersion(project.DTE.Solution);
|
| | |
|
| | | return version;
|
| | | }
|
| | |
|
| | | public string GetProjectQtVersion(EnvDTE.Project project, EnvDTE.Configuration config)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings)
|
| | | return QtProject.GetPropertyValue(project, config, "QtInstall");
|
| | |
|
| | |
| | |
|
| | | public string GetProjectQtVersion(EnvDTE.Project project, string platform)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings)
|
| | | return GetProjectQtVersion(project);
|
| | |
|
| | |
| | | version = Environment.GetEnvironmentVariable(env);
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | public bool SaveSolutionQtVersion(EnvDTE.Solution solution, string version)
|
| | | {
|
| | | if (!IsVersionAvailable(version) && version != "$(DefaultQtVersion)")
|
| | | return false;
|
| | | solution.Globals["Qt5Version"] = version;
|
| | | if (!solution.Globals.get_VariablePersists("Qt5Version"))
|
| | | solution.Globals.set_VariablePersists("Qt5Version", true);
|
| | | return true;
|
| | | }
|
| | |
|
| | | public string GetSolutionQtVersion(EnvDTE.Solution solution)
|
| | | {
|
| | | if (solution == null)
|
| | | return null;
|
| | |
|
| | | if (solution.Globals.get_VariableExists("Qt5Version")) {
|
| | | var version = (string)solution.Globals["Qt5Version"];
|
| | | return VerifyIfQtVersionExists(version) ? version : null;
|
| | | }
|
| | |
|
| | | return null;
|
| | | }
|
| | |
|
| | | public string GetDefaultVersion()
|
| | |
| | | }
|
| | | }
|
| | | return VerifyIfQtVersionExists(defaultVersion) ? defaultVersion : null;
|
| | | }
|
| | |
|
| | | public string GetDefaultVersionString()
|
| | | {
|
| | | string defaultVersion = null;
|
| | | try {
|
| | | var key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\" + regVersionPath, false);
|
| | | if (key != null)
|
| | | defaultVersion = key.GetValue("DefaultQtVersion") as string;
|
| | | } catch {
|
| | | Messages.Print("Cannot read the default Qt version from registry.");
|
| | | }
|
| | |
|
| | | if (defaultVersion == null) {
|
| | | var qtDir = Environment.GetEnvironmentVariable("QTDIR");
|
| | | if (string.IsNullOrEmpty(qtDir))
|
| | | return defaultVersion;
|
| | | }
|
| | | return defaultVersion;
|
| | | }
|
| | |
|
| | | public bool SaveDefaultVersion(string version)
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | private bool VerifyIfQtVersionExists(string version)
|
| | | internal bool VerifyIfQtVersionExists(string version)
|
| | | {
|
| | | if (version == "$(DefaultQtVersion)")
|
| | | version = GetDefaultVersion();
|