From ca47896204482bf4a6979e3838bf7f09f61cebeb Mon Sep 17 00:00:00 2001
From: giy <giy@omp-system.ru>
Date: Fri, 02 Sep 2022 14:16:56 +0300
Subject: [PATCH] Обновление до версии 2.9.0
---
QtVsTools.Package/Options/QtVersionsTable.cs | 348 +++++++++++++++++++++++++++++++++------------------------
1 files changed, 202 insertions(+), 146 deletions(-)
diff --git a/QtVsTools.Package/Options/QtVersionsTable.cs b/QtVsTools.Package/Options/QtVersionsTable.cs
index dc6f9c5..cb09fff 100644
--- a/QtVsTools.Package/Options/QtVersionsTable.cs
+++ b/QtVsTools.Package/Options/QtVersionsTable.cs
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 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.
@@ -37,11 +37,12 @@
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Microsoft.Win32;
-using QtVsTools.Common;
namespace QtVsTools.Options
{
- using static EnumExt;
+ using Common;
+ using QtVsTools.Core;
+ using static Common.EnumExt;
public enum BuildHost
{
@@ -52,9 +53,28 @@
public partial class QtVersionsTable : UserControl
{
+ LazyFactory Lazy { get; } = new LazyFactory();
+
public QtVersionsTable()
{
InitializeComponent();
+ }
+
+ [Flags] public enum Column
+ {
+ IsDefault = 0x10,
+ VersionName = 0x20,
+ Host = 0x40,
+ Path = 0x80,
+ Compiler = 0x100
+ }
+
+ [Flags] public enum State
+ {
+ Unknown = 0x00,
+ Existing = 0x01,
+ Removed = 0x02,
+ Modified = 0x04
}
public class Field
@@ -62,57 +82,66 @@
public string Value { get; set; }
public Control Control { get; set; }
public DataGridCell Cell { get; set; }
- public string ValidationError { get; set; }
+ private string error;
+ public string ValidationError {
+ set {
+ UpdateUi = value != error;
+ error = value;
+ }
+ get { return error; }
+ }
public bool IsValid => string.IsNullOrEmpty(ValidationError);
public ToolTip ToolTip
=> IsValid ? null : new ToolTip() { Content = ValidationError };
public int SelectionStart { get; set; }
+ public bool UpdateUi { get; private set; } = false;
}
public class Row
{
- public enum FieldNames { IsDefault, VersionName, Host, Path, Compiler }
+ static LazyFactory StaticLazy { get; } = new LazyFactory();
+ LazyFactory Lazy { get; } = new LazyFactory();
- public Dictionary<FieldNames, Field> _Fields;
- public Dictionary<FieldNames, Field> Fields => _Fields
- ?? (_Fields = GetValues<FieldNames>()
- .Select(field => new KeyValuePair<FieldNames, Field>(field, null))
+ public Dictionary<Column, Field> Fields => Lazy.Get(() =>
+ Fields, () => GetValues<Column>()
+ .Select(field => new KeyValuePair<Column, Field>(field, null))
.ToDictionary(keyValue => keyValue.Key, keyValue => keyValue.Value));
- public Field FieldDefault => Fields[FieldNames.IsDefault]
- ?? (Fields[FieldNames.IsDefault] = new Field());
+ public Field FieldDefault => Fields[Column.IsDefault]
+ ?? (Fields[Column.IsDefault] = new Field());
public bool IsDefault
{
get => (FieldDefault.Value == true.ToString());
set => FieldDefault.Value = value.ToString();
}
- public Field FieldVersionName => Fields[FieldNames.VersionName]
- ?? (Fields[FieldNames.VersionName] = new Field());
+ public Field FieldVersionName => Fields[Column.VersionName]
+ ?? (Fields[Column.VersionName] = new Field());
public string VersionName
{
get => FieldVersionName.Value;
set => FieldVersionName.Value = value;
}
+ public string InitialVersionName { get; set; }
- public Field FieldHost => Fields[FieldNames.Host]
- ?? (Fields[FieldNames.Host] = new Field());
+ public Field FieldHost => Fields[Column.Host]
+ ?? (Fields[Column.Host] = new Field());
public BuildHost Host
{
get => FieldHost.Value.Cast(defaultValue: BuildHost.Windows);
set => FieldHost.Value = value.Cast<string>();
}
- public Field FieldPath => Fields[FieldNames.Path]
- ?? (Fields[FieldNames.Path] = new Field());
+ public Field FieldPath => Fields[Column.Path]
+ ?? (Fields[Column.Path] = new Field());
public string Path
{
get => FieldPath.Value;
set => FieldPath.Value = value;
}
- public Field FieldCompiler => Fields[FieldNames.Compiler]
- ?? (Fields[FieldNames.Compiler] = new Field());
+ public Field FieldCompiler => Fields[Column.Compiler]
+ ?? (Fields[Column.Compiler] = new Field());
public string Compiler
{
get => FieldCompiler.Value;
@@ -124,7 +153,7 @@
public bool DefaultEnabled => !IsDefault && !LastRow;
public bool NameEnabled => !LastRow;
public bool CompilerEnabled => (Host != BuildHost.Windows);
- public Visibility RowVisibility
+ public Visibility RowContentVisibility
=> LastRow ? Visibility.Hidden : Visibility.Visible;
public Visibility ButtonAddVisibility
=> LastRow ? Visibility.Visible : Visibility.Hidden;
@@ -135,17 +164,16 @@
public FontWeight FontWeight
=> IsDefault ? FontWeights.Bold : FontWeights.Normal;
- public static ImageSource _ExplorerIcon;
- public static ImageSource ExplorerIcon => _ExplorerIcon
- ?? (_ExplorerIcon = GetExplorerIcon());
- }
+ public static ImageSource ExplorerIcon => StaticLazy.Get(() =>
+ ExplorerIcon, () => GetExplorerIcon());
- public bool IsValid { get; private set; }
+ public State State { get; set; } = State.Unknown;
+ public bool RowVisible => State != State.Removed;
+ }
Field FocusedField { get; set; }
- List<Row> _Rows;
- List<Row> Rows => _Rows ?? (_Rows = new List<Row>());
+ List<Row> Rows => Lazy.Get(() => Rows, () => new List<Row>());
public IEnumerable<Row> Versions => Rows.TakeWhile(item => !item.LastRow);
public void UpdateVersions(IEnumerable<Row> versions)
@@ -154,15 +182,16 @@
Rows.AddRange(versions);
Rows.Add(new Row { LastRow = true });
DataGrid.ItemsSource = Rows;
- IsValid = true;
FocusedField = null;
Validate(true);
+ Rows.ForEach(item => item.State = State.Existing);
}
public IEnumerable<string> GetErrorMessages()
{
Validate(true);
return Versions
+ .Where(v => v.State != State.Removed)
.SelectMany(v => v.Fields.Values.Select(f => f.ValidationError))
.Where(s => !string.IsNullOrEmpty(s))
.Distinct();
@@ -170,95 +199,73 @@
void Validate(bool mustRefresh)
{
- /////////////////////////
- // Automatic cell values
- foreach (var version in Versions) {
- if (version.Host != BuildHost.Windows && version.Compiler == "msvc") {
- version.Compiler = "g++";
- version.FieldCompiler.SelectionStart = version.Compiler.Length;
- mustRefresh = true;
- } else if (version.Host == BuildHost.Windows && version.Compiler != "msvc") {
- version.Compiler = "msvc";
- version.FieldCompiler.SelectionStart = version.Compiler.Length;
- mustRefresh = true;
- }
- }
-
////////////////////////
// Validate cell values
- string previousValidation;
- bool wasValid = IsValid;
- IsValid = true;
foreach (var version in Versions) {
+ if (!version.State.HasFlag(State.Modified))
+ continue;
//////////////////////
// Default validation
- previousValidation = version.FieldDefault.ValidationError;
- version.FieldDefault.ValidationError = null;
- if (version.IsDefault && version.Host != BuildHost.Windows) {
- version.FieldDefault.ValidationError = "Default version: host must be Windows";
- IsValid = false;
+ if (version.State.HasFlag((State)Column.IsDefault)) {
+ version.FieldDefault.ValidationError = null;
+ if (version.IsDefault && version.Host != BuildHost.Windows)
+ version.FieldDefault.ValidationError = "Default version: Host must be Windows";
+ mustRefresh |= version.FieldDefault.UpdateUi;
}
- if (previousValidation != version.FieldDefault.ValidationError)
- mustRefresh = true;
///////////////////
// Name validation
- previousValidation = version.FieldVersionName.ValidationError;
- version.FieldVersionName.ValidationError = null;
- if (string.IsNullOrEmpty(version.VersionName)) {
- version.FieldVersionName.ValidationError = "Name cannot be empty";
- IsValid = false;
- } else if (Versions
- .Where(otherVersion => otherVersion != version
- && otherVersion.VersionName == version.VersionName)
- .Any()) {
- version.FieldVersionName.ValidationError = "Duplicate version names";
- IsValid = false;
+ if (version.State.HasFlag((State)Column.VersionName)) {
+ version.FieldVersionName.ValidationError = null;
+ if (string.IsNullOrEmpty(version.VersionName)) {
+ version.FieldVersionName.ValidationError = "Name cannot be empty";
+ } else if (Versions.Where(otherVersion => otherVersion != version
+ && otherVersion.VersionName == version.VersionName).Any()) {
+ version.FieldVersionName.ValidationError = "Duplicate version names";
+ }
+ mustRefresh |= version.FieldVersionName.UpdateUi;
}
- if (previousValidation != version.FieldVersionName.ValidationError)
- mustRefresh = true;
///////////////////
// Host validation
- previousValidation = version.FieldHost.ValidationError;
- version.FieldHost.ValidationError = null;
- if (version.IsDefault && version.Host != BuildHost.Windows) {
- version.FieldHost.ValidationError = "Default version: host must be Windows";
- IsValid = false;
+ if (version.State.HasFlag((State)Column.Host)) {
+ version.FieldHost.ValidationError = null;
+ if (version.IsDefault && version.Host != BuildHost.Windows)
+ version.FieldHost.ValidationError = "Default version: Host must be Windows";
+ mustRefresh |= version.FieldHost.UpdateUi;
}
- if (previousValidation != version.FieldHost.ValidationError)
- mustRefresh = true;
///////////////////
// Path validation
- previousValidation = version.FieldPath.ValidationError;
- version.FieldPath.ValidationError = null;
- if (string.IsNullOrEmpty(version.Path)) {
- version.FieldPath.ValidationError = "Path cannot be empty";
- IsValid = false;
- } else if (version.Host == BuildHost.Windows && !Directory.Exists(version.Path)) {
- version.FieldPath.ValidationError = "Path does not exist";
- IsValid = false;
+ if (version.State.HasFlag((State)Column.Path)) {
+ version.FieldPath.ValidationError = null;
+ if (string.IsNullOrEmpty(version.Path)) {
+ version.FieldPath.ValidationError = "Path cannot be empty";
+ } else if (version.Host == BuildHost.Windows) {
+ string path = NormalizePath(version.Path);
+ if (path == null) {
+ version.FieldPath.ValidationError = "Invalid path format";
+ } else {
+ if (!QMake.Exists(path))
+ version.FieldPath.ValidationError = "Cannot find qmake.exe";
+ }
+ }
+ mustRefresh |= version.FieldPath.UpdateUi;
}
- if (previousValidation != version.FieldPath.ValidationError)
- mustRefresh = true;
///////////////////////
// Compiler validation
- previousValidation = version.FieldCompiler.ValidationError;
- version.FieldCompiler.ValidationError = null;
- if (string.IsNullOrEmpty(version.Compiler)) {
- version.FieldCompiler.ValidationError = "Compiler cannot be empty";
- IsValid = false;
+ if (version.State.HasFlag((State)Column.Compiler)) {
+ version.FieldCompiler.ValidationError = null;
+ if (string.IsNullOrEmpty(version.Compiler))
+ version.FieldCompiler.ValidationError = "Compiler cannot be empty";
+ mustRefresh |= version.FieldCompiler.UpdateUi;
}
- if (previousValidation != version.FieldCompiler.ValidationError)
- mustRefresh = true;
}
//////////////////////////////////////
// Refresh versions table if required
- mustRefresh |= (wasValid != IsValid);
if (mustRefresh) {
// Reset bindings
foreach (var version in Versions) {
@@ -304,22 +311,20 @@
if (sender is Control control && GetBinding(control) is Row version) {
if (version.LastRow)
return;
-
- Row.FieldNames field;
- if (string.IsNullOrEmpty(control.Name) || !control.Name.TryCast(out field))
+ if (string.IsNullOrEmpty(control.Name) || !control.Name.TryCast(out Column column))
return;
- var fieldBinding = version.Fields[field];
- fieldBinding.Control = control;
- fieldBinding.Cell = FindContainingCell(control);
- if (fieldBinding.Cell != null) {
- fieldBinding.Cell.Background =
- fieldBinding.IsValid ? Brushes.Transparent : InvalidCellBackground;
+ var field = version.Fields[column];
+ field.Control = control;
+ field.Cell = FindContainingCell(control);
+ if (field.Cell != null) {
+ field.Cell.Background =
+ field.IsValid ? Brushes.Transparent : InvalidCellBackground;
}
- if (fieldBinding == FocusedField)
+ if (field == FocusedField)
control.Focus();
- if (control is TextBox textBox && fieldBinding.SelectionStart >= 0)
- textBox.Select(fieldBinding.SelectionStart, 0);
+ if (control is TextBox textBox && field.SelectionStart >= 0)
+ textBox.Select(field.SelectionStart, 0);
}
}
@@ -339,24 +344,24 @@
void Control_GotFocus(object sender, RoutedEventArgs e)
{
if (sender is Control control && GetBinding(control) is Row version) {
- Row.FieldNames field;
- if (string.IsNullOrEmpty(control.Name) || !control.Name.TryCast(out field))
+ if (string.IsNullOrEmpty(control.Name) || !control.Name.TryCast(out Column column))
return;
- var fieldBinding = version.Fields[field];
- if (fieldBinding.Control != control)
+
+ var field = version.Fields[column];
+ if (field.Control != control)
return;
- FocusedField = fieldBinding;
+ FocusedField = field;
}
}
void Control_LostFocus(object sender, RoutedEventArgs e)
{
if (sender is Control control && GetBinding(control) is Row version) {
- Row.FieldNames field;
- if (string.IsNullOrEmpty(control.Name) || !control.Name.TryCast(out field))
+ if (string.IsNullOrEmpty(control.Name) || !control.Name.TryCast(out Column column))
return;
- var fieldBinding = version.Fields[field];
- if (fieldBinding != FocusedField || fieldBinding.Control != control)
+
+ var field = version.Fields[column];
+ if (field != FocusedField || field.Control != control)
return;
FocusedField = null;
}
@@ -365,29 +370,32 @@
void TextBox_SelectionChanged(object sender, RoutedEventArgs e)
{
if (sender is TextBox textBox && GetBinding(textBox) is Row version) {
- Row.FieldNames field;
- if (string.IsNullOrEmpty(textBox.Name) || !textBox.Name.TryCast(out field))
+ if (string.IsNullOrEmpty(textBox.Name) || !textBox.Name.TryCast(out Column column))
return;
- var fieldBinding = version.Fields[field];
- if (fieldBinding.Control != textBox)
+
+ var field = version.Fields[column];
+ if (field.Control != textBox)
return;
- fieldBinding.SelectionStart = textBox.SelectionStart;
+ field.SelectionStart = textBox.SelectionStart;
}
}
void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (sender is TextBox textBox && GetBinding(textBox) is Row version) {
- Row.FieldNames field;
- if (string.IsNullOrEmpty(textBox.Name) || !textBox.Name.TryCast(out field))
+ if (string.IsNullOrEmpty(textBox.Name) || !textBox.Name.TryCast(out Column column))
return;
- var fieldBinding = version.Fields[field];
- if (fieldBinding == null
- || fieldBinding.Control != textBox
- || fieldBinding.Value == textBox.Text)
+
+ var field = version.Fields[column];
+ if (field == null
+ || field.Control != textBox
+ || field.Value == textBox.Text)
return;
- fieldBinding.SelectionStart = textBox.SelectionStart;
- fieldBinding.Value = textBox.Text;
+
+ field.SelectionStart = textBox.SelectionStart;
+ field.Value = textBox.Text;
+ version.State |= State.Modified | (State)column;
+
Validate(false);
}
}
@@ -397,28 +405,49 @@
if (sender is ComboBox comboBox && GetBinding(comboBox) is Row version) {
if (!comboBox.IsEnabled || comboBox.SelectedIndex < 0)
return;
+ if (string.IsNullOrEmpty(comboBox.Name) || !comboBox.Name.TryCast(out Column column))
+ return;
+
string comboBoxValue = comboBox.Items[comboBox.SelectedIndex] as string;
- string controlName = comboBox.Name;
- Row.FieldNames field;
- if (string.IsNullOrEmpty(controlName) || !controlName.TryCast(out field))
+ var field = version.Fields[column];
+ if (field == null
+ || field.Control != comboBox
+ || field.Value == comboBoxValue)
return;
- var fieldBinding = version.Fields[field];
- if (fieldBinding == null
- || fieldBinding.Control != comboBox
- || fieldBinding.Value == comboBoxValue)
- return;
- fieldBinding.Value = comboBoxValue;
- Validate(false);
+
+ field.Value = comboBoxValue;
+ version.State |= State.Modified | (State)Column.Host;
+
+ bool mustRefresh = false;
+ if (version.Host != BuildHost.Windows && version.Compiler == "msvc") {
+ version.Compiler = "g++";
+ version.FieldCompiler.SelectionStart = version.Compiler.Length;
+ version.State |= (State)Column.Compiler;
+ mustRefresh = true;
+ } else if (version.Host == BuildHost.Windows && version.Compiler != "msvc") {
+ version.Compiler = "msvc";
+ version.FieldCompiler.SelectionStart = version.Compiler.Length;
+ version.State |= (State)Column.Compiler;
+ mustRefresh = true;
+ }
+
+ Validate(mustRefresh);
}
+ }
+
+ static void SetDefaultState(ref Row version, bool value)
+ {
+ version.IsDefault = value;
+ version.State |= State.Modified | (State)Column.IsDefault;
}
void Default_Click(object sender, RoutedEventArgs e)
{
if (sender is CheckBox checkBox && GetBinding(checkBox) is Row version) {
- var defaultVersion = Rows.Where(row => row.IsDefault).FirstOrDefault();
+ var defaultVersion = Rows.FirstOrDefault(row => row.IsDefault);
if (defaultVersion != null)
- defaultVersion.IsDefault = false;
- version.IsDefault = true;
+ SetDefaultState(ref defaultVersion, false);
+ SetDefaultState(ref version, true);
Validate(true);
}
}
@@ -427,12 +456,16 @@
{
var version = new Row()
{
- IsDefault = !Versions.Any(),
+ IsDefault = !Versions.Any(x => x.State != State.Removed),
Host = BuildHost.Windows,
Path = "",
Compiler = "msvc",
- LastRow = false
+ LastRow = false,
+ State = State.Modified | (State)Column.VersionName | (State)Column.Host
+ | (State)Column.Path | (State)Column.Compiler
};
+ if (version.IsDefault)
+ version.State |= (State)Column.IsDefault;
Rows.Insert(Rows.Count - 1, version);
FocusedField = version.FieldVersionName;
Validate(true);
@@ -441,10 +474,26 @@
void Remove_Click(object sender, RoutedEventArgs e)
{
if (sender is Button button && GetBinding(button) is Row version) {
- Rows.Remove(version);
- if (version.IsDefault && Versions.Any())
- Versions.First().IsDefault = true;
+ version.State = State.Removed;
+ if (version.IsDefault) {
+ var first = Versions.FirstOrDefault(x => x.State != State.Removed);
+ if (first != null)
+ SetDefaultState(ref first, true);
+ }
Validate(true);
+ }
+ }
+
+ static string NormalizePath(string path)
+ {
+ if (string.IsNullOrEmpty(path))
+ return path;
+ try {
+ return Path.GetFullPath(new Uri(path).LocalPath)
+ .TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
+ .ToUpperInvariant();
+ } catch (UriFormatException) {
+ return null;
}
}
@@ -462,6 +511,7 @@
if (openFileDialog.ShowDialog() == true) {
var qmakePath = openFileDialog.FileName;
var qmakeDir = Path.GetDirectoryName(qmakePath);
+ var previousPath = NormalizePath(version.Path);
if (Path.GetFileName(qmakeDir)
.Equals("bin", StringComparison.InvariantCultureIgnoreCase)) {
qmakeDir = Path.GetDirectoryName(qmakeDir);
@@ -469,12 +519,18 @@
} else {
version.Path = qmakePath;
}
+
+ if (previousPath != NormalizePath(version.Path))
+ version.State |= State.Modified | (State)Column.Path;
+
if (string.IsNullOrEmpty(version.VersionName)) {
version.VersionName = string.Format("{0}_{1}",
Path.GetFileName(Path.GetDirectoryName(qmakeDir)),
Path.GetFileName(qmakeDir))
.Replace(" ", "_");
+ version.State |= State.Modified | (State)Column.VersionName;
}
+
Validate(true);
}
}
@@ -503,9 +559,9 @@
static object GetBinding(FrameworkElement control)
{
if (control == null
- || control.BindingGroup == null
- || control.BindingGroup.Items == null
- || control.BindingGroup.Items.Count == 0) {
+ || control.BindingGroup == null
+ || control.BindingGroup.Items == null
+ || control.BindingGroup.Items.Count == 0) {
return null;
}
return control.BindingGroup.Items[0];
@@ -515,7 +571,7 @@
{
while (control != null) {
if (control is ContentPresenter contentPresenter
- && contentPresenter.Parent is DataGridCell cell) {
+ && contentPresenter.Parent is DataGridCell cell) {
return cell;
}
control = VisualTreeHelper.GetParent(control);
--
Gitblit v1.9.1