Skip to content

Commit d71189c

Browse files
committed
feature: tooltip for submodule list item (#1307)
1 parent 55232ae commit d71189c

File tree

6 files changed

+122
-32
lines changed

6 files changed

+122
-32
lines changed

src/Commands/QuerySubmodules.cs

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Text;
34
using System.Text.RegularExpressions;
45

56
namespace SourceGit.Commands
67
{
78
public partial class QuerySubmodules : Command
89
{
9-
[GeneratedRegex(@"^[U\-\+ ][0-9a-f]+\s(.*)\s\(.*\)$")]
10-
private static partial Regex REG_FORMAT1();
11-
[GeneratedRegex(@"^[U\-\+ ][0-9a-f]+\s(.*)$")]
12-
private static partial Regex REG_FORMAT2();
13-
[GeneratedRegex(@"^\s?[\w\?]{1,4}\s+(.+)$")]
10+
[GeneratedRegex(@"^([U\-\+ ])([0-9a-f]+)\s(.*?)(\s\(.*\))?$")]
1411
private static partial Regex REG_FORMAT_STATUS();
12+
[GeneratedRegex(@"^\s?[\w\?]{1,4}\s+(.+)$")]
13+
private static partial Regex REG_FORMAT_DIRTY();
1514

1615
public QuerySubmodules(string repo)
1716
{
@@ -25,49 +24,65 @@ public QuerySubmodules(string repo)
2524
var submodules = new List<Models.Submodule>();
2625
var rs = ReadToEnd();
2726

28-
var builder = new StringBuilder();
29-
var lines = rs.StdOut.Split(['\r', '\n'], System.StringSplitOptions.RemoveEmptyEntries);
27+
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
28+
var needCheckLocalChanges = new Dictionary<string, Models.Submodule>();
3029
foreach (var line in lines)
3130
{
32-
var match = REG_FORMAT1().Match(line);
31+
var match = REG_FORMAT_STATUS().Match(line);
3332
if (match.Success)
3433
{
35-
var path = match.Groups[1].Value;
36-
builder.Append($"\"{path}\" ");
37-
submodules.Add(new Models.Submodule() { Path = path });
38-
continue;
39-
}
34+
var stat = match.Groups[1].Value;
35+
var sha = match.Groups[2].Value;
36+
var path = match.Groups[3].Value;
4037

41-
match = REG_FORMAT2().Match(line);
42-
if (match.Success)
43-
{
44-
var path = match.Groups[1].Value;
45-
builder.Append($"\"{path}\" ");
46-
submodules.Add(new Models.Submodule() { Path = path });
38+
var module = new Models.Submodule() { Path = path, SHA = sha };
39+
switch (stat[0])
40+
{
41+
case '-':
42+
module.Status = Models.SubmoduleStatus.NotInited;
43+
break;
44+
case '+':
45+
module.Status = Models.SubmoduleStatus.RevisionChanged;
46+
break;
47+
case 'U':
48+
module.Status = Models.SubmoduleStatus.Unmerged;
49+
break;
50+
default:
51+
module.Status = Models.SubmoduleStatus.Normal;
52+
needCheckLocalChanges.Add(path, module);
53+
break;
54+
}
55+
56+
submodules.Add(module);
4757
}
4858
}
4959

50-
if (submodules.Count > 0)
60+
if (needCheckLocalChanges.Count > 0)
5161
{
62+
var builder = new StringBuilder();
63+
foreach (var kv in needCheckLocalChanges)
64+
{
65+
builder.Append('"');
66+
builder.Append(kv.Key);
67+
builder.Append("\" ");
68+
}
69+
5270
Args = $"--no-optional-locks status -uno --porcelain -- {builder}";
5371
rs = ReadToEnd();
5472
if (!rs.IsSuccess)
5573
return submodules;
5674

57-
var dirty = new HashSet<string>();
58-
lines = rs.StdOut.Split(['\r', '\n'], System.StringSplitOptions.RemoveEmptyEntries);
75+
lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
5976
foreach (var line in lines)
6077
{
61-
var match = REG_FORMAT_STATUS().Match(line);
78+
var match = REG_FORMAT_DIRTY().Match(line);
6279
if (match.Success)
6380
{
6481
var path = match.Groups[1].Value;
65-
dirty.Add(path);
82+
if (needCheckLocalChanges.TryGetValue(path, out var m))
83+
m.Status = Models.SubmoduleStatus.Modified;
6684
}
6785
}
68-
69-
foreach (var submodule in submodules)
70-
submodule.IsDirty = dirty.Contains(submodule.Path);
7186
}
7287

7388
return submodules;

src/Models/Submodule.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
11
namespace SourceGit.Models
22
{
3+
public enum SubmoduleStatus
4+
{
5+
Normal = 0,
6+
NotInited,
7+
RevisionChanged,
8+
Unmerged,
9+
Modified,
10+
}
11+
312
public class Submodule
413
{
5-
public string Path { get; set; } = "";
6-
public bool IsDirty { get; set; } = false;
14+
public string Path { get; set; } = string.Empty;
15+
public string SHA { get; set; } = string.Empty;
16+
public SubmoduleStatus Status { get; set; } = SubmoduleStatus.Normal;
17+
public bool IsDirty => Status > SubmoduleStatus.NotInited;
718
}
819
}

src/Resources/Locales/en_US.axaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,11 @@
704704
<x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">Relative Path:</x:String>
705705
<x:String x:Key="Text.Submodule.RelativePath.Placeholder" xml:space="preserve">Relative folder to store this module.</x:String>
706706
<x:String x:Key="Text.Submodule.Remove" xml:space="preserve">Delete Submodule</x:String>
707+
<x:String x:Key="Text.Submodule.Status" xml:space="preserve">STATUS</x:String>
708+
<x:String x:Key="Text.Submodule.Status.Modified" xml:space="preserve">modified</x:String>
709+
<x:String x:Key="Text.Submodule.Status.NotInited" xml:space="preserve">not initialized</x:String>
710+
<x:String x:Key="Text.Submodule.Status.RevisionChanged" xml:space="preserve">revision changed</x:String>
711+
<x:String x:Key="Text.Submodule.Status.Unmerged" xml:space="preserve">unmerged</x:String>
707712
<x:String x:Key="Text.Sure" xml:space="preserve">OK</x:String>
708713
<x:String x:Key="Text.TagCM.Copy" xml:space="preserve">Copy Tag Name</x:String>
709714
<x:String x:Key="Text.TagCM.CopyMessage" xml:space="preserve">Copy Tag Message</x:String>

src/Resources/Locales/zh_CN.axaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,11 @@
708708
<x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">相对仓库路径 :</x:String>
709709
<x:String x:Key="Text.Submodule.RelativePath.Placeholder" xml:space="preserve">本地存放的相对路径。</x:String>
710710
<x:String x:Key="Text.Submodule.Remove" xml:space="preserve">删除子模块</x:String>
711+
<x:String x:Key="Text.Submodule.Status" xml:space="preserve">状态</x:String>
712+
<x:String x:Key="Text.Submodule.Status.Modified" xml:space="preserve">未提交修改</x:String>
713+
<x:String x:Key="Text.Submodule.Status.NotInited" xml:space="preserve">未初始化</x:String>
714+
<x:String x:Key="Text.Submodule.Status.RevisionChanged" xml:space="preserve">SHA变更</x:String>
715+
<x:String x:Key="Text.Submodule.Status.Unmerged" xml:space="preserve">未解决冲突</x:String>
711716
<x:String x:Key="Text.Sure" xml:space="preserve">确 定</x:String>
712717
<x:String x:Key="Text.TagCM.Copy" xml:space="preserve">复制标签名</x:String>
713718
<x:String x:Key="Text.TagCM.CopyMessage" xml:space="preserve">复制标签信息</x:String>

src/Resources/Locales/zh_TW.axaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,11 @@
708708
<x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">相對存放庫路徑:</x:String>
709709
<x:String x:Key="Text.Submodule.RelativePath.Placeholder" xml:space="preserve">本機存放的相對路徑。</x:String>
710710
<x:String x:Key="Text.Submodule.Remove" xml:space="preserve">刪除子模組</x:String>
711+
<x:String x:Key="Text.Submodule.Status" xml:space="preserve">狀態</x:String>
712+
<x:String x:Key="Text.Submodule.Status.Modified" xml:space="preserve">未提交變更</x:String>
713+
<x:String x:Key="Text.Submodule.Status.NotInited" xml:space="preserve">未初始化</x:String>
714+
<x:String x:Key="Text.Submodule.Status.RevisionChanged" xml:space="preserve">SHA 變更</x:String>
715+
<x:String x:Key="Text.Submodule.Status.Unmerged" xml:space="preserve">未解決的衝突</x:String>
711716
<x:String x:Key="Text.Sure" xml:space="preserve">確 定</x:String>
712717
<x:String x:Key="Text.TagCM.Copy" xml:space="preserve">複製標籤名稱</x:String>
713718
<x:String x:Key="Text.TagCM.CopyMessage" xml:space="preserve">複製標籤訊息</x:String>

src/Views/Repository.axaml

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,56 @@
348348
</ListBox.Styles>
349349
<ListBox.ItemTemplate>
350350
<DataTemplate DataType="m:Submodule">
351-
<Grid ColumnDefinitions="Auto,*,8,8">
351+
<Grid ColumnDefinitions="Auto,*,8,8" Background="Transparent">
352+
<ToolTip.Tip>
353+
<StackPanel Orientation="Vertical">
354+
<StackPanel Orientation="Horizontal">
355+
<Path Width="10" Height="10" Data="{StaticResource Icons.Submodule}"/>
356+
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Text="{Binding Path}"/>
357+
</StackPanel>
358+
359+
<Grid RowDefinitions="24,24" ColumnDefinitions="Auto,Auto" Margin="0,8,0,0">
360+
<TextBlock Grid.Row="0" Grid.Column="0" Classes="info_label" Text="{DynamicResource Text.CommitDetail.Info.SHA}" VerticalAlignment="Center"/>
361+
<TextBlock Grid.Row="0" Grid.Column="1" Margin="8,0,0,0" Text="{Binding SHA}" VerticalAlignment="Center"/>
362+
363+
<TextBlock Grid.Row="1" Grid.Column="0" Classes="info_label" Text="{DynamicResource Text.Submodule.Status}" VerticalAlignment="Center"/>
364+
<Path Grid.Row="1" Grid.Column="1"
365+
Margin="8,0,0,0"
366+
HorizontalAlignment="Left" VerticalAlignment="Center"
367+
Width="12" Height="12"
368+
Data="{StaticResource Icons.Check}"
369+
Fill="Green"
370+
IsVisible="{Binding Status, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:SubmoduleStatus.Normal}}"/>
371+
<Border Grid.Row="1" Grid.Column="1"
372+
Height="16"
373+
Margin="8,0,0,0" Padding="4,0"
374+
HorizontalAlignment="Left" VerticalAlignment="Center"
375+
Background="DarkOrange"
376+
CornerRadius="4"
377+
IsVisible="{Binding Status, Converter={x:Static ObjectConverters.NotEqual}, ConverterParameter={x:Static m:SubmoduleStatus.Normal}}">
378+
<Grid>
379+
<TextBlock VerticalAlignment="Center"
380+
Text="{DynamicResource Text.Submodule.Status.NotInited}"
381+
Foreground="White"
382+
IsVisible="{Binding Status, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:SubmoduleStatus.NotInited}}"/>
383+
<TextBlock VerticalAlignment="Center"
384+
Text="{DynamicResource Text.Submodule.Status.Modified}"
385+
Foreground="White"
386+
IsVisible="{Binding Status, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:SubmoduleStatus.Modified}}"/>
387+
<TextBlock VerticalAlignment="Center"
388+
Text="{DynamicResource Text.Submodule.Status.RevisionChanged}"
389+
Foreground="White"
390+
IsVisible="{Binding Status, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:SubmoduleStatus.RevisionChanged}}"/>
391+
<TextBlock VerticalAlignment="Center"
392+
Text="{DynamicResource Text.Submodule.Status.Unmerged}"
393+
Foreground="White"
394+
IsVisible="{Binding Status, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:SubmoduleStatus.Unmerged}}"/>
395+
</Grid>
396+
</Border>
397+
</Grid>
398+
</StackPanel>
399+
</ToolTip.Tip>
400+
352401
<Path Grid.Column="0" Width="10" Height="10" Margin="8,0" Data="{StaticResource Icons.Submodule}"/>
353402
<TextBlock Grid.Column="1" Text="{Binding Path}" ClipToBounds="True" Classes="primary" TextTrimming="CharacterEllipsis"/>
354403
<Path Grid.Column="2"
@@ -406,7 +455,7 @@
406455
</ListBox.Styles>
407456
<ListBox.ItemTemplate>
408457
<DataTemplate DataType="m:Worktree">
409-
<Grid ColumnDefinitions="Auto,*,22">
458+
<Grid ColumnDefinitions="Auto,*,22" Background="Transparent">
410459
<Path Grid.Column="0" Width="10" Height="10" Margin="8,0,0,0" Data="{StaticResource Icons.Worktree}"/>
411460
<TextBlock Grid.Column="1" Classes="primary" Margin="8,0,0,0" TextTrimming="CharacterEllipsis">
412461
<Run Text="{Binding Name}"/>

0 commit comments

Comments
 (0)