Наша сборка Qt VS Tools
giy
2022-09-02 ca47896204482bf4a6979e3838bf7f09f61cebeb
QtVsTools.Package/Package/DteEventsHandler.cs
@@ -26,44 +26,45 @@
**
****************************************************************************/
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.VCProjectEngine;
using QtVsTools.Core;
using QtVsTools.Core.QtMsBuild;
using QtVsTools.QtMsBuild;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.VCProjectEngine;
using EnvDTE;
using EnvDTE80;
namespace QtVsTools
{
    using Core;
    using QtMsBuild;
    class DteEventsHandler
    {
        private DTE dte;
        private SolutionEvents solutionEvents;
        private BuildEvents buildEvents;
        private DocumentEvents documentEvents;
        private ProjectItemsEvents projectItemsEvents;
        private readonly DTE dte;
        private readonly SolutionEvents solutionEvents;
        private readonly BuildEvents buildEvents;
        private readonly DocumentEvents documentEvents;
        private readonly ProjectItemsEvents projectItemsEvents;
        private vsBuildAction currentBuildAction = vsBuildAction.vsBuildActionBuild;
        private VCProjectEngineEvents vcProjectEngineEvents;
        private CommandEvents debugStartEvents;
        private CommandEvents debugStartWithoutDebuggingEvents;
        private CommandEvents f1HelpEvents;
        private int dispId_VCFileConfiguration_ExcludedFromBuild;
        private int dispId_VCCLCompilerTool_UsePrecompiledHeader;
        private int dispId_VCCLCompilerTool_PrecompiledHeaderThrough;
        private int dispId_VCCLCompilerTool_PreprocessorDefinitions;
        private int dispId_VCCLCompilerTool_AdditionalIncludeDirectories;
        private readonly CommandEvents debugStartEvents;
        private readonly CommandEvents debugStartWithoutDebuggingEvents;
        private readonly CommandEvents f1HelpEvents;
        private WindowEvents windowEvents;
        private readonly int dispId_VCFileConfiguration_ExcludedFromBuild;
        private readonly int dispId_VCCLCompilerTool_UsePrecompiledHeader;
        private readonly int dispId_VCCLCompilerTool_PrecompiledHeaderThrough;
        private readonly int dispId_VCCLCompilerTool_PreprocessorDefinitions;
        private readonly int dispId_VCCLCompilerTool_AdditionalIncludeDirectories;
        public DteEventsHandler(DTE _dte)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            dte = _dte;
            var events = dte.Events as Events2;
@@ -85,6 +86,9 @@
            solutionEvents.Opened += SolutionEvents_Opened;
            solutionEvents.AfterClosing += SolutionEvents_AfterClosing;
            windowEvents = events.WindowEvents;
            windowEvents.WindowActivated += WindowEvents_WindowActivated;
            var debugCommandsGUID = "{5EFC7975-14BC-11CF-9B2B-00AA00573819}";
            debugStartEvents = events.get_CommandEvents(debugCommandsGUID, 295);
            debugStartEvents.BeforeExecute += debugStartEvents_BeforeExecute;
@@ -105,15 +109,33 @@
            InitializeVCProjects();
        }
        private void WindowEvents_WindowActivated(Window gotFocus, Window lostFocus)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (dte.MainWindow?.Visible == true) {
                windowEvents.WindowActivated -= WindowEvents_WindowActivated;
                windowEvents = null;
                QtVsToolsPackage.Instance.VsMainWindowActivated();
            }
        }
        private void F1HelpEvents_BeforeExecute(
            string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault)
        {
            if (QtVsToolsPackage.Instance.Options.TryQtHelpOnF1Pressed && QtHelp.QueryEditorContextHelp())
            ThreadHelper.ThrowIfNotOnUIThread();
            if (QtVsToolsPackage.Instance.Options.TryQtHelpOnF1Pressed) {
                if (!QtHelp.ShowEditorContextHelp()) {
                    Messages.Print("No help match was found. You can still try to search online at "
                        + "https://doc.qt.io" + ".", false, true);
                }
                CancelDefault = true;
            }
        }
        void debugStartEvents_BeforeExecute(string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var debugger = dte.Debugger;
            if (debugger != null && debugger.CurrentMode != dbgDebugMode.dbgDesignMode)
                return;
@@ -147,6 +169,8 @@
        public void Disconnect()
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (buildEvents != null) {
                buildEvents.OnBuildBegin -= buildEvents_OnBuildBegin;
                buildEvents.OnBuildProjConfigBegin -= OnBuildProjConfigBegin;
@@ -174,12 +198,19 @@
            if (debugStartWithoutDebuggingEvents != null)
                debugStartWithoutDebuggingEvents.BeforeExecute -= debugStartWithoutDebuggingEvents_BeforeExecute;
            if (vcProjectEngineEvents != null)
            if (vcProjectEngineEvents != null) {
                vcProjectEngineEvents.ItemPropertyChange -= OnVCProjectEngineItemPropertyChange;
                vcProjectEngineEvents.ItemPropertyChange2 -= OnVCProjectEngineItemPropertyChange2;
            }
            if (windowEvents != null)
                windowEvents.WindowActivated -= WindowEvents_WindowActivated;
        }
        public void OnBuildProjConfigBegin(string projectName, string projectConfig, string platform, string solutionConfig)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (!QtVsToolsPackage.Instance.LegacyOptions.PreBuildSetup)
                return;
@@ -195,7 +226,7 @@
                    break;
                }
            }
            if (project == null || !HelperFunctions.IsQtProject(project))
            if (project == null || !HelperFunctions.IsVsToolsProject(project))
                return;
            if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings)
