From 3eaae12f6828d1a22491a26686cd6b7c46e96d8c Mon Sep 17 00:00:00 2001 From: "Serg V. Zhdanovskih (Norseman)" Date: Wed, 31 Jan 2024 01:22:48 +0300 Subject: [PATCH 01/11] Experimental support for locations hierarchy --- projects/GKCore/GDModel/GDMDateValue.cs | 5 + projects/GKCore/GDModel/GDMLocationRecord.cs | 90 ++++++++++- .../GKTests/GDModel/GDMLocationRecordTests.cs | 145 +++++++++++++++++- 3 files changed, 230 insertions(+), 10 deletions(-) diff --git a/projects/GKCore/GDModel/GDMDateValue.cs b/projects/GKCore/GDModel/GDMDateValue.cs index fb76ccad7..d3c940b40 100644 --- a/projects/GKCore/GDModel/GDMDateValue.cs +++ b/projects/GKCore/GDModel/GDMDateValue.cs @@ -164,5 +164,10 @@ public override string GetDisplayStringExt(DateFormat format, bool sign, bool sh string result = (fValue == null) ? string.Empty : fValue.GetDisplayStringExt(format, sign, showCalendar, shorten); return result; } + + public override string ToString() + { + return GetDisplayStringExt(DateFormat.dfDD_MM_YYYY, true, true, false); + } } } diff --git a/projects/GKCore/GDModel/GDMLocationRecord.cs b/projects/GKCore/GDModel/GDMLocationRecord.cs index 670343b19..d12a0c7db 100644 --- a/projects/GKCore/GDModel/GDMLocationRecord.cs +++ b/projects/GKCore/GDModel/GDMLocationRecord.cs @@ -19,6 +19,7 @@ */ using System; +using System.Collections.Generic; using GDModel.Providers.GEDCOM; using GKCore.Calendar; using GKCore.Types; @@ -29,6 +30,7 @@ public sealed class GDMLocationRecord : GDMRecord { private readonly GDMMap fMap; private GDMList fNames; + private GDMList fTopLevels; public string LocationName @@ -56,6 +58,11 @@ public GDMList Names get { return fNames; } } + public GDMList TopLevels + { + get { return fTopLevels; } + } + public GDMLocationRecord(GDMTree tree) : base(tree) { @@ -63,6 +70,7 @@ public GDMLocationRecord(GDMTree tree) : base(tree) fMap = new GDMMap(); fNames = new GDMList(); + fTopLevels = new GDMList(); } internal override void TrimExcess() @@ -71,6 +79,7 @@ internal override void TrimExcess() fMap.TrimExcess(); fNames.TrimExcess(); + fTopLevels.TrimExcess(); } public override void Assign(GDMTag source) @@ -83,6 +92,7 @@ public override void Assign(GDMTag source) fMap.Assign(otherLoc.fMap); AssignList(otherLoc.fNames, Names); + AssignList(otherLoc.fTopLevels, TopLevels); } public override void Clear() @@ -91,11 +101,12 @@ public override void Clear() fMap.Clear(); fNames.Clear(); + fTopLevels.Clear(); } public override bool IsEmpty() { - return base.IsEmpty() && fMap.IsEmpty() && (fNames.Count == 0); + return base.IsEmpty() && fMap.IsEmpty() && (fNames.Count == 0) && (fTopLevels.Count == 0); } // TODO: connect to use @@ -113,6 +124,67 @@ public override void ReplaceXRefs(GDMXRefReplacer map) base.ReplaceXRefs(map); fMap.ReplaceXRefs(map); fNames.ReplaceXRefs(map); + fTopLevels.ReplaceXRefs(map); + } + + public IList GetFullNames(GDMTree tree) + { + var result = new List(); + + if (fTopLevels.Count > 0) { + var buffer = new List(); + + for (int j = 0; j < fTopLevels.Count; j++) { + var topLevel = fTopLevels[j]; + var topLoc = tree.GetPtrValue(topLevel); + if (topLoc == null) continue; + + var topNames = topLoc.GetFullNames(tree); + for (int i = 0; i < topNames.Count; i++) { + var topName = topNames[i]; + if (topName.Date.IsEmpty()) continue; + + var interDate = GDMCustomDate.GetIntersection(topLevel.Date.Value, topName.Date.Value); + if (!interDate.IsEmpty()) { + var newLocName = new GDMLocationName(); + newLocName.StringValue = topName.StringValue; + newLocName.Date.ParseString(interDate.StringValue); + buffer.Add(newLocName); + } + } + //buffer.AddRange(topNames); + } + + for (int j = 0; j < buffer.Count; j++) { + var topLocName = buffer[j]; + var topName = topLocName.StringValue; + var topDate = topLocName.Date.Value; + + for (int i = 0; i < fNames.Count; i++) { + var locName = fNames[i]; + if (locName.Date.IsEmpty()) continue; + + var interDate = GDMCustomDate.GetIntersection(topDate, locName.Date.Value); + if (!interDate.IsEmpty()) { + string newName = locName.StringValue + ", " + topName; + + var newLocName = new GDMLocationName(); + newLocName.StringValue = newName; + newLocName.Date.ParseString(interDate.StringValue); + result.Add(newLocName); + } + } + } + } else { + for (int i = 0; i < fNames.Count; i++) { + var locName = fNames[i]; + if (locName.Date.IsEmpty()) continue; + + result.Add(locName); + } + } + + return result; } public string GetNameByDate(GDMCustomDate date) @@ -150,10 +222,22 @@ public bool ValidateNames() public void SortNames() { - fNames.Sort(ChildrenEventsCompare); + fNames.Sort(NamesCompare); + } + + private static int NamesCompare(GDMLocationName cp1, GDMLocationName cp2) + { + UDN udn1 = cp1.Date.GetUDN(); + UDN udn2 = cp2.Date.GetUDN(); + return -udn1.CompareTo(udn2); + } + + public void SortTopLevels() + { + fTopLevels.Sort(TopLevelsCompare); } - private static int ChildrenEventsCompare(GDMLocationName cp1, GDMLocationName cp2) + private static int TopLevelsCompare(GDMLocationLink cp1, GDMLocationLink cp2) { UDN udn1 = cp1.Date.GetUDN(); UDN udn2 = cp2.Date.GetUDN(); diff --git a/projects/GKTests/GDModel/GDMLocationRecordTests.cs b/projects/GKTests/GDModel/GDMLocationRecordTests.cs index fbec046d1..5a2e969df 100644 --- a/projects/GKTests/GDModel/GDMLocationRecordTests.cs +++ b/projects/GKTests/GDModel/GDMLocationRecordTests.cs @@ -19,6 +19,8 @@ */ using System; +using System.Collections.Generic; +using System.Linq; using GDModel.Providers.GEDCOM; using GKCore; using GKCore.Types; @@ -34,6 +36,8 @@ public class GDMLocationRecordTests public GDMLocationRecordTests() { + TestUtils.InitUITest(); + fContext = TestUtils.CreateContext(); } @@ -109,13 +113,6 @@ public void Test_Names() locName.StringValue = "Казанская губ., Вятская пров., Слободской уезд, Верховская вол., д. Мокрая Слободка"; locName.Date.ParseString("FROM 1727 TO 1764"); - // Сибирская губерния, 18 DEC 1708 - 18 JAN 1782 - // Казанская губерния, 1796 - 1920 - // Вятская провинция, to Sib 29 MAY 1719 — 28 APR 1727, to Kazan 29 APR 1727 — 10 SEP 1780 - - // Вятское наместничество, 11 SEP 1780 - 30 DEC 1796 - // Вятская губерния, 31 DEC 1796 - 13 DEC 1929 - string buf = GEDCOMProvider.GetTagStreamText(locRec, 0); Assert.AreEqual("0 @L4@ _LOC\r\n" + "1 NAME РФ, Кировская обл., Верхнекамский р-н, д. Прислонская\r\n" + @@ -185,6 +182,122 @@ public void Test_NamesByDate() } } + [Test] + public void Test_Hierarchy() + { + var tree = new GDMTree(); + + var locRus = tree.CreateLocation(); + locRus.AddLocName("Россия", "FROM 862 TO 9999"); + + IList fullNames = locRus.GetFullNames(tree); + string result = string.Join("\n", fullNames.Select(x => string.Format("'{0}': '{1}'", x.Date.ToString(), x.StringValue))); + Assert.AreEqual("'__.__._862 [G] - __.__.9999 [G]': 'Россия'", + result); + + var locSibGub = tree.CreateLocation(); + locSibGub.AddLocName("Сибирская губерния", "FROM 18 DEC 1708 TO 18 JAN 1782"); + locSibGub.AddLocLink(locRus, "FROM 18 DEC 1708 TO 18 JAN 1782"); + + fullNames = locSibGub.GetFullNames(tree); + result = string.Join("\n", fullNames.Select(x => string.Format("'{0}': '{1}'", x.Date.ToString(), x.StringValue))); + Assert.AreEqual("'18.12.1708 [G] - 18.01.1782 [G]': 'Сибирская губерния, Россия'", + result); + + var locKazGub = tree.CreateLocation(); + locKazGub.AddLocName("Казанская губерния", "FROM 18 DEC 1708 TO 27 SEP 1781"); + locKazGub.AddLocName("Казанское наместничество", "FROM 28 SEP 1781 TO 11 DEC 1796"); + locKazGub.AddLocName("Казанская губерния", "FROM 12 DEC 1796 TO 27 MAY 1920"); + locKazGub.AddLocLink(locRus, "FROM 18 DEC 1708 TO 27 MAY 1920"); + + fullNames = locKazGub.GetFullNames(tree); + result = string.Join("\n", fullNames.Select(x => string.Format("'{0}': '{1}'", x.Date.ToString(), x.StringValue))); + Assert.AreEqual("'18.12.1708 [G] - 27.09.1781 [G]': 'Казанская губерния, Россия'\n"+ + "'28.09.1781 [G] - 11.12.1796 [G]': 'Казанское наместничество, Россия'\n" + + "'12.12.1796 [G] - 27.05.1920 [G]': 'Казанская губерния, Россия'", + result); + + var locVyatGub = tree.CreateLocation(); + locVyatGub.AddLocName("Вятская провинция", "FROM 29 MAY 1719 TO 10 SEP 1780"); + locVyatGub.AddLocName("Вятское наместничество", "FROM 11 SEP 1780 TO 30 DEC 1796"); + locVyatGub.AddLocName("Вятская губерния", "FROM 31 DEC 1796 TO 13 DEC 1929"); + locVyatGub.AddLocLink(locSibGub, "FROM 29 MAY 1719 TO 28 APR 1727"); + locVyatGub.AddLocLink(locKazGub, "FROM 29 APR 1727 TO 10 SEP 1780"); + locVyatGub.AddLocLink(locRus, "FROM 11 SEP 1780 TO 13 DEC 1929"); + + fullNames = locVyatGub.GetFullNames(tree); + result = string.Join("\n", fullNames.Select(x => string.Format("'{0}': '{1}'", x.Date.ToString(), x.StringValue))); + Assert.AreEqual("'29.05.1719 [G] - 28.04.1727 [G]': 'Вятская провинция, Сибирская губерния, Россия'\n" + + "'29.04.1727 [G] - 10.09.1780 [G]': 'Вятская провинция, Казанская губерния, Россия'\n"+ + "'11.09.1780 [G] - 30.12.1796 [G]': 'Вятское наместничество, Россия'\n"+ + "'31.12.1796 [G] - 13.12.1929 [G]': 'Вятская губерния, Россия'", + result); + + var locSlobUezd = tree.CreateLocation(); + locSlobUezd.AddLocName("Слободской уезд", "FROM 1646 TO 1719"); + locSlobUezd.AddLocName("Слободской дистр.", "FROM 1719 TO 1726"); + locSlobUezd.AddLocName("Слободской уезд", "FROM 1727 TO 1929"); + locSlobUezd.AddLocLink(locRus, "TO 1718"); + locSlobUezd.AddLocLink(locVyatGub, "FROM 1719 TO 1726"); + locSlobUezd.AddLocLink(locKazGub, "FROM 1727 TO 10 SEP 1780"); + locSlobUezd.AddLocLink(locVyatGub, "FROM 11 SEP 1780 TO 10 JUN 1929"); + + fullNames = locSlobUezd.GetFullNames(tree); + result = string.Join("\n", fullNames.Select(x => string.Format("'{0}': '{1}'", x.Date.ToString(), x.StringValue))); + Assert.AreEqual("'__.__.1646 [G] - __.__.1718 [G]': 'Слободской уезд, Россия'\n" + + "'29.05.1719 [G] - __.__.1726 [G]': 'Слободской дистр., Вятская провинция, Сибирская губерния, Россия'\n" + + "'__.__.1727 [G] - 10.09.1780 [G]': 'Слободской уезд, Казанская губерния, Россия'\n" + + "'11.09.1780 [G] - 30.12.1796 [G]': 'Слободской уезд, Вятское наместничество, Россия'\n" + + "'31.12.1796 [G] - __.__.1929 [G]': 'Слободской уезд, Вятская губерния, Россия'", + result); + + var locVerhVol = tree.CreateLocation(); + locVerhVol.AddLocName("Верховская вол.", "FROM 1720 TO 1764"); + locVerhVol.AddLocLink(locSlobUezd, "FROM 1720 TO 1764"); + + var locLoinVol = tree.CreateLocation(); + locLoinVol.AddLocName("Лоинская вол.", "FROM 1802 TO 1884"); + locLoinVol.AddLocLink(locSlobUezd, "FROM 1802 TO 1884"); + + var locKirsVol = tree.CreateLocation(); + locKirsVol.AddLocName("Кирсинская вол.", "FROM 1884 TO 1926"); + locKirsVol.AddLocLink(locSlobUezd, "FROM 1884 TO 1926"); + + var locPrislon = tree.CreateLocation(); + locPrislon.AddLocName("поч. Старое раменье", "FROM 1678 TO 1719"); + locPrislon.AddLocName("д. Прислонская", "FROM 1720 TO 1726"); + locPrislon.AddLocName("д. Мокрая Слободка", "FROM 1727 TO 1926"); + locPrislon.AddLocLink(locSlobUezd, "FROM 1678 TO 1719"); + locPrislon.AddLocLink(locVerhVol, "FROM 1720 TO 1801"); + locPrislon.AddLocLink(locLoinVol, "FROM 1802 TO 1883"); + locPrislon.AddLocLink(locKirsVol, "FROM 1884 TO 1926"); + + fullNames = locPrislon.GetFullNames(tree); + result = string.Join("\n", fullNames.Select(x => string.Format("'{0}': '{1}'", x.Date.ToString(), x.StringValue))); + Assert.AreEqual("'__.__.1678 [G] - __.__.1718 [G]': 'поч. Старое раменье, Слободской уезд, Россия'\n" + + "'__.__.1720 [G] - __.__.1726 [G]': 'д. Прислонская, Верховская вол., Слободской дистр., Вятская провинция, Сибирская губерния, Россия'\n" + + "'__.__.1727 [G] - __.__.1764 [G]': 'д. Мокрая Слободка, Верховская вол., Слободской уезд, Казанская губерния, Россия'\n" + + "'__.__.1802 [G] - __.__.1883 [G]': 'д. Мокрая Слободка, Лоинская вол., Слободской уезд, Вятская губерния, Россия'\n" + + "'__.__.1884 [G] - __.__.1926 [G]': 'д. Мокрая Слободка, Кирсинская вол., Слободской уезд, Вятская губерния, Россия'", + result); + + /*var dateVal = new GDMDate(); + dateVal.ParseString("10 JAN 1701"); + Assert.AreEqual("Российское царство, Вятка, Слободской уезд, Екатерининского мон. вотч., поч. Старое раменье", locPrislon.GetNameByDate(dateVal)); + + // + dateVal.ParseString("1711"); + Assert.AreEqual("Сибирская губерния, Вятка, Слободской уезд, Екатерининского мон. вотч., поч. Старое раменье", locPrislon.GetNameByDate(dateVal)); + + // + dateVal.ParseString("1726"); + Assert.AreEqual("Сибирская губ., Вятская пров., Слободской дистр., Верховская вол., д. Прислонская", locPrislon.GetNameByDate(dateVal)); + + // + dateVal.ParseString("1747"); + Assert.AreEqual("Казанская губ., Вятская пров., Слободской уезд, Верховская вол., д. Мокрая Слободка", locPrislon.GetNameByDate(dateVal));*/ + } + [Test] public void Test_DateIntersections() { @@ -206,4 +319,22 @@ private static GDMDatePeriod GetRange(string strDateRange) return result; } } + + public static class LocExts + { + public static void AddLocName(this GDMLocationRecord locRec, string name, string date) + { + var locName = locRec.Names.Add(new GDMLocationName()); + locName.StringValue = name; + locName.Date.ParseString(date); + } + + public static void AddLocLink(this GDMLocationRecord locRec, GDMLocationRecord topLevel, string date) + { + var locLink = locRec.TopLevels.Add(new GDMLocationLink()); + locLink.XRef = topLevel.XRef; + locLink.Date.ParseString(date); + } + + } } From 2d12cf164d2fbbfaf84d1d577635fa1a3c005968 Mon Sep 17 00:00:00 2001 From: "Serg V. Zhdanovskih (Norseman)" Date: Wed, 31 Jan 2024 18:43:21 +0300 Subject: [PATCH 02/11] Experimental locations hierarchy --- .../GKTests/GDModel/GDMLocationRecordTests.cs | 135 +++++++++++++----- 1 file changed, 96 insertions(+), 39 deletions(-) diff --git a/projects/GKTests/GDModel/GDMLocationRecordTests.cs b/projects/GKTests/GDModel/GDMLocationRecordTests.cs index 5a2e969df..6459d9914 100644 --- a/projects/GKTests/GDModel/GDMLocationRecordTests.cs +++ b/projects/GKTests/GDModel/GDMLocationRecordTests.cs @@ -187,12 +187,26 @@ public void Test_Hierarchy() { var tree = new GDMTree(); + // J2G Rus transfer: 26 JAN 1918 (Julian), 1 FEB -> 14 FEB 1918 + var locRus = tree.CreateLocation(); - locRus.AddLocName("Россия", "FROM 862 TO 9999"); + locRus.AddLocName("Россия", "FROM 862 TO 1546"); + locRus.AddLocName("Российское царство", "FROM 1547 TO 21 OCT 1721");//++ + locRus.AddLocName("Российская империя", "FROM 22 OCT 1721 TO 31 AUG 1917");//++ + locRus.AddLocName("Российская республика", "FROM 01 SEP 1917 TO 18 JUL 1918");//++ + locRus.AddLocName("РСФСР", "FROM 19 JUL 1918 TO 29 DEC 1922");//++ + locRus.AddLocName("СССР", "FROM 30 DEC 1922 TO 26 DEC 1991");//++ + locRus.AddLocName("РФ", "FROM 27 DEC 1991 TO 9999");//++ IList fullNames = locRus.GetFullNames(tree); string result = string.Join("\n", fullNames.Select(x => string.Format("'{0}': '{1}'", x.Date.ToString(), x.StringValue))); - Assert.AreEqual("'__.__._862 [G] - __.__.9999 [G]': 'Россия'", + Assert.AreEqual("'__.__._862 [G] - __.__.1546 [G]': 'Россия'\n" + + "'__.__.1547 [G] - 21.10.1721 [G]': 'Российское царство'\n" + + "'22.10.1721 [G] - 31.08.1917 [G]': 'Российская империя'\n" + + "'01.09.1917 [G] - 18.07.1918 [G]': 'Российская республика'\n" + + "'19.07.1918 [G] - 29.12.1922 [G]': 'РСФСР'\n" + + "'30.12.1922 [G] - 26.12.1991 [G]': 'СССР'\n" + + "'27.12.1991 [G] - __.__.9999 [G]': 'РФ'", result); var locSibGub = tree.CreateLocation(); @@ -201,7 +215,8 @@ public void Test_Hierarchy() fullNames = locSibGub.GetFullNames(tree); result = string.Join("\n", fullNames.Select(x => string.Format("'{0}': '{1}'", x.Date.ToString(), x.StringValue))); - Assert.AreEqual("'18.12.1708 [G] - 18.01.1782 [G]': 'Сибирская губерния, Россия'", + Assert.AreEqual("'18.12.1708 [G] - 21.10.1721 [G]': 'Сибирская губерния, Российское царство'\n" + + "'22.10.1721 [G] - 18.01.1782 [G]': 'Сибирская губерния, Российская империя'", result); var locKazGub = tree.CreateLocation(); @@ -212,43 +227,86 @@ public void Test_Hierarchy() fullNames = locKazGub.GetFullNames(tree); result = string.Join("\n", fullNames.Select(x => string.Format("'{0}': '{1}'", x.Date.ToString(), x.StringValue))); - Assert.AreEqual("'18.12.1708 [G] - 27.09.1781 [G]': 'Казанская губерния, Россия'\n"+ - "'28.09.1781 [G] - 11.12.1796 [G]': 'Казанское наместничество, Россия'\n" + - "'12.12.1796 [G] - 27.05.1920 [G]': 'Казанская губерния, Россия'", + Assert.AreEqual("'18.12.1708 [G] - 21.10.1721 [G]': 'Казанская губерния, Российское царство'\n" + + "'22.10.1721 [G] - 27.09.1781 [G]': 'Казанская губерния, Российская империя'\n" + + "'28.09.1781 [G] - 11.12.1796 [G]': 'Казанское наместничество, Российская империя'\n" + + "'12.12.1796 [G] - 31.08.1917 [G]': 'Казанская губерния, Российская империя'\n" + + "'01.09.1917 [G] - 18.07.1918 [G]': 'Казанская губерния, Российская республика'\n" + + "'19.07.1918 [G] - 27.05.1920 [G]': 'Казанская губерния, РСФСР'", result); + var locNizhNovgGub = tree.CreateLocation(); + locNizhNovgGub.AddLocName("Нижегородская губерния", "FROM JAN 1714 TO 1717"); + locNizhNovgGub.AddLocName("Нижегородская губерния", "FROM 29 MAY 1719 TO 04 SEP 1779"); + locNizhNovgGub.AddLocName("Нижегородское наместничество", "FROM 05 SEP 1779 TO 11 DEC 1796"); + locNizhNovgGub.AddLocName("Нижегородская губерния", "FROM 12 DEC 1796 TO 13 JAN 1929"); + locNizhNovgGub.AddLocName("Нижегородская область", "FROM 14 JAN 1929 TO 14 JUL 1929"); + locNizhNovgGub.AddLocName("Нижегородский край", "FROM 15 JUL 1929 TO 06 OCT 1932"); + locNizhNovgGub.AddLocName("Горьковский край", "FROM 07 OCT 1932 TO 04 DEC 1936"); + locNizhNovgGub.AddLocName("Горьковская область", "FROM 05 DEC 1936 TO 21 OCT 1990"); + locNizhNovgGub.AddLocName("Нижегородская область", "FROM 22 OCT 1990 TO 9999"); + locNizhNovgGub.AddLocLink(locRus, "FROM JAN 1714 TO 9999"); + var locVyatGub = tree.CreateLocation(); locVyatGub.AddLocName("Вятская провинция", "FROM 29 MAY 1719 TO 10 SEP 1780"); locVyatGub.AddLocName("Вятское наместничество", "FROM 11 SEP 1780 TO 30 DEC 1796"); - locVyatGub.AddLocName("Вятская губерния", "FROM 31 DEC 1796 TO 13 DEC 1929"); + locVyatGub.AddLocName("Вятская губерния", "FROM 31 DEC 1796 TO 14 JUL 1929"); + locVyatGub.AddLocName("Вятский округ", "FROM 15 JUL 1929 TO 29 JUL 1930"); + locVyatGub.AddLocName("Кировский край", "FROM 07 DEC 1934 TO 04 DEC 1936"); + locVyatGub.AddLocName("Кировская область", "FROM 05 DEC 1936 TO 9999"); locVyatGub.AddLocLink(locSibGub, "FROM 29 MAY 1719 TO 28 APR 1727"); locVyatGub.AddLocLink(locKazGub, "FROM 29 APR 1727 TO 10 SEP 1780"); - locVyatGub.AddLocLink(locRus, "FROM 11 SEP 1780 TO 13 DEC 1929"); + locVyatGub.AddLocLink(locRus, "FROM 11 SEP 1780 TO 14 JUL 1929"); + locVyatGub.AddLocLink(locNizhNovgGub, "FROM 15 JUL 1929 TO 29 JUL 1930"); + locVyatGub.AddLocLink(locRus, "FROM 30 JUL 1930 TO 9999"); fullNames = locVyatGub.GetFullNames(tree); result = string.Join("\n", fullNames.Select(x => string.Format("'{0}': '{1}'", x.Date.ToString(), x.StringValue))); - Assert.AreEqual("'29.05.1719 [G] - 28.04.1727 [G]': 'Вятская провинция, Сибирская губерния, Россия'\n" + - "'29.04.1727 [G] - 10.09.1780 [G]': 'Вятская провинция, Казанская губерния, Россия'\n"+ - "'11.09.1780 [G] - 30.12.1796 [G]': 'Вятское наместничество, Россия'\n"+ - "'31.12.1796 [G] - 13.12.1929 [G]': 'Вятская губерния, Россия'", + Assert.AreEqual("'29.05.1719 [G] - 21.10.1721 [G]': 'Вятская провинция, Сибирская губерния, Российское царство'\n" + + "'22.10.1721 [G] - 28.04.1727 [G]': 'Вятская провинция, Сибирская губерния, Российская империя'\n" + + "'29.04.1727 [G] - 10.09.1780 [G]': 'Вятская провинция, Казанская губерния, Российская империя'\n" + + "'11.09.1780 [G] - 30.12.1796 [G]': 'Вятское наместничество, Российская империя'\n" + + "'31.12.1796 [G] - 31.08.1917 [G]': 'Вятская губерния, Российская империя'\n" + + "'01.09.1917 [G] - 18.07.1918 [G]': 'Вятская губерния, Российская республика'\n" + + "'19.07.1918 [G] - 29.12.1922 [G]': 'Вятская губерния, РСФСР'\n" + + "'30.12.1922 [G] - 14.07.1929 [G]': 'Вятская губерния, СССР'\n" + + "'15.07.1929 [G] - 29.07.1930 [G]': 'Вятский округ, Нижегородский край, СССР'\n" + + "'07.12.1934 [G] - 04.12.1936 [G]': 'Кировский край, СССР'\n" + + "'05.12.1936 [G] - 26.12.1991 [G]': 'Кировская область, СССР'\n" + + "'27.12.1991 [G] - __.__.9999 [G]': 'Кировская область, РФ'", result); var locSlobUezd = tree.CreateLocation(); locSlobUezd.AddLocName("Слободской уезд", "FROM 1646 TO 1719"); locSlobUezd.AddLocName("Слободской дистр.", "FROM 1719 TO 1726"); - locSlobUezd.AddLocName("Слободской уезд", "FROM 1727 TO 1929"); + locSlobUezd.AddLocName("Слободской уезд", "FROM 1727 TO 09 JUN 1929"); + locSlobUezd.AddLocName("Слободской район", "FROM 10 JUN 1929 TO 9999"); locSlobUezd.AddLocLink(locRus, "TO 1718"); locSlobUezd.AddLocLink(locVyatGub, "FROM 1719 TO 1726"); locSlobUezd.AddLocLink(locKazGub, "FROM 1727 TO 10 SEP 1780"); locSlobUezd.AddLocLink(locVyatGub, "FROM 11 SEP 1780 TO 10 JUN 1929"); + var locOmutUezd = tree.CreateLocation(); + locOmutUezd.AddLocName("Омутнинский уезд", "FROM 05 JAN 1921 TO 09 JUN 1929"); + locOmutUezd.AddLocName("Омутнинский район", "FROM 10 JUN 1929 TO 9999"); + locOmutUezd.AddLocLink(locVyatGub, "FROM 05 JAN 1921 TO 9999"); + + var locVerhkamRn = tree.CreateLocation(); + locVerhkamRn.AddLocName("Верхнекамский район", "FROM 12 JAN 1965 TO 9999"); + locVerhkamRn.AddLocLink(locVyatGub, "FROM 12 JAN 1965 TO 9999"); + fullNames = locSlobUezd.GetFullNames(tree); result = string.Join("\n", fullNames.Select(x => string.Format("'{0}': '{1}'", x.Date.ToString(), x.StringValue))); - Assert.AreEqual("'__.__.1646 [G] - __.__.1718 [G]': 'Слободской уезд, Россия'\n" + - "'29.05.1719 [G] - __.__.1726 [G]': 'Слободской дистр., Вятская провинция, Сибирская губерния, Россия'\n" + - "'__.__.1727 [G] - 10.09.1780 [G]': 'Слободской уезд, Казанская губерния, Россия'\n" + - "'11.09.1780 [G] - 30.12.1796 [G]': 'Слободской уезд, Вятское наместничество, Россия'\n" + - "'31.12.1796 [G] - __.__.1929 [G]': 'Слободской уезд, Вятская губерния, Россия'", + Assert.AreEqual("'__.__.1646 [G] - __.__.1718 [G]': 'Слободской уезд, Российское царство'\n" + + "'29.05.1719 [G] - 21.10.1721 [G]': 'Слободской дистр., Вятская провинция, Сибирская губерния, Российское царство'\n" + + "'22.10.1721 [G] - __.__.1726 [G]': 'Слободской дистр., Вятская провинция, Сибирская губерния, Российская империя'\n" + + "'__.__.1727 [G] - 10.09.1780 [G]': 'Слободской уезд, Казанская губерния, Российская империя'\n" + + "'11.09.1780 [G] - 30.12.1796 [G]': 'Слободской уезд, Вятское наместничество, Российская империя'\n" + + "'31.12.1796 [G] - 31.08.1917 [G]': 'Слободской уезд, Вятская губерния, Российская империя'\n" + + "'01.09.1917 [G] - 18.07.1918 [G]': 'Слободской уезд, Вятская губерния, Российская республика'\n" + + "'19.07.1918 [G] - 29.12.1922 [G]': 'Слободской уезд, Вятская губерния, РСФСР'\n" + + "'30.12.1922 [G] - 09.06.1929 [G]': 'Слободской уезд, Вятская губерния, СССР'\n" + + "'10.06.1929 [G] - 10.06.1929 [G]': 'Слободской район, Вятская губерния, СССР'", result); var locVerhVol = tree.CreateLocation(); @@ -262,40 +320,39 @@ public void Test_Hierarchy() var locKirsVol = tree.CreateLocation(); locKirsVol.AddLocName("Кирсинская вол.", "FROM 1884 TO 1926"); locKirsVol.AddLocLink(locSlobUezd, "FROM 1884 TO 1926"); + locKirsVol.AddLocLink(locOmutUezd, "FROM 1926 TO 1926"); var locPrislon = tree.CreateLocation(); locPrislon.AddLocName("поч. Старое раменье", "FROM 1678 TO 1719"); locPrislon.AddLocName("д. Прислонская", "FROM 1720 TO 1726"); locPrislon.AddLocName("д. Мокрая Слободка", "FROM 1727 TO 1926"); + locPrislon.AddLocName("д. Колегово", "FROM 1927 TO 1978"); locPrislon.AddLocLink(locSlobUezd, "FROM 1678 TO 1719"); locPrislon.AddLocLink(locVerhVol, "FROM 1720 TO 1801"); locPrislon.AddLocLink(locLoinVol, "FROM 1802 TO 1883"); locPrislon.AddLocLink(locKirsVol, "FROM 1884 TO 1926"); + locPrislon.AddLocLink(locOmutUezd, "FROM 1927 TO 1964"); + locPrislon.AddLocLink(locVerhkamRn, "FROM 1965 TO 9999"); fullNames = locPrislon.GetFullNames(tree); result = string.Join("\n", fullNames.Select(x => string.Format("'{0}': '{1}'", x.Date.ToString(), x.StringValue))); - Assert.AreEqual("'__.__.1678 [G] - __.__.1718 [G]': 'поч. Старое раменье, Слободской уезд, Россия'\n" + - "'__.__.1720 [G] - __.__.1726 [G]': 'д. Прислонская, Верховская вол., Слободской дистр., Вятская провинция, Сибирская губерния, Россия'\n" + - "'__.__.1727 [G] - __.__.1764 [G]': 'д. Мокрая Слободка, Верховская вол., Слободской уезд, Казанская губерния, Россия'\n" + - "'__.__.1802 [G] - __.__.1883 [G]': 'д. Мокрая Слободка, Лоинская вол., Слободской уезд, Вятская губерния, Россия'\n" + - "'__.__.1884 [G] - __.__.1926 [G]': 'д. Мокрая Слободка, Кирсинская вол., Слободской уезд, Вятская губерния, Россия'", + Assert.AreEqual("'__.__.1678 [G] - __.__.1718 [G]': 'поч. Старое раменье, Слободской уезд, Российское царство'\n" + + "'__.__.1720 [G] - 21.10.1721 [G]': 'д. Прислонская, Верховская вол., Слободской дистр., Вятская провинция, Сибирская губерния, Российское царство'\n" + + "'22.10.1721 [G] - __.__.1726 [G]': 'д. Прислонская, Верховская вол., Слободской дистр., Вятская провинция, Сибирская губерния, Российская империя'\n" + + "'__.__.1727 [G] - __.__.1764 [G]': 'д. Мокрая Слободка, Верховская вол., Слободской уезд, Казанская губерния, Российская империя'\n" + + "'__.__.1802 [G] - __.__.1883 [G]': 'д. Мокрая Слободка, Лоинская вол., Слободской уезд, Вятская губерния, Российская империя'\n" + + "'__.__.1884 [G] - 31.08.1917 [G]': 'д. Мокрая Слободка, Кирсинская вол., Слободской уезд, Вятская губерния, Российская империя'\n" + + "'01.09.1917 [G] - 18.07.1918 [G]': 'д. Мокрая Слободка, Кирсинская вол., Слободской уезд, Вятская губерния, Российская республика'\n" + + "'19.07.1918 [G] - 29.12.1922 [G]': 'д. Мокрая Слободка, Кирсинская вол., Слободской уезд, Вятская губерния, РСФСР'\n" + + "'30.12.1922 [G] - __.__.1926 [G]': 'д. Мокрая Слободка, Кирсинская вол., Слободской уезд, Вятская губерния, СССР'\n" + + "'__.__.1926 [G] - __.__.1926 [G]': 'д. Мокрая Слободка, Кирсинская вол., Омутнинский уезд, Вятская губерния, СССР'\n" + + "'__.__.1927 [G] - 09.06.1929 [G]': 'д. Колегово, Омутнинский уезд, Вятская губерния, СССР'\n" + + "'10.06.1929 [G] - 14.07.1929 [G]': 'д. Колегово, Омутнинский район, Вятская губерния, СССР'\n" + + "'15.07.1929 [G] - 29.07.1930 [G]': 'д. Колегово, Омутнинский район, Вятский округ, Нижегородский край, СССР'\n" + + "'07.12.1934 [G] - 04.12.1936 [G]': 'д. Колегово, Омутнинский район, Кировский край, СССР'\n" + + "'05.12.1936 [G] - __.__.1964 [G]': 'д. Колегово, Омутнинский район, Кировская область, СССР'\n" + + "'12.01.1965 [G] - __.__.1978 [G]': 'д. Колегово, Верхнекамский район, Кировская область, СССР'", result); - - /*var dateVal = new GDMDate(); - dateVal.ParseString("10 JAN 1701"); - Assert.AreEqual("Российское царство, Вятка, Слободской уезд, Екатерининского мон. вотч., поч. Старое раменье", locPrislon.GetNameByDate(dateVal)); - - // - dateVal.ParseString("1711"); - Assert.AreEqual("Сибирская губерния, Вятка, Слободской уезд, Екатерининского мон. вотч., поч. Старое раменье", locPrislon.GetNameByDate(dateVal)); - - // - dateVal.ParseString("1726"); - Assert.AreEqual("Сибирская губ., Вятская пров., Слободской дистр., Верховская вол., д. Прислонская", locPrislon.GetNameByDate(dateVal)); - - // - dateVal.ParseString("1747"); - Assert.AreEqual("Казанская губ., Вятская пров., Слободской уезд, Верховская вол., д. Мокрая Слободка", locPrislon.GetNameByDate(dateVal));*/ } [Test] From 6a1dc1f873d311f58415dbb6fd58b4418aacc9d6 Mon Sep 17 00:00:00 2001 From: "Serg V. Zhdanovskih (Norseman)" Date: Thu, 1 Feb 2024 21:53:48 +0300 Subject: [PATCH 03/11] Minor improvements --- projects/GKCore/GDModel/GDMCustomDate.cs | 29 +++-------- projects/GKCore/GDModel/GDMDate.cs | 8 +++ projects/GKCore/GDModel/GDMDatePeriod.cs | 6 +++ projects/GKCore/GDModel/GDMDateRange.cs | 6 +++ projects/GKCore/GDModel/GDMDateValue.cs | 10 ++++ .../Providers/GEDCOM/GEDCOMProvider.cs | 34 ++++++++++++ .../GKTests/GDModel/GDMLocationRecordTests.cs | 52 +++++++++++++------ 7 files changed, 107 insertions(+), 38 deletions(-) diff --git a/projects/GKCore/GDModel/GDMCustomDate.cs b/projects/GKCore/GDModel/GDMCustomDate.cs index b4a4e20b0..088cf6919 100644 --- a/projects/GKCore/GDModel/GDMCustomDate.cs +++ b/projects/GKCore/GDModel/GDMCustomDate.cs @@ -157,6 +157,8 @@ public bool Equals(GDMCustomDate other) return abs1.Equals(abs2); } + public abstract void GetDateRange(out GDMDate dateStart, out GDMDate dateEnd); + public static GDMDate CreateApproximated(GDMDate date, GDMApproximated approximated) { GDMDate result = new GDMDate(); @@ -181,36 +183,17 @@ public static GDMDateRange CreateRange(GDMDate dateAfter, GDMDate dateBefore) return result; } - - public static void GetDateRange(GDMCustomDate date, out GDMDate dateStart, out GDMDate dateEnd) - { - if (date is GDMDateRange) { - GDMDateRange dtRange = date as GDMDateRange; - dateStart = dtRange.After; - dateEnd = dtRange.Before; - } else if (date is GDMDatePeriod) { - GDMDatePeriod dtPeriod = date as GDMDatePeriod; - dateStart = dtPeriod.DateFrom; - dateEnd = dtPeriod.DateTo; - } else { - var dt = date as GDMDate; - dateStart = dt; - dateEnd = dt; - } - } - public static GDMDatePeriod GetIntersection(GDMCustomDate range1, GDMCustomDate range2) { if (range1 == null || range1.IsEmpty() || range2 == null || range2.IsEmpty()) return GDMDatePeriod.Empty; GDMDate r1start, r1end, r2start, r2end; + range1.GetDateRange(out r1start, out r1end); + range2.GetDateRange(out r2start, out r2end); - GetDateRange(range1, out r1start, out r1end); - GetDateRange(range2, out r2start, out r2end); - - GDMDate greatestStart = r1start.CompareTo(r2start) > 0 ? r1start : r2start; - GDMDate smallestEnd = r1end.CompareTo(r2end) < 0 ? r1end : r2end; + GDMDate greatestStart = r1start.IsEmpty() ? r2start : (r2start.IsEmpty() ? r1start : (r1start.CompareTo(r2start) > 0) ? r1start : r2start); + GDMDate smallestEnd = r1end.IsEmpty() ? r2end : (r2end.IsEmpty() ? r1end : (r1end.CompareTo(r2end) < 0) ? r1end : r2end); // no intersection if (greatestStart.CompareTo(smallestEnd) > 0) { diff --git a/projects/GKCore/GDModel/GDMDate.cs b/projects/GKCore/GDModel/GDMDate.cs index 7f8671bbd..5cc8e1b8c 100644 --- a/projects/GKCore/GDModel/GDMDate.cs +++ b/projects/GKCore/GDModel/GDMDate.cs @@ -36,6 +36,8 @@ namespace GDModel /// public class GDMDate : GDMCustomDate { + public static readonly GDMDate Empty = new GDMDate(); + public const int UNKNOWN_YEAR = -1; private GDMApproximated fApproximated; @@ -585,5 +587,11 @@ public override string GetDisplayStringExt(DateFormat format, bool sign, bool sh } #endregion + + public override void GetDateRange(out GDMDate dateStart, out GDMDate dateEnd) + { + dateStart = this; + dateEnd = this; + } } } diff --git a/projects/GKCore/GDModel/GDMDatePeriod.cs b/projects/GKCore/GDModel/GDMDatePeriod.cs index 5092e9fdf..704903c0f 100644 --- a/projects/GKCore/GDModel/GDMDatePeriod.cs +++ b/projects/GKCore/GDModel/GDMDatePeriod.cs @@ -155,5 +155,11 @@ public override string GetDisplayStringExt(DateFormat format, bool sign, bool sh return result; } + + public override void GetDateRange(out GDMDate dateStart, out GDMDate dateEnd) + { + dateStart = fDateFrom; + dateEnd = fDateTo; + } } } diff --git a/projects/GKCore/GDModel/GDMDateRange.cs b/projects/GKCore/GDModel/GDMDateRange.cs index fb64d2572..40d79022f 100644 --- a/projects/GKCore/GDModel/GDMDateRange.cs +++ b/projects/GKCore/GDModel/GDMDateRange.cs @@ -168,5 +168,11 @@ public override string GetDisplayStringExt(DateFormat format, bool sign, bool sh return result; } + + public override void GetDateRange(out GDMDate dateStart, out GDMDate dateEnd) + { + dateStart = fDateAfter; + dateEnd = fDateBefore; + } } } diff --git a/projects/GKCore/GDModel/GDMDateValue.cs b/projects/GKCore/GDModel/GDMDateValue.cs index d3c940b40..49cddb5cc 100644 --- a/projects/GKCore/GDModel/GDMDateValue.cs +++ b/projects/GKCore/GDModel/GDMDateValue.cs @@ -169,5 +169,15 @@ public override string ToString() { return GetDisplayStringExt(DateFormat.dfDD_MM_YYYY, true, true, false); } + + public override void GetDateRange(out GDMDate dateStart, out GDMDate dateEnd) + { + if (fValue == null) { + dateStart = null; + dateEnd = null; + } else { + fValue.GetDateRange(out dateStart, out dateEnd); + } + } } } diff --git a/projects/GKCore/GDModel/Providers/GEDCOM/GEDCOMProvider.cs b/projects/GKCore/GDModel/Providers/GEDCOM/GEDCOMProvider.cs index 35aa5c38c..3c81c71b4 100644 --- a/projects/GKCore/GDModel/Providers/GEDCOM/GEDCOMProvider.cs +++ b/projects/GKCore/GDModel/Providers/GEDCOM/GEDCOMProvider.cs @@ -1814,6 +1814,10 @@ private StackTuple AddLocationRecordTag(GDMTag owner, int tagLevel, int tagId, s curTag = locRec.Names.Add(new GDMLocationName()); curTag.ParseString(tagValue); addHandler = AddLocationNameTag; + } else if (tagType == GEDCOMTagType._LOC) { + curTag = locRec.TopLevels.Add(new GDMLocationLink()); + curTag.ParseString(tagValue); + addHandler = AddLocationLinkTag; } else if (tagType == GEDCOMTagType.MAP) { curTag = locRec.Map; addHandler = AddMapTag; @@ -1834,6 +1838,7 @@ private static void WriteLocationRecord(StreamWriter stream, int level, GDMTag t WriteMap(stream, level, locRec.Map); WriteList(stream, level, locRec.Names, WriteLocationName); + WriteList(stream, level, locRec.TopLevels, WriteLocationLink); } @@ -1873,6 +1878,35 @@ private static bool WriteLocationName(StreamWriter stream, int level, GDMTag tag } + private StackTuple AddLocationLinkTag(GDMTag owner, int tagLevel, int tagId, string tagValue) + { + GDMLocationLink locLink = (GDMLocationLink)owner; + GDMTag curTag = null; + AddTagHandler addHandler = null; + + GEDCOMTagType tagType = (GEDCOMTagType)tagId; + if (tagType == GEDCOMTagType.DATE) { + curTag = locLink.Date; + GEDCOMUtils.ParseDateValue(fTree, locLink.Date, tagValue); + } else { + return AddBaseTag(owner, tagLevel, tagId, tagValue); + } + + return CreateReaderStackTuple(tagLevel, curTag, addHandler); + } + + private static bool WriteLocationLink(StreamWriter stream, int level, GDMTag tag) + { + GDMLocationLink locLink = (GDMLocationLink)tag; + + if (!WriteBaseTag(stream, level, locLink)) return false; + + level += 1; + WriteBaseTag(stream, level, locLink.Date); + return true; + } + + private static StackTuple AddPlaceTag(GDMTag owner, int tagLevel, int tagId, string tagValue) { GDMPlace place = (GDMPlace)owner; diff --git a/projects/GKTests/GDModel/GDMLocationRecordTests.cs b/projects/GKTests/GDModel/GDMLocationRecordTests.cs index 6459d9914..0a0076ceb 100644 --- a/projects/GKTests/GDModel/GDMLocationRecordTests.cs +++ b/projects/GKTests/GDModel/GDMLocationRecordTests.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using GDModel.Providers.GEDCOM; using GKCore; @@ -196,7 +197,7 @@ public void Test_Hierarchy() locRus.AddLocName("Российская республика", "FROM 01 SEP 1917 TO 18 JUL 1918");//++ locRus.AddLocName("РСФСР", "FROM 19 JUL 1918 TO 29 DEC 1922");//++ locRus.AddLocName("СССР", "FROM 30 DEC 1922 TO 26 DEC 1991");//++ - locRus.AddLocName("РФ", "FROM 27 DEC 1991 TO 9999");//++ + locRus.AddLocName("РФ", "FROM 27 DEC 1991");//++ IList fullNames = locRus.GetFullNames(tree); string result = string.Join("\n", fullNames.Select(x => string.Format("'{0}': '{1}'", x.Date.ToString(), x.StringValue))); @@ -206,17 +207,17 @@ public void Test_Hierarchy() "'01.09.1917 [G] - 18.07.1918 [G]': 'Российская республика'\n" + "'19.07.1918 [G] - 29.12.1922 [G]': 'РСФСР'\n" + "'30.12.1922 [G] - 26.12.1991 [G]': 'СССР'\n" + - "'27.12.1991 [G] - __.__.9999 [G]': 'РФ'", + "'27.12.1991 [G] >': 'РФ'", result); var locSibGub = tree.CreateLocation(); - locSibGub.AddLocName("Сибирская губерния", "FROM 18 DEC 1708 TO 18 JAN 1782"); - locSibGub.AddLocLink(locRus, "FROM 18 DEC 1708 TO 18 JAN 1782"); + locSibGub.AddLocName("Сибирская губерния", "FROM 18 DEC 1708 TO 19 JAN 1782"); + locSibGub.AddLocLink(locRus, "FROM 18 DEC 1708 TO 19 JAN 1782"); fullNames = locSibGub.GetFullNames(tree); result = string.Join("\n", fullNames.Select(x => string.Format("'{0}': '{1}'", x.Date.ToString(), x.StringValue))); Assert.AreEqual("'18.12.1708 [G] - 21.10.1721 [G]': 'Сибирская губерния, Российское царство'\n" + - "'22.10.1721 [G] - 18.01.1782 [G]': 'Сибирская губерния, Российская империя'", + "'22.10.1721 [G] - 19.01.1782 [G]': 'Сибирская губерния, Российская империя'", result); var locKazGub = tree.CreateLocation(); @@ -253,7 +254,7 @@ public void Test_Hierarchy() locVyatGub.AddLocName("Вятская губерния", "FROM 31 DEC 1796 TO 14 JUL 1929"); locVyatGub.AddLocName("Вятский округ", "FROM 15 JUL 1929 TO 29 JUL 1930"); locVyatGub.AddLocName("Кировский край", "FROM 07 DEC 1934 TO 04 DEC 1936"); - locVyatGub.AddLocName("Кировская область", "FROM 05 DEC 1936 TO 9999"); + locVyatGub.AddLocName("Кировская область", "FROM 05 DEC 1936"); locVyatGub.AddLocLink(locSibGub, "FROM 29 MAY 1719 TO 28 APR 1727"); locVyatGub.AddLocLink(locKazGub, "FROM 29 APR 1727 TO 10 SEP 1780"); locVyatGub.AddLocLink(locRus, "FROM 11 SEP 1780 TO 14 JUL 1929"); @@ -280,19 +281,19 @@ public void Test_Hierarchy() locSlobUezd.AddLocName("Слободской уезд", "FROM 1646 TO 1719"); locSlobUezd.AddLocName("Слободской дистр.", "FROM 1719 TO 1726"); locSlobUezd.AddLocName("Слободской уезд", "FROM 1727 TO 09 JUN 1929"); - locSlobUezd.AddLocName("Слободской район", "FROM 10 JUN 1929 TO 9999"); + locSlobUezd.AddLocName("Слободской район", "FROM 10 JUN 1929"); locSlobUezd.AddLocLink(locRus, "TO 1718"); locSlobUezd.AddLocLink(locVyatGub, "FROM 1719 TO 1726"); - locSlobUezd.AddLocLink(locKazGub, "FROM 1727 TO 10 SEP 1780"); + locSlobUezd.AddLocLink(locVyatGub, "FROM 1727 TO 10 SEP 1780"); locSlobUezd.AddLocLink(locVyatGub, "FROM 11 SEP 1780 TO 10 JUN 1929"); var locOmutUezd = tree.CreateLocation(); locOmutUezd.AddLocName("Омутнинский уезд", "FROM 05 JAN 1921 TO 09 JUN 1929"); - locOmutUezd.AddLocName("Омутнинский район", "FROM 10 JUN 1929 TO 9999"); + locOmutUezd.AddLocName("Омутнинский район", "FROM 10 JUN 1929"); locOmutUezd.AddLocLink(locVyatGub, "FROM 05 JAN 1921 TO 9999"); var locVerhkamRn = tree.CreateLocation(); - locVerhkamRn.AddLocName("Верхнекамский район", "FROM 12 JAN 1965 TO 9999"); + locVerhkamRn.AddLocName("Верхнекамский район", "FROM 12 JAN 1965"); locVerhkamRn.AddLocLink(locVyatGub, "FROM 12 JAN 1965 TO 9999"); fullNames = locSlobUezd.GetFullNames(tree); @@ -300,7 +301,8 @@ public void Test_Hierarchy() Assert.AreEqual("'__.__.1646 [G] - __.__.1718 [G]': 'Слободской уезд, Российское царство'\n" + "'29.05.1719 [G] - 21.10.1721 [G]': 'Слободской дистр., Вятская провинция, Сибирская губерния, Российское царство'\n" + "'22.10.1721 [G] - __.__.1726 [G]': 'Слободской дистр., Вятская провинция, Сибирская губерния, Российская империя'\n" + - "'__.__.1727 [G] - 10.09.1780 [G]': 'Слободской уезд, Казанская губерния, Российская империя'\n" + + "'__.__.1727 [G] - 28.04.1727 [G]': 'Слободской уезд, Вятская провинция, Сибирская губерния, Российская империя'\n" + + "'29.04.1727 [G] - 10.09.1780 [G]': 'Слободской уезд, Вятская провинция, Казанская губерния, Российская империя'\n" + "'11.09.1780 [G] - 30.12.1796 [G]': 'Слободской уезд, Вятское наместничество, Российская империя'\n" + "'31.12.1796 [G] - 31.08.1917 [G]': 'Слободской уезд, Вятская губерния, Российская империя'\n" + "'01.09.1917 [G] - 18.07.1918 [G]': 'Слободской уезд, Вятская губерния, Российская республика'\n" + @@ -339,7 +341,8 @@ public void Test_Hierarchy() Assert.AreEqual("'__.__.1678 [G] - __.__.1718 [G]': 'поч. Старое раменье, Слободской уезд, Российское царство'\n" + "'__.__.1720 [G] - 21.10.1721 [G]': 'д. Прислонская, Верховская вол., Слободской дистр., Вятская провинция, Сибирская губерния, Российское царство'\n" + "'22.10.1721 [G] - __.__.1726 [G]': 'д. Прислонская, Верховская вол., Слободской дистр., Вятская провинция, Сибирская губерния, Российская империя'\n" + - "'__.__.1727 [G] - __.__.1764 [G]': 'д. Мокрая Слободка, Верховская вол., Слободской уезд, Казанская губерния, Российская империя'\n" + + "'__.__.1727 [G] - 28.04.1727 [G]': 'д. Мокрая Слободка, Верховская вол., Слободской уезд, Вятская провинция, Сибирская губерния, Российская империя'\n" + + "'29.04.1727 [G] - __.__.1764 [G]': 'д. Мокрая Слободка, Верховская вол., Слободской уезд, Вятская провинция, Казанская губерния, Российская империя'\n" + "'__.__.1802 [G] - __.__.1883 [G]': 'д. Мокрая Слободка, Лоинская вол., Слободской уезд, Вятская губерния, Российская империя'\n" + "'__.__.1884 [G] - 31.08.1917 [G]': 'д. Мокрая Слободка, Кирсинская вол., Слободской уезд, Вятская губерния, Российская империя'\n" + "'01.09.1917 [G] - 18.07.1918 [G]': 'д. Мокрая Слободка, Кирсинская вол., Слободской уезд, Вятская губерния, Российская республика'\n" + @@ -353,6 +356,9 @@ public void Test_Hierarchy() "'05.12.1936 [G] - __.__.1964 [G]': 'д. Колегово, Омутнинский район, Кировская область, СССР'\n" + "'12.01.1965 [G] - __.__.1978 [G]': 'д. Колегово, Верхнекамский район, Кировская область, СССР'", result); + + //var gedcomProvider = new GEDCOMProvider(tree); + //gedcomProvider.SaveToStreamExt(new FileStream("d:\\Russia.ged", FileMode.CreateNew), GEDCOMCharacterSet.csUTF8); } [Test] @@ -364,9 +370,25 @@ public void Test_DateIntersections() var r3 = GetRange("FROM 1701 TO 1780"); var r4 = GetRange("FROM 1780 TO 1936"); - Assert.AreEqual("FROM 1719 TO 1727", GDMCustomDate.GetIntersection(r1, r2).StringValue); - Assert.AreEqual("FROM 1708 TO 1780", GDMCustomDate.GetIntersection(r1, r3).StringValue); - Assert.AreEqual("FROM 1780 TO 1929", GDMCustomDate.GetIntersection(r1, r4).StringValue); + Assert.AreEqual("FROM 1719 TO 1727", GDMCustomDate.GetIntersection(r1, r2).StringValue); // r2 inside r1 + Assert.AreEqual("FROM 1708 TO 1780", GDMCustomDate.GetIntersection(r1, r3).StringValue); // r3 to left of r1 + Assert.AreEqual("FROM 1780 TO 1929", GDMCustomDate.GetIntersection(r1, r4).StringValue); // r4 to right of r1 + + Assert.AreEqual("FROM 1747 TO 1764", GDMCustomDate.GetIntersection(GetRange("TO 1764"), GetRange("FROM 1747 TO 1834")).StringValue); + Assert.AreEqual("FROM 1747 TO 1764", GDMCustomDate.GetIntersection(GetRange("FROM 1747 TO 1834"), GetRange("TO 1764")).StringValue); + + Assert.AreEqual("FROM 1782 TO 1834", GDMCustomDate.GetIntersection(GetRange("FROM 1782"), GetRange("FROM 1747 TO 1834")).StringValue); + Assert.AreEqual("FROM 1782 TO 1834", GDMCustomDate.GetIntersection(GetRange("FROM 1747 TO 1834"), GetRange("FROM 1782")).StringValue); + + Assert.AreEqual("FROM 1782 TO 1834", GDMCustomDate.GetIntersection(GetRange("FROM 1782"), GetRange("TO 1834")).StringValue); + Assert.AreEqual("FROM 1782 TO 1834", GDMCustomDate.GetIntersection(GetRange("TO 1834"), GetRange("FROM 1782")).StringValue); + + Assert.AreEqual("", GDMCustomDate.GetIntersection(GetRange("FROM 1858"), GetRange("TO 1834")).StringValue); // no intersects + Assert.AreEqual("", GDMCustomDate.GetIntersection(GetRange("TO 1834"), GetRange("FROM 1858")).StringValue); // no intersects + + Assert.AreEqual("", GDMCustomDate.GetIntersection(GetRange(""), GetRange("FROM 1747 TO 1834")).StringValue); // no intersects + + Assert.AreEqual("", GDMCustomDate.GetIntersection(GetRange("FROM 1719 TO 1727"), GetRange("FROM 1747 TO 1834")).StringValue); // no intersects } private static GDMDatePeriod GetRange(string strDateRange) From 27faa1f15c3195a84f6ccf7e4e4d68e8e5e887cf Mon Sep 17 00:00:00 2001 From: "Serg V. Zhdanovskih (Norseman)" Date: Fri, 2 Feb 2024 22:14:14 +0300 Subject: [PATCH 04/11] Finished location hierarchy support --- projects/GKCore/GDModel/GDMLocationLink.cs | 2 +- projects/GKCore/GDModel/GDMLocationName.cs | 2 +- projects/GKCore/GDModel/GDMLocationRecord.cs | 52 +++-- projects/GKCore/GKCore.csproj | 3 + .../GKCore/Controllers/BaseController.cs | 35 ++++ .../Controllers/LocationEditDlgController.cs | 6 + .../LocationLinkEditDlgController.cs | 103 +++++++++ .../GKCore/Design/Views/ILocationEditDlg.cs | 1 + .../Design/Views/ILocationLinkEditDlg.cs | 35 ++++ projects/GKCore/GKCore/GKUtils.cs | 14 ++ .../GKCore/Lists/LocationLinksListModel.cs | 124 +++++++++++ .../GKCore/Operations/OrdinaryOperation.cs | 28 +++ projects/GKv2/GEDKeeper2/GEDKeeper2.csproj | 6 + .../GKUI/Forms/LocationEditDlg.Designer.cs | 39 +++- .../GEDKeeper2/GKUI/Forms/LocationEditDlg.cs | 10 +- .../Forms/LocationLinkEditDlg.Designer.cs | 115 ++++++++++ .../GKUI/Forms/LocationLinkEditDlg.cs | 70 +++++++ .../GEDKeeper2/GKUI/Platform/WFAppHost.cs | 1 + .../GEDKeeper3/GKUI/Forms/LocationEditDlg.cs | 8 + .../GKUI/Forms/LocationEditDlg.xeto | 9 +- .../GKUI/Forms/LocationLinkEditDlg.cs | 82 ++++++++ .../GKUI/Forms/LocationLinkEditDlg.xeto | 37 ++++ .../GEDKeeper3/GKUI/Platform/EtoAppHost.cs | 1 + .../GKUI/Forms/LocationEditDlg.xaml | 11 +- .../GKUI/Forms/LocationEditDlg.xaml.cs | 5 + .../GKUI/Forms/LocationLinkEditDlg.xaml | 37 ++++ .../GKUI/Forms/LocationLinkEditDlg.xaml.cs | 65 ++++++ .../GEDKeeperX/GKUI/Platform/XFAppHost.cs | 1 + .../GEDKeeperX/GKUI/Platform/XFStdDialogs.cs | 6 + samples/RussiaLocations.ged | 196 ++++++++++++++++++ 30 files changed, 1076 insertions(+), 28 deletions(-) create mode 100644 projects/GKCore/GKCore/Controllers/LocationLinkEditDlgController.cs create mode 100644 projects/GKCore/GKCore/Design/Views/ILocationLinkEditDlg.cs create mode 100644 projects/GKCore/GKCore/Lists/LocationLinksListModel.cs create mode 100644 projects/GKv2/GEDKeeper2/GKUI/Forms/LocationLinkEditDlg.Designer.cs create mode 100644 projects/GKv2/GEDKeeper2/GKUI/Forms/LocationLinkEditDlg.cs create mode 100644 projects/GKv3/GEDKeeper3/GKUI/Forms/LocationLinkEditDlg.cs create mode 100644 projects/GKv3/GEDKeeper3/GKUI/Forms/LocationLinkEditDlg.xeto create mode 100644 projects/GKvX/GEDKeeperX/GKUI/Forms/LocationLinkEditDlg.xaml create mode 100644 projects/GKvX/GEDKeeperX/GKUI/Forms/LocationLinkEditDlg.xaml.cs create mode 100644 samples/RussiaLocations.ged diff --git a/projects/GKCore/GDModel/GDMLocationLink.cs b/projects/GKCore/GDModel/GDMLocationLink.cs index b0e296a95..6e9d23090 100644 --- a/projects/GKCore/GDModel/GDMLocationLink.cs +++ b/projects/GKCore/GDModel/GDMLocationLink.cs @@ -29,7 +29,7 @@ public enum GDMLocationRelationship } - public sealed class GDMLocationLink : GDMPointer + public sealed class GDMLocationLink : GDMPointer, IGDMLocationElement { private readonly GDMDateValue fDate; private GDMLocationRelationship fRelationship; diff --git a/projects/GKCore/GDModel/GDMLocationName.cs b/projects/GKCore/GDModel/GDMLocationName.cs index 21e9533fc..10e64c3f9 100644 --- a/projects/GKCore/GDModel/GDMLocationName.cs +++ b/projects/GKCore/GDModel/GDMLocationName.cs @@ -23,7 +23,7 @@ namespace GDModel { - public sealed class GDMLocationName : GDMValueTag + public sealed class GDMLocationName : GDMValueTag, IGDMLocationElement { private string fAbbreviation; private readonly GDMDateValue fDate; diff --git a/projects/GKCore/GDModel/GDMLocationRecord.cs b/projects/GKCore/GDModel/GDMLocationRecord.cs index d12a0c7db..640ca3c1d 100644 --- a/projects/GKCore/GDModel/GDMLocationRecord.cs +++ b/projects/GKCore/GDModel/GDMLocationRecord.cs @@ -142,7 +142,6 @@ public IList GetFullNames(GDMTree tree) var topNames = topLoc.GetFullNames(tree); for (int i = 0; i < topNames.Count; i++) { var topName = topNames[i]; - if (topName.Date.IsEmpty()) continue; var interDate = GDMCustomDate.GetIntersection(topLevel.Date.Value, topName.Date.Value); if (!interDate.IsEmpty()) { @@ -152,7 +151,6 @@ public IList GetFullNames(GDMTree tree) buffer.Add(newLocName); } } - //buffer.AddRange(topNames); } for (int j = 0; j < buffer.Count; j++) { @@ -162,7 +160,6 @@ public IList GetFullNames(GDMTree tree) for (int i = 0; i < fNames.Count; i++) { var locName = fNames[i]; - if (locName.Date.IsEmpty()) continue; var interDate = GDMCustomDate.GetIntersection(topDate, locName.Date.Value); if (!interDate.IsEmpty()) { @@ -192,11 +189,10 @@ public string GetNameByDate(GDMCustomDate date) if (date != null && !date.IsEmpty()) { for (int i = 1; i < fNames.Count; i++) { var locName = fNames[i]; - if (!locName.Date.IsEmpty()) { - var interDate = GDMCustomDate.GetIntersection(date, locName.Date.Value); - if (!interDate.IsEmpty()) { - return locName.StringValue; - } + + var interDate = GDMCustomDate.GetIntersection(date, locName.Date.Value); + if (!interDate.IsEmpty()) { + return locName.StringValue; } } } @@ -209,39 +205,53 @@ public bool ValidateNames() GDMCustomDate prevDate = null; for (int i = 0; i < fNames.Count; i++) { var locName = fNames[i]; - if (!locName.Date.IsEmpty()) { - var interDate = GDMCustomDate.GetIntersection(prevDate, locName.Date.Value); - if (!interDate.IsEmpty()) { - return false; - } + + var interDate = GDMCustomDate.GetIntersection(prevDate, locName.Date.Value); + if (!interDate.IsEmpty()) { + return false; } + prevDate = locName.Date.Value; } return true; } - public void SortNames() + public bool ValidateLinks() { - fNames.Sort(NamesCompare); + GDMCustomDate prevDate = null; + for (int i = 0; i < fTopLevels.Count; i++) { + var locLink = fTopLevels[i]; + + var interDate = GDMCustomDate.GetIntersection(prevDate, locLink.Date.Value); + if (!interDate.IsEmpty()) { + return false; + } + + prevDate = locLink.Date.Value; + } + return true; } - private static int NamesCompare(GDMLocationName cp1, GDMLocationName cp2) + public void SortNames() { - UDN udn1 = cp1.Date.GetUDN(); - UDN udn2 = cp2.Date.GetUDN(); - return -udn1.CompareTo(udn2); + fNames.Sort(ElementsCompare); } public void SortTopLevels() { - fTopLevels.Sort(TopLevelsCompare); + fTopLevels.Sort(ElementsCompare); } - private static int TopLevelsCompare(GDMLocationLink cp1, GDMLocationLink cp2) + private static int ElementsCompare(IGDMLocationElement cp1, IGDMLocationElement cp2) { UDN udn1 = cp1.Date.GetUDN(); UDN udn2 = cp2.Date.GetUDN(); return -udn1.CompareTo(udn2); } } + + public interface IGDMLocationElement + { + GDMDateValue Date { get; } + } } diff --git a/projects/GKCore/GKCore.csproj b/projects/GKCore/GKCore.csproj index e7fd267ba..9538b29e1 100644 --- a/projects/GKCore/GKCore.csproj +++ b/projects/GKCore/GKCore.csproj @@ -64,6 +64,8 @@ GlobalSuppressions.cs + + @@ -528,6 +530,7 @@ + diff --git a/projects/GKCore/GKCore/Controllers/BaseController.cs b/projects/GKCore/GKCore/Controllers/BaseController.cs index 098451710..76948bf49 100644 --- a/projects/GKCore/GKCore/Controllers/BaseController.cs +++ b/projects/GKCore/GKCore/Controllers/BaseController.cs @@ -514,6 +514,41 @@ public static async Task> ModifyLocationName return result; } + public static async Task> ModifyLocationLink(IView owner, IBaseWindow baseWin, ChangeTracker undoman, + GDMLocationRecord locRec, GDMLocationLink locLink) + { + var result = new ModificationResult(); + + try { + baseWin.Context.BeginUpdate(); + + bool exists = locLink != null; + if (!exists) { + locLink = new GDMLocationLink(); + } + + using (var dlg = AppHost.ResolveDialog(baseWin)) { + dlg.LocationLink = locLink; + result.Result = await AppHost.Instance.ShowModalAsync(dlg, owner, false); + } + + if (!exists) { + if (result.Result) { + result.Result = undoman.DoOrdinaryOperation(OperationType.otLocationLinkAdd, locRec, locLink); + } else { + locLink.Dispose(); + locLink = null; + } + } + + result.Record = locLink; + } finally { + baseWin.Context.EndUpdate(); + } + + return result; + } + private static async Task PostProcessPerson(IBaseWindow baseWin, GDMIndividualRecord indivRec) { baseWin.Context.ImportNames(indivRec); diff --git a/projects/GKCore/GKCore/Controllers/LocationEditDlgController.cs b/projects/GKCore/GKCore/Controllers/LocationEditDlgController.cs index ba15eb206..3bbc508dd 100644 --- a/projects/GKCore/GKCore/Controllers/LocationEditDlgController.cs +++ b/projects/GKCore/GKCore/Controllers/LocationEditDlgController.cs @@ -62,6 +62,8 @@ public override void Init(IBaseWindow baseWin) base.Init(baseWin); fView.NamesList.ListModel = new LocationNamesListModel(fView, baseWin, fLocalUndoman); + fView.LinksList.ListModel = new LocationLinksListModel(fView, baseWin, fLocalUndoman); + fView.NotesList.ListModel = new NoteLinksListModel(fView, baseWin, fLocalUndoman); fView.MediaList.ListModel = new MediaLinksListModel(fView, baseWin, fLocalUndoman); } @@ -99,6 +101,8 @@ public override void UpdateView() fView.Longitude.Text = GEDCOMUtils.CoordToStr(fLocationRecord.Map.Long); fView.NamesList.ListModel.DataOwner = fLocationRecord; + fView.LinksList.ListModel.DataOwner = fLocationRecord; + fView.NotesList.ListModel.DataOwner = fLocationRecord; fView.MediaList.ListModel.DataOwner = fLocationRecord; @@ -202,6 +206,8 @@ public override void SetLocale() fView.GeoCoordsList.AddColumn(LangMan.LS(LSID.Longitude), 80, false); GetControl("pageHistory").Text = LangMan.LS(LSID.History); + GetControl("pageHistNames").Text = LangMan.LS(LSID.Names); + GetControl("pageHistLinks").Text = LangMan.LS(LSID.Links); } } } diff --git a/projects/GKCore/GKCore/Controllers/LocationLinkEditDlgController.cs b/projects/GKCore/GKCore/Controllers/LocationLinkEditDlgController.cs new file mode 100644 index 000000000..8649b40df --- /dev/null +++ b/projects/GKCore/GKCore/Controllers/LocationLinkEditDlgController.cs @@ -0,0 +1,103 @@ +/* + * "GEDKeeper", the personal genealogical database editor. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. + * + * This file is part of "GEDKeeper". + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; +using GDModel; +using GKCore.Design; +using GKCore.Design.Controls; +using GKCore.Design.Views; + +namespace GKCore.Controllers +{ + /// + /// + /// + public sealed class LocationLinkEditDlgController : DialogController + { + private GDMLocationLink fLocationLink; + private GDMLocationRecord fTempLocation; + + public GDMLocationLink LocationLink + { + get { return fLocationLink; } + set { + if (fLocationLink != value) { + fLocationLink = value; + fTempLocation = fBase.Context.Tree.GetPtrValue(fLocationLink); + UpdateView(); + } + } + } + + + public LocationLinkEditDlgController(ILocationLinkEditDlg view) : base(view) + { + fView.TopLevelText.Activate(); + } + + public override bool Accept() + { + try { + fBase.Context.Tree.SetPtrValue(fLocationLink, fTempLocation); + + try { + GDMCustomDate dt = fView.DateCtl.Date; + if (dt == null) throw new ArgumentNullException("dt"); + + fLocationLink.Date.ParseString(dt.StringValue); + } catch (Exception ex) { + AppHost.StdDialogs.ShowError(LangMan.LS(LSID.DateInvalid)); + throw ex; + } + + fLocalUndoman.Commit(); + + return true; + } catch (Exception ex) { + Logger.WriteError("LocationLinkEditDlgController.Accept()", ex); + return false; + } + } + + public override void UpdateView() + { + fView.DateCtl.FixedDateType = GDMDateType.PeriodBetween; + + fView.TopLevelText.Text = (fTempLocation == null) ? "" : fTempLocation.GetNameByDate(fView.DateCtl.Date); + fView.DateCtl.Date = fLocationLink.Date.Value; + } + + public async void SetLocation() + { + fTempLocation = await fBase.Context.SelectRecord(fView, GDMRecordType.rtLocation, null) as GDMLocationRecord; + fView.TopLevelText.Text = (fTempLocation == null) ? "" : fTempLocation.GetNameByDate(fView.DateCtl.Date); + } + + public override void SetLocale() + { + fView.Title = LangMan.LS(LSID.Location); + + GetControl("btnAccept").Text = LangMan.LS(LSID.DlgAccept); + GetControl("btnCancel").Text = LangMan.LS(LSID.DlgCancel); + GetControl("lblLocation").Text = LangMan.LS(LSID.Location); + GetControl("lblDate").Text = LangMan.LS(LSID.Date); + } + } +} diff --git a/projects/GKCore/GKCore/Design/Views/ILocationEditDlg.cs b/projects/GKCore/GKCore/Design/Views/ILocationEditDlg.cs index 94c42ee73..7dca237d1 100644 --- a/projects/GKCore/GKCore/Design/Views/ILocationEditDlg.cs +++ b/projects/GKCore/GKCore/Design/Views/ILocationEditDlg.cs @@ -33,6 +33,7 @@ public interface ILocationEditDlg : ICommonDialog, IBaseEditor ISheetList MediaList { get; } ISheetList NotesList { get; } ISheetList NamesList { get; } + ISheetList LinksList { get; } IListView GeoCoordsList { get; } ITextBox Name { get; } ITextBox Latitude { get; } diff --git a/projects/GKCore/GKCore/Design/Views/ILocationLinkEditDlg.cs b/projects/GKCore/GKCore/Design/Views/ILocationLinkEditDlg.cs new file mode 100644 index 000000000..f8b387175 --- /dev/null +++ b/projects/GKCore/GKCore/Design/Views/ILocationLinkEditDlg.cs @@ -0,0 +1,35 @@ +/* + * "GEDKeeper", the personal genealogical database editor. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. + * + * This file is part of "GEDKeeper". + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using GDModel; +using GKCore.Design.Controls; +using GKCore.Interfaces; + +namespace GKCore.Design.Views +{ + public interface ILocationLinkEditDlg : ICommonDialog, IBaseEditor + { + GDMLocationLink LocationLink { get; set; } + + ITextBox TopLevelText { get; } + + IDateControl DateCtl { get; } + } +} diff --git a/projects/GKCore/GKCore/GKUtils.cs b/projects/GKCore/GKCore/GKUtils.cs index 70e698b2a..1edd589bf 100644 --- a/projects/GKCore/GKCore/GKUtils.cs +++ b/projects/GKCore/GKCore/GKUtils.cs @@ -3020,6 +3020,20 @@ public static void ShowLocationInfo(IBaseContext baseContext, GDMLocationRecord GDMTree tree = baseContext.Tree; + var fullNames = locRec.GetFullNames(tree); + if (fullNames.Count > 0) { + //linkList.Sort(); + + summary.Add(""); + summary.Add(LangMan.LS(LSID.History) + ":"); + + int num = fullNames.Count; + for (int i = 0; i < num; i++) { + var xName = fullNames[i]; + summary.Add(" " + string.Format("{0}: {1}", xName.Date.GetDisplayStringExt(glob.DefDateFormat, glob.ShowDatesSign, glob.ShowDatesCalendar, false), xName.StringValue)); + } + } + linkList = GetLocationLinks(tree, locRec); if (linkList.Count > 0) { diff --git a/projects/GKCore/GKCore/Lists/LocationLinksListModel.cs b/projects/GKCore/GKCore/Lists/LocationLinksListModel.cs new file mode 100644 index 000000000..fdf0353d8 --- /dev/null +++ b/projects/GKCore/GKCore/Lists/LocationLinksListModel.cs @@ -0,0 +1,124 @@ +/* + * "GEDKeeper", the personal genealogical database editor. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. + * + * This file is part of "GEDKeeper". + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; +using System.Threading.Tasks; +using BSLib; +using GDModel; +using GKCore.Controllers; +using GKCore.Design; +using GKCore.Interfaces; +using GKCore.Operations; +using GKCore.Types; + +namespace GKCore.Lists +{ + public sealed class LocationLinksListModel : SheetModel + { + private GDMLocationRecord fRelLocation; + + public LocationLinksListModel(IView owner, IBaseWindow baseWin, ChangeTracker undoman) : base(owner, baseWin, undoman) + { + AllowedActions = EnumSet.Create(RecordAction.raAdd, RecordAction.raEdit, RecordAction.raDelete); + + fListColumns.AddColumn(LSID.NumberSym, 25, false); + fListColumns.AddColumn(LSID.Name, 300, false); + fListColumns.AddColumn(LSID.Date, 140, false); + fListColumns.ResetDefaults(); + } + + public override void Fetch(GDMLocationLink aRec) + { + base.Fetch(aRec); + fRelLocation = fBaseContext.Tree.GetPtrValue(fFetchedRec); + } + + protected override object GetColumnValueEx(int colType, int colSubtype, bool isVisible) + { + object result = null; + switch (colType) { + case 0: + result = fStructList.IndexOf(fFetchedRec) + 1; + break; + case 1: + result = (fRelLocation == null) ? string.Empty : fRelLocation.GetNameByDate(fFetchedRec.Date.Value); + break; + case 2: + result = new GDMDateItem(fFetchedRec.Date.Value); + break; + } + return result; + } + + public override void UpdateContents() + { + var dataOwner = fDataOwner as GDMLocationRecord; + if (dataOwner == null) return; + + try { + UpdateStructList(dataOwner.TopLevels); + } catch (Exception ex) { + Logger.WriteError("LocationLinksListModel.UpdateContents()", ex); + } + } + + public override async Task Modify(object sender, ModifyEventArgs eArgs) + { + var dataOwner = fDataOwner as GDMLocationRecord; + if (fBaseWin == null || dataOwner == null) return; + + var locLink = eArgs.ItemData as GDMLocationLink; + + bool result = false; + + switch (eArgs.Action) { + case RecordAction.raAdd: + case RecordAction.raEdit: { + var locLinkRes = await BaseController.ModifyLocationLink(fOwner, fBaseWin, fUndoman, dataOwner, locLink); + locLink = locLinkRes.Record; + result = locLinkRes.Result; + + if (result) { + if (!dataOwner.ValidateLinks()) { + AppHost.StdDialogs.ShowError(LangMan.LS(LSID.ThePeriodsOfPlaceNamesOverlap)); + } + dataOwner.SortNames(); + } + } + break; + + case RecordAction.raDelete: + if (await AppHost.StdDialogs.ShowQuestion(LangMan.LS(LSID.RemoveNameQuery))) { + result = fUndoman.DoOrdinaryOperation(OperationType.otLocationNameRemove, dataOwner, locLink); + } + break; + } + + if (result) { + if (eArgs.Action == RecordAction.raAdd) { + eArgs.ItemData = locLink; + } + + fBaseWin.Context.Modified = true; + eArgs.IsChanged = true; + } + } + } +} diff --git a/projects/GKCore/GKCore/Operations/OrdinaryOperation.cs b/projects/GKCore/GKCore/Operations/OrdinaryOperation.cs index 94469cbf0..291124213 100644 --- a/projects/GKCore/GKCore/Operations/OrdinaryOperation.cs +++ b/projects/GKCore/GKCore/Operations/OrdinaryOperation.cs @@ -75,6 +75,9 @@ public enum OperationType otLocationNameAdd, otLocationNameRemove, + + otLocationLinkAdd, + otLocationLinkRemove, } /// @@ -213,6 +216,11 @@ private bool ProcessOperation(bool redo) result = ProcessLocationName(redo); break; + case OperationType.otLocationLinkAdd: + case OperationType.otLocationLinkRemove: + result = ProcessLocationLink(redo); + break; + default: result = false; break; @@ -636,5 +644,25 @@ private bool ProcessLocationName(bool redo) } return true; } + + private bool ProcessLocationLink(bool redo) + { + GDMLocationRecord locRec = fObj as GDMLocationRecord; + GDMLocationLink locLink = fNewVal as GDMLocationLink; + + if (locRec == null || locLink == null) { + return false; + } + + if (fType == OperationType.otLocationLinkRemove) { + redo = !redo; + } + if (redo) { + locRec.TopLevels.Add(locLink); + } else { + locRec.TopLevels.Extract(locLink); + } + return true; + } } } diff --git a/projects/GKv2/GEDKeeper2/GEDKeeper2.csproj b/projects/GKv2/GEDKeeper2/GEDKeeper2.csproj index e26f72ffd..77d6806ba 100644 --- a/projects/GKv2/GEDKeeper2/GEDKeeper2.csproj +++ b/projects/GKv2/GEDKeeper2/GEDKeeper2.csproj @@ -155,6 +155,12 @@ LocationEditDlg.cs + + Form + + + LocationLinkEditDlg.cs + Form diff --git a/projects/GKv2/GEDKeeper2/GKUI/Forms/LocationEditDlg.Designer.cs b/projects/GKv2/GEDKeeper2/GKUI/Forms/LocationEditDlg.Designer.cs index 24368d815..0be0116ad 100644 --- a/projects/GKv2/GEDKeeper2/GKUI/Forms/LocationEditDlg.Designer.cs +++ b/projects/GKv2/GEDKeeper2/GKUI/Forms/LocationEditDlg.Designer.cs @@ -25,6 +25,9 @@ partial class LocationEditDlg private System.Windows.Forms.ColumnHeader ColumnHeader2; private System.Windows.Forms.ColumnHeader ColumnHeader3; private System.Windows.Forms.TabPage pageHistory; + private GKUI.Components.GKTabControl tabsHistory; + private System.Windows.Forms.TabPage pageHistNames; + private System.Windows.Forms.TabPage pageHistLinks; private void InitializeComponent() { @@ -51,8 +54,12 @@ private void InitializeComponent() this.pageNotes = new System.Windows.Forms.TabPage(); this.pageMultimedia = new System.Windows.Forms.TabPage(); this.pageHistory = new System.Windows.Forms.TabPage(); + this.tabsHistory = new GKUI.Components.GKTabControl(); + this.pageHistNames = new System.Windows.Forms.TabPage(); + this.pageHistLinks = new System.Windows.Forms.TabPage(); this.tabsData.SuspendLayout(); - this.pageCommon.SuspendLayout(); + this.tabsHistory.SuspendLayout(); + this.pageCommon.SuspendLayout(); this.grpSearch.SuspendLayout(); this.SuspendLayout(); // @@ -245,8 +252,35 @@ private void InitializeComponent() this.btnShowOnMap.Text = "btnShowOnMap"; this.btnShowOnMap.Click += new System.EventHandler(this.btnShowOnMap_Click); // + // pageHistNames + // + this.pageHistNames.Location = new System.Drawing.Point(4, 26); + this.pageHistNames.Name = "pageHistNames"; + this.pageHistNames.Size = new System.Drawing.Size(777, 486); + this.pageHistNames.TabIndex = 0; + this.pageHistNames.Text = "pageHistNames"; + // + // pageHistLinks + // + this.pageHistLinks.Location = new System.Drawing.Point(4, 26); + this.pageHistLinks.Name = "pageHistLinks"; + this.pageHistLinks.Size = new System.Drawing.Size(777, 486); + this.pageHistLinks.TabIndex = 1; + this.pageHistLinks.Text = "pageHistLinks"; + // + // tabsHistory + // + this.tabsHistory.Controls.Add(this.pageHistNames); + this.tabsHistory.Controls.Add(this.pageHistLinks); + this.tabsHistory.Location = new System.Drawing.Point(0, 0); + this.tabsHistory.Name = "tabsHistory"; + this.tabsHistory.SelectedIndex = 0; + this.tabsHistory.Size = new System.Drawing.Size(785, 516); + this.tabsHistory.TabIndex = 0; + // // pageHistory // + this.pageHistory.Controls.Add(this.tabsHistory); this.pageHistory.Location = new System.Drawing.Point(4, 26); this.pageHistory.Name = "pageHistory"; this.pageHistory.Size = new System.Drawing.Size(777, 486); @@ -287,7 +321,8 @@ private void InitializeComponent() this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "LocationEditDlg"; - this.tabsData.ResumeLayout(false); + this.tabsHistory.ResumeLayout(false); + this.tabsData.ResumeLayout(false); this.pageCommon.ResumeLayout(false); this.pageCommon.PerformLayout(); this.grpSearch.ResumeLayout(false); diff --git a/projects/GKv2/GEDKeeper2/GKUI/Forms/LocationEditDlg.cs b/projects/GKv2/GEDKeeper2/GKUI/Forms/LocationEditDlg.cs index 93d0ac555..31b9ed851 100644 --- a/projects/GKv2/GEDKeeper2/GKUI/Forms/LocationEditDlg.cs +++ b/projects/GKv2/GEDKeeper2/GKUI/Forms/LocationEditDlg.cs @@ -36,6 +36,7 @@ public sealed partial class LocationEditDlg : CommonDialog. + */ + +using System; +using GDModel; +using GKCore.Controllers; +using GKCore.Design.Controls; +using GKCore.Design.Views; +using GKCore.Interfaces; +using GKUI.Components; + +namespace GKUI.Forms +{ + public sealed partial class LocationLinkEditDlg : CommonDialog, ILocationLinkEditDlg + { + public GDMLocationLink LocationLink + { + get { return fController.LocationLink; } + set { fController.LocationLink = value; } + } + + #region View Interface + + ITextBox ILocationLinkEditDlg.TopLevelText + { + get { return GetControlHandler(txtTopLevel); } + } + + IDateControl ILocationLinkEditDlg.DateCtl + { + get { return GetControlHandler(dateCtl); } + } + + #endregion + + public LocationLinkEditDlg(IBaseWindow baseWin) + { + InitializeComponent(); + + btnLocationAdd.Image = UIHelper.LoadResourceImage("Resources.btn_rec_new.gif"); + btnAccept.Image = UIHelper.LoadResourceImage("Resources.btn_accept.gif"); + btnCancel.Image = UIHelper.LoadResourceImage("Resources.btn_cancel.gif"); + + fController = new LocationLinkEditDlgController(this); + fController.Init(baseWin); + } + + private void btnLocationAdd_Click(object sender, EventArgs e) + { + fController.SetLocation(); + } + } +} diff --git a/projects/GKv2/GEDKeeper2/GKUI/Platform/WFAppHost.cs b/projects/GKv2/GEDKeeper2/GKUI/Platform/WFAppHost.cs index 1144fa4d4..b63211a5c 100644 --- a/projects/GKv2/GEDKeeper2/GKUI/Platform/WFAppHost.cs +++ b/projects/GKv2/GEDKeeper2/GKUI/Platform/WFAppHost.cs @@ -468,6 +468,7 @@ public static void ConfigureBootstrap() container.Register(LifeCycle.Transient); container.Register(LifeCycle.Transient); container.Register(LifeCycle.Transient); + container.Register(LifeCycle.Transient); container.Register(LifeCycle.Transient); container.Register(LifeCycle.Transient); container.Register(LifeCycle.Transient); diff --git a/projects/GKv3/GEDKeeper3/GKUI/Forms/LocationEditDlg.cs b/projects/GKv3/GEDKeeper3/GKUI/Forms/LocationEditDlg.cs index e122115f1..80f1a5485 100644 --- a/projects/GKv3/GEDKeeper3/GKUI/Forms/LocationEditDlg.cs +++ b/projects/GKv3/GEDKeeper3/GKUI/Forms/LocationEditDlg.cs @@ -57,7 +57,10 @@ public sealed partial class LocationEditDlg : CommonDialog - + + + + + + + + diff --git a/projects/GKv3/GEDKeeper3/GKUI/Forms/LocationLinkEditDlg.cs b/projects/GKv3/GEDKeeper3/GKUI/Forms/LocationLinkEditDlg.cs new file mode 100644 index 000000000..f1ddc2e55 --- /dev/null +++ b/projects/GKv3/GEDKeeper3/GKUI/Forms/LocationLinkEditDlg.cs @@ -0,0 +1,82 @@ +/* + * "GEDKeeper", the personal genealogical database editor. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. + * + * This file is part of "GEDKeeper". + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; +using Eto.Forms; +using Eto.Serialization.Xaml; +using GDModel; +using GKCore.Controllers; +using GKCore.Design.Controls; +using GKCore.Design.Views; +using GKCore.Interfaces; +using GKUI.Components; + +namespace GKUI.Forms +{ + public sealed partial class LocationLinkEditDlg : CommonDialog, ILocationLinkEditDlg + { + #region Design components +#pragma warning disable CS0169, CS0649, IDE0044, IDE0051 + + private Button btnAccept; + private Button btnCancel; + private Label lblLocation; + private TextBox txtTopLevel; + private Button btnLocationAdd; + private Label lblDate; + private GKDateControl dateCtl; + +#pragma warning restore CS0169, CS0649, IDE0044, IDE0051 + #endregion + + public GDMLocationLink LocationLink + { + get { return fController.LocationLink; } + set { fController.LocationLink = value; } + } + + #region View Interface + + ITextBox ILocationLinkEditDlg.TopLevelText + { + get { return GetControlHandler(txtTopLevel); } + } + + IDateControl ILocationLinkEditDlg.DateCtl + { + get { return GetControlHandler(dateCtl); } + } + + #endregion + + public LocationLinkEditDlg(IBaseWindow baseWin) + { + XamlReader.Load(this); + + fController = new LocationLinkEditDlgController(this); + fController.Init(baseWin); + } + + private void btnLocationAdd_Click(object sender, EventArgs e) + { + fController.SetLocation(); + } + } +} diff --git a/projects/GKv3/GEDKeeper3/GKUI/Forms/LocationLinkEditDlg.xeto b/projects/GKv3/GEDKeeper3/GKUI/Forms/LocationLinkEditDlg.xeto new file mode 100644 index 000000000..e57972935 --- /dev/null +++ b/projects/GKv3/GEDKeeper3/GKUI/Forms/LocationLinkEditDlg.xeto @@ -0,0 +1,37 @@ + + + + + + + + + diff --git a/projects/GKv3/GEDKeeper3/GKUI/Platform/EtoAppHost.cs b/projects/GKv3/GEDKeeper3/GKUI/Platform/EtoAppHost.cs index bd2338872..0c608a27d 100644 --- a/projects/GKv3/GEDKeeper3/GKUI/Platform/EtoAppHost.cs +++ b/projects/GKv3/GEDKeeper3/GKUI/Platform/EtoAppHost.cs @@ -512,6 +512,7 @@ public static void ConfigureBootstrap() container.Register(LifeCycle.Transient); container.Register(LifeCycle.Transient); container.Register(LifeCycle.Transient); + container.Register(LifeCycle.Transient); container.Register(LifeCycle.Transient); container.Register(LifeCycle.Transient); container.Register(LifeCycle.Transient); diff --git a/projects/GKvX/GEDKeeperX/GKUI/Forms/LocationEditDlg.xaml b/projects/GKvX/GEDKeeperX/GKUI/Forms/LocationEditDlg.xaml index 73382e11a..3008cd449 100644 --- a/projects/GKvX/GEDKeeperX/GKUI/Forms/LocationEditDlg.xaml +++ b/projects/GKvX/GEDKeeperX/GKUI/Forms/LocationEditDlg.xaml @@ -47,7 +47,16 @@ - + + + + + + + + + + diff --git a/projects/GKvX/GEDKeeperX/GKUI/Forms/LocationEditDlg.xaml.cs b/projects/GKvX/GEDKeeperX/GKUI/Forms/LocationEditDlg.xaml.cs index c22f5c8bd..46944779b 100644 --- a/projects/GKvX/GEDKeeperX/GKUI/Forms/LocationEditDlg.xaml.cs +++ b/projects/GKvX/GEDKeeperX/GKUI/Forms/LocationEditDlg.xaml.cs @@ -49,6 +49,11 @@ ISheetList ILocationEditDlg.NamesList get { return fNamesList; } } + ISheetList ILocationEditDlg.LinksList + { + get { return fLinksList; } + } + ISheetList ILocationEditDlg.MediaList { get { return fMediaList; } diff --git a/projects/GKvX/GEDKeeperX/GKUI/Forms/LocationLinkEditDlg.xaml b/projects/GKvX/GEDKeeperX/GKUI/Forms/LocationLinkEditDlg.xaml new file mode 100644 index 000000000..7f09e22b1 --- /dev/null +++ b/projects/GKvX/GEDKeeperX/GKUI/Forms/LocationLinkEditDlg.xaml @@ -0,0 +1,37 @@ + + + + + + +