Copy the statistics table and graph to the clipboard
Copy All takes whichever tab is open, as N1MM's does: the table off the table tab, a picture of the graph off the graph tab. Copy Table as Text and Copy Graph as Image do either one from either tab. `StatisticsTable` lays the pivot out as the window prints it — the headings, the rows, the Total line — and pads it into columns for the text form, so the grid, the clipboard and Print to File all say the same thing. X11 asks for a picture when the other program pastes rather than when it is copied, so the bitmap given to the clipboard is held until the clipboard is given a different one. Disposing it at the end of the copy killed the program on the next paste; the table pasted into a second Avalonia program reads back lined up, and the picture reads back as a 916x438 bitmap. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PdAYHcdRktqKry7nk414TU
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
using Nonemm.Core;
|
||||
|
||||
namespace Nonemm.Session.Tests;
|
||||
|
||||
public class StatisticsTableTests
|
||||
{
|
||||
private static readonly DateTime Start = new(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
private static Qso Contact(double kilohertz, Mode? mode = null, int minute = 0) => new()
|
||||
{
|
||||
Id = Qso.NewId(),
|
||||
TimestampUtc = Start.AddMinutes(minute),
|
||||
Call = Callsign.Parse("DL1ABC"),
|
||||
Frequency = Frequency.FromKilohertz(kilohertz),
|
||||
Mode = mode ?? Modes.Cw,
|
||||
ContestName = "CQWW",
|
||||
};
|
||||
|
||||
private static StatisticsTable Of(IReadOnlyList<Qso> log, string row = "Band", string column = "Mode") =>
|
||||
StatisticsTable.Of(StatisticsPivot.Of(
|
||||
log,
|
||||
StatisticsFields.Find(StatisticsFields.Rows, row),
|
||||
StatisticsFields.Find(StatisticsFields.Columns, column),
|
||||
Start));
|
||||
|
||||
[Fact]
|
||||
public void HeadsTheCountsWithTheColumnValuesAndEndsWithTotAndAccum()
|
||||
{
|
||||
StatisticsTable table = Of([Contact(14_030), Contact(7_030, Modes.Usb)]);
|
||||
|
||||
Assert.Equal(["Band", "CW", "USB", "Tot", "Accum"], table.Headings);
|
||||
Assert.Equal(1, table.LabelColumns);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PutsTheTotalLineLast()
|
||||
{
|
||||
StatisticsTable table = Of([Contact(14_030), Contact(14_040), Contact(7_030)]);
|
||||
|
||||
Assert.Equal(["40M", "1", "1", "1"], table.Rows[0]);
|
||||
Assert.Equal(["20M", "2", "2", "3"], table.Rows[1]);
|
||||
Assert.Equal(["Total", "3", "3", "3"], table.Rows[^1]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LinesTheColumnsUpUnderTheirHeadings()
|
||||
{
|
||||
string text = Of([Contact(14_030), Contact(3_530, Modes.Usb), Contact(3_540, Modes.Usb)]).ToText();
|
||||
|
||||
Assert.Equal(
|
||||
"""
|
||||
Band CW USB Tot Accum
|
||||
80M 2 2 2
|
||||
20M 1 1 3
|
||||
Total 1 2 3 3
|
||||
""",
|
||||
text.TrimEnd('\n'));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void KeepsTheTwoLabelColumnsOfAFieldThatHasThem()
|
||||
{
|
||||
StatisticsTable table = Of([Contact(14_030, minute: 5), Contact(14_040, minute: 70)], row: "Hour");
|
||||
|
||||
Assert.Equal(2, table.LabelColumns);
|
||||
Assert.Equal(["Day", "Hr", "CW", "Tot", "Accum"], table.Headings);
|
||||
Assert.Equal(["2026-01-01", "00", "1", "1", "1"], table.Rows[0]);
|
||||
Assert.Equal(["Total", "", "2", "2", "2"], table.Rows[^1]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LeavesNoSpacesHangingOffTheEndOfALine()
|
||||
{
|
||||
string text = Of([Contact(14_030)]).ToText();
|
||||
|
||||
Assert.All(text.Split('\n'), line => Assert.Equal(line.TrimEnd(), line));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user