@@ -229,9 +260,11 @@
        public void DocumentSaved(Document document)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var qtPro = QtProject.Create(document.ProjectItem.ContainingProject);
            if (!HelperFunctions.IsQtProject(qtPro.VCProject))
            if (!HelperFunctions.IsVsToolsProject(qtPro.VCProject))
                return;
            var file = (VCFile)((IVCCollection)qtPro.VCProject.Files).Item(document.FullName);
@@ -323,10 +356,13 @@
        public void ProjectItemsEvents_ItemAdded(ProjectItem projectItem)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var project = HelperFunctions.GetSelectedQtProject(QtVsToolsPackage.Instance.Dte);
            var qtPro = QtProject.Create(project);
            if (!HelperFunctions.IsQtProject(project))
            if (!HelperFunctions.IsVsToolsProject(project))
                return;
            var vcFile = GetVCFileFromProject(projectItem.Name, qtPro.VCProject);
            if (vcFile == null)
                return;
@@ -373,12 +409,15 @@
                        HelperFunctions.EnsureCustomBuildToolAvailable(projectItem);
                    qtPro.UpdateRccStep(vcFile, null);
                } else if (HelperFunctions.IsTranslationFile(vcFile.Name)) {
                    Translation.RunlUpdate(vcFile);
                }
            } catch { }
        }
        void ProjectItemsEvents_ItemRemoved(ProjectItem ProjectItem)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var pro = HelperFunctions.GetSelectedQtProject(QtVsToolsPackage.Instance.Dte);
            if (pro == null)
                return;
@@ -389,6 +428,8 @@
        void ProjectItemsEvents_ItemRenamed(ProjectItem ProjectItem, string OldName)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (OldName == null)
                return;
            var pro = HelperFunctions.GetSelectedQtProject(QtVsToolsPackage.Instance.Dte);
