aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiguel Costa <miguel.costa@qt.io>2018-10-04 23:37:33 +0200
committerMiguel Costa <miguel.costa@qt.io>2018-10-24 11:36:08 +0000
commit9463ffcc35db59f6519a8ea70ca884a3573e65da (patch)
tree477687f0fa8e937181e115e3f49fecdafdcadeda
parent4886ac44e587a44ba4fc63c6cd65d66e6e1b47df (diff)
Add QML debug options to project settings
Added two new options to the Qt project settings dialog: "QML Debug", that enables/disables the debugging of QML code, and "QML Debug Port", that allows the TCP port of the QML runtime to be configured. When creating new projects or opening projects created with previous versions of the Qt VS Tools, QML debugging will be enabled by default. Task-number: QTVSADDINBUG-412 Change-Id: I2ad9ed8ed575b2349e74910870d867adce5d94a8 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
-rw-r--r--src/qtprojectlib/QtProject.cs248
-rw-r--r--src/qtprojectlib/QtVSIPSettings.cs20
-rw-r--r--src/qtvstools/DteEventsHandler.cs25
-rw-r--r--src/qtvstools/ProjectQtSettings.cs77
4 files changed, 358 insertions, 12 deletions
diff --git a/src/qtprojectlib/QtProject.cs b/src/qtprojectlib/QtProject.cs
index 7c88da3c..7dd1a248 100644
--- a/src/qtprojectlib/QtProject.cs
+++ b/src/qtprojectlib/QtProject.cs
@@ -85,6 +85,7 @@ namespace QtProjectLib
dte = envPro.DTE;
vcPro = envPro.Object as VCProject;
qtMsBuild = new QtMsBuildContainer(new VCPropertyStorageProvider());
+ InitializeQmlJsDebugger(vcPro);
}
public VCProject VCProject
@@ -3405,6 +3406,253 @@ namespace QtProjectLib
}
HelperFunctions.SetDebuggingEnvironment(envPro);
+ InitializeQmlJsDebugger(envPro.Object as VCProject);
+ }
+
+ public class CppConfig
+ {
+ public VCConfiguration Config;
+ public IVCRulePropertyStorage Cpp;
+
+ public string GetUserPropertyValue(string pszPropName)
+ {
+ var vcProj = Config.project as VCProject;
+ var projProps = vcProj as IVCBuildPropertyStorage;
+ try {
+ return projProps.GetPropertyValue(pszPropName, Config.Name, "UserFile");
+ } catch (Exception e) {
+ System.Diagnostics.Debug.WriteLine(
+ e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace);
+ return string.Empty;
+ }
+ }
+
+ public void SetUserPropertyValue(string pszPropName, string pszPropValue)
+ {
+ var vcProj = Config.project as VCProject;
+ var projProps = vcProj as IVCBuildPropertyStorage;
+ try {
+ projProps.SetPropertyValue(pszPropName, Config.Name, "UserFile", pszPropValue);
+ } catch (Exception e) {
+ System.Diagnostics.Debug.WriteLine(
+ e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace);
+ }
+ }
+
+ public void RemoveUserProperty(string pszPropName)
+ {
+ var vcProj = Config.project as VCProject;
+ var projProps = vcProj as IVCBuildPropertyStorage;
+ try {
+ projProps.RemoveProperty(pszPropName, Config.Name, "UserFile");
+ } catch (Exception e) {
+ System.Diagnostics.Debug.WriteLine(
+ e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace);
+ }
+ }
+ }
+
+ public static IEnumerable<CppConfig> GetCppConfigs(VCProject vcPro)
+ {
+ return ((IVCCollection)vcPro.Configurations).Cast<VCConfiguration>()
+ .Select(x => new CppConfig
+ {
+ Config = x,
+ Cpp = x.Rules.Item("CL") as IVCRulePropertyStorage,
+ })
+ .Where(x => x.Cpp != null);
+ }
+
+ public static IEnumerable<CppConfig> GetCppDebugConfigs(VCProject vcPro)
+ {
+ return GetCppConfigs(vcPro).Where(x => x.Cpp
+ .GetEvaluatedPropertyValue("PreprocessorDefinitions").Split(new char[] { ';' })
+ .Contains("QT_NO_DEBUG") == false);
+ }
+
+ public static bool IsQtQmlDebugDefined(VCProject vcPro)
+ {
+ return (GetCppDebugConfigs(vcPro).Where(x => x.Cpp
+ .GetEvaluatedPropertyValue("PreprocessorDefinitions").Split(new char[] { ';' })
+ .Contains("QT_QML_DEBUG") == false)
+ .Any() == false);
+ }
+
+ public static void DefineQtQmlDebug(VCProject vcPro)
+ {
+ var configs = GetCppDebugConfigs(vcPro).Where(x => x.Cpp
+ .GetEvaluatedPropertyValue("PreprocessorDefinitions").Split(new char[] { ';' })
+ .Contains("QT_QML_DEBUG") == false)
+ .Select(x => new
+ {
+ x.Cpp,
+ Macros = x.Cpp.GetUnevaluatedPropertyValue("PreprocessorDefinitions")
+ });
+
+ foreach (var config in configs) {
+ config.Cpp.SetPropertyValue("PreprocessorDefinitions",
+ string.Format("QT_QML_DEBUG;{0}", config.Macros));
+ }
+ }
+
+ public static void UndefineQtQmlDebug(VCProject vcPro)
+ {
+ var configs = GetCppDebugConfigs(vcPro).Where(x => x.Cpp
+ .GetEvaluatedPropertyValue("PreprocessorDefinitions").Split(new char[] { ';' })
+ .Contains("QT_QML_DEBUG") == true)
+ .Select(x => new
+ {
+ x.Cpp,
+ Macros = x.Cpp.GetUnevaluatedPropertyValue("PreprocessorDefinitions")
+ .Split(new char[] { ';' }).ToList()
+ });
+
+ foreach (var config in configs) {
+ config.Macros.Remove("QT_QML_DEBUG");
+ config.Cpp.SetPropertyValue("PreprocessorDefinitions",
+ string.Join(";", config.Macros));
+ }
+ }
+
+ public static bool IsQmlJsDebuggerInitialized(VCProject vcPro)
+ {
+ foreach (var config in GetCppDebugConfigs(vcPro)) {
+ var qmlDebugPort = config.GetUserPropertyValue("QmlDebugPort");
+ if (string.IsNullOrEmpty(qmlDebugPort))
+ return false;
+
+ if (qmlDebugPort != "false" && !IsQtQmlDebugDefined(vcPro))
+ return false;
+ }
+ return true;
+ }
+
+ public static void InitializeQmlJsDebugger(VCProject vcPro)
+ {
+ if (vcPro == null || !IsQtMsBuildEnabled(vcPro))
+ return;
+
+ if (!IsQmlJsDebuggerInitialized(vcPro)) {
+ DefineQtQmlDebug(vcPro);
+ DefineQmlJsDebugger(vcPro);
+ }
+ }
+
+ public static bool IsQmlJsDebuggerDefined(VCProject vcPro)
+ {
+ foreach (var config in GetCppDebugConfigs(vcPro)) {
+ var qmlDebug = config.GetUserPropertyValue("QmlDebug");
+ if (string.IsNullOrEmpty(qmlDebug))
+ return false;
+ var debugArgs = config.GetUserPropertyValue("LocalDebuggerCommandArguments");
+ if (string.IsNullOrEmpty(debugArgs))
+ return false;
+ if (!debugArgs.Contains(qmlDebug))
+ return false;
+ }
+ return true;
+ }
+
+ public static readonly ushort DefaultQmlDebugPort // 0x7451 = 29777
+ = BitConverter.ToUInt16(Encoding.ASCII.GetBytes("Qt"), 0);
+
+ public static void DefineQmlJsDebugger(VCProject vcPro)
+ {
+ var configs = GetCppDebugConfigs(vcPro)
+ .Select(x => new
+ {
+ Self = x,
+ QmlDebug = x.GetUserPropertyValue("QmlDebug"),
+ Args = x.GetUserPropertyValue("LocalDebuggerCommandArguments")
+ })
+ .Where(x => string.IsNullOrEmpty(x.QmlDebug) || !x.Args.Contains(x.QmlDebug));
+
+ foreach (var config in configs) {
+
+ config.Self.RemoveUserProperty("LocalDebuggerCommandArguments");
+ config.Self.RemoveUserProperty("QmlDebug");
+ config.Self.RemoveUserProperty("QmlDebugPort");
+
+ config.Self.SetUserPropertyValue("QmlDebugPort",
+ DefaultQmlDebugPort.ToString());
+
+ config.Self.SetUserPropertyValue("QmlDebug",
+ "-qmljsdebugger=port:$(QmlDebugPort),block");
+
+ config.Self.SetUserPropertyValue("LocalDebuggerCommandArguments",
+ string.Join(" ", new[] { config.Args, "$(QmlDebug)" }).Trim());
+ }
+ }
+
+ public static void UndefineQmlJsDebugger(VCProject vcPro)
+ {
+ var configs = GetCppDebugConfigs(vcPro)
+ .Select(x => new
+ {
+ Self = x,
+ QmlDebug = x.GetUserPropertyValue("QmlDebug"),
+ Args = x.GetUserPropertyValue("LocalDebuggerCommandArguments")
+ })
+ .Where(x => !string.IsNullOrEmpty(x.QmlDebug) && x.Args.Contains(x.QmlDebug));
+
+ foreach (var config in configs) {
+
+ config.Self.SetUserPropertyValue("QmlDebug", "##QMLDEBUG##");
+ var args = config.Self.GetUserPropertyValue("LocalDebuggerCommandArguments");
+
+ var newArgs = args.Replace("##QMLDEBUG##", "").Trim();
+ if (string.IsNullOrEmpty(newArgs))
+ config.Self.RemoveUserProperty("LocalDebuggerCommandArguments");
+ else
+ config.Self.SetUserPropertyValue("LocalDebuggerCommandArguments", newArgs);
+
+ config.Self.RemoveUserProperty("QmlDebug");
+ config.Self.SetUserPropertyValue("QmlDebugPort", "false");
+ }
+ }
+
+ public bool QmlDebug
+ {
+ get
+ {
+ return IsQtQmlDebugDefined(vcPro) && IsQmlJsDebuggerDefined(vcPro);
+ }
+ set
+ {
+ bool enabled = (IsQtQmlDebugDefined(vcPro) && IsQmlJsDebuggerDefined(vcPro));
+ if (value == enabled)
+ return;
+
+ if (value) {
+ DefineQtQmlDebug(vcPro);
+ DefineQmlJsDebugger(vcPro);
+ } else {
+ UndefineQtQmlDebug(vcPro);
+ UndefineQmlJsDebugger(vcPro);
+ }
+ }
+ }
+
+ public ushort QmlDebugPort
+ {
+ get
+ {
+ if (!QmlDebug)
+ return DefaultQmlDebugPort;
+ var portString = GetCppDebugConfigs(vcPro).First()
+ .GetUserPropertyValue("QmlDebugPort");
+ ushort port;
+ if (!ushort.TryParse(portString, out port))
+ return DefaultQmlDebugPort;
+ return port;
+ }
+ set
+ {
+ if (QmlDebug) {
+ foreach (var config in GetCppDebugConfigs(vcPro))
+ config.SetUserPropertyValue("QmlDebugPort", value.ToString());
+ }
+ }
}
}
diff --git a/src/qtprojectlib/QtVSIPSettings.cs b/src/qtprojectlib/QtVSIPSettings.cs
index 93fb20b8..230eeeb8 100644
--- a/src/qtprojectlib/QtVSIPSettings.cs
+++ b/src/qtprojectlib/QtVSIPSettings.cs
@@ -506,5 +506,25 @@ namespace QtProjectLib
return;
regKey.SetValue(key, val ? 1 : 0);
}
+
+ public static bool GetQmlDebug(EnvDTE.Project project)
+ {
+ return QtProject.Create(project).QmlDebug;
+ }
+
+ public static void SaveQmlDebug(EnvDTE.Project project, bool enabled)
+ {
+ QtProject.Create(project).QmlDebug = enabled;
+ }
+
+ public static ushort GetQmlDebugPort(EnvDTE.Project project)
+ {
+ return QtProject.Create(project).QmlDebugPort;
+ }
+
+ public static void SaveQmlDebugPort(EnvDTE.Project project, ushort port)
+ {
+ QtProject.Create(project).QmlDebugPort = port;
+ }
}
}
diff --git a/src/qtvstools/DteEventsHandler.cs b/src/qtvstools/DteEventsHandler.cs
index 23b8671f..af446568 100644
--- a/src/qtvstools/DteEventsHandler.cs
+++ b/src/qtvstools/DteEventsHandler.cs
@@ -94,7 +94,7 @@ namespace QtVsTools
dispId_VCCLCompilerTool_PrecompiledHeaderThrough = GetPropertyDispId(typeof(VCCLCompilerTool), "PrecompiledHeaderThrough");
dispId_VCCLCompilerTool_PreprocessorDefinitions = GetPropertyDispId(typeof(VCCLCompilerTool), "PreprocessorDefinitions");
dispId_VCCLCompilerTool_AdditionalIncludeDirectories = GetPropertyDispId(typeof(VCCLCompilerTool), "AdditionalIncludeDirectories");
- RegisterVCProjectEngineEvents();
+ InitializeVCProjects();
DefaultEditorsClient.Initialize(this);
DefaultEditorsClient.Instance.Listen();
@@ -498,7 +498,7 @@ namespace QtVsTools
void SolutionEvents_ProjectAdded(Project project)
{
if (HelperFunctions.IsQMakeProject(project)) {
- RegisterVCProjectEngineEvents(project);
+ InitializeVCProject(project);
var vcpro = project.Object as VCProject;
VCFilter filter = null;
foreach (VCFilter f in vcpro.Filters as IVCCollection) {
@@ -541,7 +541,7 @@ namespace QtVsTools
{
foreach (var p in HelperFunctions.ProjectsInSolution(Vsix.Instance.Dte)) {
if (HelperFunctions.IsQtProject(p))
- RegisterVCProjectEngineEvents(p);
+ InitializeVCProject(p);
}
}
@@ -550,26 +550,24 @@ namespace QtVsTools
QtProject.ClearInstances();
}
- /// <summary>
- /// Tries to get a VCProjectEngine from the loaded projects and registers the handlers for VCProjectEngineEvents.
- /// </summary>
- void RegisterVCProjectEngineEvents()
+ void InitializeVCProjects()
{
foreach (var project in HelperFunctions.ProjectsInSolution(dte)) {
if (project != null && HelperFunctions.IsQtProject(project))
- RegisterVCProjectEngineEvents(project);
+ InitializeVCProject(project);
}
}
- /// <summary>
- /// Retrieves the VCProjectEngine from the given project and registers the handlers for VCProjectEngineEvents.
- /// </summary>
- void RegisterVCProjectEngineEvents(Project p)
+ void InitializeVCProject(Project p)
{
if (vcProjectEngineEvents != null)
return;
var vcPrj = p.Object as VCProject;
+ if (vcPrj == null)
+ return;
+
+ // Retrieves the VCProjectEngine from the given project and registers the handlers for VCProjectEngineEvents.
var prjEngine = vcPrj.VCProjectEngine as VCProjectEngine;
if (prjEngine != null) {
vcProjectEngineEvents = prjEngine.Events as VCProjectEngineEvents;
@@ -581,6 +579,9 @@ namespace QtVsTools
}
}
}
+
+ // Initialize QML debugger settings
+ QtProject.InitializeQmlJsDebugger(vcPrj);
}
private void OnVCProjectEngineItemPropertyChange(object item, object tool, int dispid)
diff --git a/src/qtvstools/ProjectQtSettings.cs b/src/qtvstools/ProjectQtSettings.cs
index 2fdff725..78cd8806 100644
--- a/src/qtvstools/ProjectQtSettings.cs
+++ b/src/qtvstools/ProjectQtSettings.cs
@@ -29,6 +29,7 @@
using QtProjectLib;
using System;
using System.ComponentModel;
+using System.Globalization;
using System.Text.RegularExpressions;
namespace QtVsTools
@@ -48,6 +49,8 @@ namespace QtVsTools
newLUpdateOptions = oldLUpdateOptions = QtVSIPSettings.GetLUpdateOptions(project);
newLReleaseOptions = oldLReleaseOptions = QtVSIPSettings.GetLReleaseOptions(project);
newQtVersion = oldQtVersion = versionManager.GetProjectQtVersion(project);
+ QmlDebug = oldQmlDebug = QtVSIPSettings.GetQmlDebug(project);
+ QmlDebugPort = oldQmlDebugPort = QtVSIPSettings.GetQmlDebugPort(project);
}
private QtVersionManager versionManager;
@@ -61,6 +64,8 @@ namespace QtVsTools
private bool oldLUpdateOnBuild;
private string oldLUpdateOptions;
private string oldLReleaseOptions;
+ private bool oldQmlDebug;
+ private ushort oldQmlDebugPort;
private string newMocDir;
private string newMocOptions;
@@ -106,6 +111,12 @@ namespace QtVsTools
if (oldLReleaseOptions != newLReleaseOptions)
QtVSIPSettings.SaveLReleaseOptions(project, newLReleaseOptions);
+ if (oldQmlDebug != QmlDebug)
+ QtVSIPSettings.SaveQmlDebug(project, QmlDebug);
+
+ if (oldQmlDebugPort != QmlDebugPort)
+ QtVSIPSettings.SaveQmlDebugPort(project, QmlDebugPort);
+
if (oldQtVersion != newQtVersion) {
if (qtPro.PromptChangeQtVersion(oldQtVersion, newQtVersion)) {
var newProjectCreated = false;
@@ -229,6 +240,72 @@ namespace QtVsTools
}
}
+ [DisplayName("QML Debug")]
+ [TypeConverter(typeof(QmlDebugConverter))]
+ public bool QmlDebug { get; set; }
+
+ internal class QmlDebugConverter : BooleanConverter
+ {
+ public override object ConvertTo(
+ ITypeDescriptorContext context,
+ CultureInfo culture,
+ object value,
+ Type destinationType)
+ {
+ return (bool)value ? "Enabled" : "Disabled";
+ }
+
+ public override object ConvertFrom(
+ ITypeDescriptorContext context,
+ CultureInfo culture,
+ object value)
+ {
+ return (string)value == "Enabled";
+ }
+ }
+
+ [DisplayName("QML Debug Port")]
+ [TypeConverter(typeof(QmlDebugPortConverter))]
+ public ushort QmlDebugPort { get; set; }
+
+ internal class QmlDebugPortConverter : UInt16Converter
+ {
+ public override object ConvertTo(
+ ITypeDescriptorContext context,
+ CultureInfo culture,
+ object value,
+ Type destinationType)
+ {
+ var obj = context.Instance as ProjectQtSettings;
+ if (obj == null)
+ return QtProject.DefaultQmlDebugPort.ToString();
+
+ if (obj.QmlDebug)
+ return value.ToString();
+
+ return "Disabled";
+ }
+
+ public override object ConvertFrom(
+ ITypeDescriptorContext context,
+ CultureInfo culture,
+ object value)
+ {
+ ushort port;
+ if (!ushort.TryParse((string)value, out port) || port == 0)
+ return QtProject.DefaultQmlDebugPort;
+
+ var obj = context.Instance as ProjectQtSettings;
+ if (obj == null)
+ return QtProject.DefaultQmlDebugPort;
+
+ if (obj.QmlDebug)
+ return port;
+
+ return QtProject.DefaultQmlDebugPort;
+ }
+ }
+
[TypeConverter(typeof(VersionConverter))]
public string Version
{