@@ -397,12 +438,15 @@
            var qtPro = QtProject.Create(pro);
            qtPro.RemoveGeneratedFiles(OldName);
            ProjectItemsEvents_ItemAdded(ProjectItem);
        }
        void SolutionEvents_ProjectAdded(Project project)
        {
            if (HelperFunctions.IsQMakeProject(project)) {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (HelperFunctions.IsQtProject(project)) {
                InitializeVCProject(project);
                QtProjectTracker.Add(project);
                var vcpro = project.Object as VCProject;
@@ -446,9 +490,11 @@
        public void SolutionEvents_Opened()
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            QtProjectTracker.SolutionPath = QtVsToolsPackage.Instance.Dte.Solution.FullName;
            foreach (var p in HelperFunctions.ProjectsInSolution(QtVsToolsPackage.Instance.Dte)) {
                if (HelperFunctions.IsQtProject(p)) {
                if (HelperFunctions.IsVsToolsProject(p)) {
                    InitializeVCProject(p);
                    QtProjectTracker.Add(p);
                }
@@ -464,14 +510,18 @@
        void InitializeVCProjects()
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            foreach (var project in HelperFunctions.ProjectsInSolution(dte)) {
                if (project != null && HelperFunctions.IsQtProject(project))
                if (project != null && HelperFunctions.IsVsToolsProject(project))
                    InitializeVCProject(project);
            }
        }
        void InitializeVCProject(Project p)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (vcProjectEngineEvents != null)
                return;
@@ -480,12 +530,12 @@
                return;
            // Retrieves the VCProjectEngine from the given project and registers the handlers for VCProjectEngineEvents.
            var prjEngine = vcPrj.VCProjectEngine as VCProjectEngine;
            if (prjEngine != null) {
            if (vcPrj.VCProjectEngine is VCProjectEngine prjEngine) {
                vcProjectEngineEvents = prjEngine.Events as VCProjectEngineEvents;
                if (vcProjectEngineEvents != null) {
                    try {
                        vcProjectEngineEvents.ItemPropertyChange += OnVCProjectEngineItemPropertyChange;
                        vcProjectEngineEvents.ItemPropertyChange2 += OnVCProjectEngineItemPropertyChange2;
                    } catch {
                        Messages.DisplayErrorMessage("VCProjectEngine events could not be registered.");
                    }
@@ -495,7 +545,6 @@
        private void OnVCProjectEngineItemPropertyChange(object item, object tool, int dispid)
        {
            //System.Diagnostics.Debug.WriteLine("OnVCProjectEngineItemPropertyChange " + dispid.ToString());
            var vcFileCfg = item as VCFileConfiguration;
            if (vcFileCfg == null) {
                // A global or project specific property has changed.
@@ -506,7 +555,7 @@
                var vcPrj = vcCfg.project as VCProject;
                if (vcPrj == null)
                    return;
                if (!HelperFunctions.IsQtProject(vcPrj))
                if (!HelperFunctions.IsVsToolsProject(vcPrj))
                    return;
                // Ignore property events when using shared compiler properties
                if (QtProject.GetFormatVersion(vcPrj) >= Resources.qtMinFormatVersion_ClProperties)
@@ -538,7 +587,7 @@
                var vcPrj = vcFile.project as VCProject;
                if (vcPrj == null)
                    return;
                if (!HelperFunctions.IsQtProject(vcPrj))
                if (!HelperFunctions.IsVsToolsProject(vcPrj))
                    return;
                // Ignore property events when using shared compiler properties
                if (QtProject.GetFormatVersion(vcPrj) >= Resources.qtMinFormatVersion_ClProperties)
@@ -557,10 +606,27 @@
            }
        }
        private void OnVCProjectEngineItemPropertyChange2(
            object item,
            string propertySheet,
            string itemType,
            string propertyName)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (!propertyName.StartsWith("Qt") || propertyName == "QtLastBackgroundBuild")
                return;
            if (item is VCConfiguration vcConfig
                && vcConfig.project is VCProject vcProject
                && vcProject.Object is Project project) {
                QtProjectIntellisense.Refresh(
                    QtProjectTracker.Get(project, project.FullName).Project, vcConfig.Name);
            }
        }
        private static VCFile GetVCFileFromProject(string absFileName, VCProject project)
        {
            foreach (VCFile f in (IVCCollection)project.Files) {
                if (f.Name.ToLower() == absFileName.ToLower())
                if (f.Name.Equals(absFileName, StringComparison.OrdinalIgnoreCase))
                    return f;
            }
            return null;
@@ -574,8 +640,7 @@
            var pi = type.GetProperty(propertyName);
            if (pi != null) {
                foreach (Attribute attribute in pi.GetCustomAttributes(true)) {
                    var dispIdAttribute = attribute as DispIdAttribute;
                    if (dispIdAttribute != null)
                    if (attribute is DispIdAttribute dispIdAttribute)
                        return dispIdAttribute.Value;
                }
            }