1 /*
2  *  "GEDKeeper", the personal genealogical database editor.
3  *  Copyright (C) 2009-2021 by Sergey V. Zhdanovskih.
4  *
5  *  This file is part of "GEDKeeper".
6  *
7  *  This program is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 using System;
22 using System.Collections.Generic;
23 using System.IO;
24 using System.Text;
25 using BSLib;
26 using GDModel;
27 using GKCore.Interfaces;
28 using GKCore.Lists;
29 using GKCore.Types;
30 
31 namespace GKCore.Options
32 {
33     public enum OptionsPage
34     {
35         opCommon, opTreeChart, opCircleChart, opInterface, opPedigree, opMultimedia
36     }
37 
38     /// <summary>
39     ///
40     /// </summary>
41     public sealed class GlobalOptions : BaseObject
42     {
43         public const int OPTS_VERSION = 1;
44 
45         private static GlobalOptions fInstance = null;
46 
47         private readonly TreeChartOptions fTreeChartOptions;
48         private DateFormat fDefDateFormat;
49         private bool fShowDatesSign;
50         private NameFormat fDefNameFormat;
51         private readonly StringList fEventFilters;
52         private int fInterfaceLang;
53         private readonly List<LangRecord> fLanguages;
54         private string fLastDir;
55         private readonly List<MRUFile> fMRUFiles;
56         private readonly StringList fNameFilters;
57         private readonly PedigreeOptions fPedigreeOptions;
58         private bool fPlacesWithAddress;
59         private readonly ProxyOptions fProxy;
60         private readonly StringList fRelations;
61         private readonly StringList fResidenceFilters;
62         private bool fShowTips;
63         private readonly ListColumns fIndividualListColumns;
64         private bool fListHighlightUnmarriedPersons;
65         private bool fListHighlightUnparentedPersons;
66         private ExtRect fMWinRect;
67         private WindowState fMWinState;
68         private readonly StringList fLastBases;
69         private bool fShowDatesCalendar;
70         private FileBackup fFileBackup;
71         private int fFileBackupEachRevisionMaxCount;
72         private bool fAutosave;
73         private int fAutosaveInterval;
74         private bool fExtendedNames;
75         private WomanSurnameFormat fWomanSurnameFormat;
76         private readonly CircleChartOptions fCircleChartOptions;
77         private string fGeocoder;
78         private bool fRemovableMediaWarning;
79         private bool fLoadRecentFiles;
80         private bool fEmbeddedMediaPlayer;
81         private bool fAllowMediaStoreReferences;
82         private bool fAllowMediaStoreRelativeReferences;
83         private MediaStoreType fMediaStoreDefault;
84         private bool fAllowDeleteMediaFileFromStgArc;
85         private bool fAllowDeleteMediaFileFromRefs;
86         private bool fDeleteMediaFileWithoutConfirm;
87         private bool fUseExtendedNotes;
88 
89         private bool fAutoCheckUpdates;
90         private bool fAutoSortChildren;
91         private bool fAutoSortSpouses;
92         private bool fCharsetDetection;
93         private bool fCheckTreeSize;
94         private bool fDialogClosingWarn;
95         private bool fFirstCapitalLetterInNames;
96         private string fGeoSearchCountry;
97         private readonly ListOptionsCollection fListOptions;
98         private bool fReadabilityHighlightRows;
99         private bool fShortKinshipForm;
100         private bool fSurnameFirstInOrder;
101 
102 
103         public static GlobalOptions Instance
104         {
105             get {
106                 if (fInstance == null) fInstance = new GlobalOptions();
107                 return fInstance;
108             }
109         }
110 
111 
112         public bool AllowDeleteMediaFileFromStgArc
113         {
114             get { return fAllowDeleteMediaFileFromStgArc; }
115             set { fAllowDeleteMediaFileFromStgArc = value; }
116         }
117 
118         public bool AllowDeleteMediaFileFromRefs
119         {
120             get { return fAllowDeleteMediaFileFromRefs; }
121             set { fAllowDeleteMediaFileFromRefs = value; }
122         }
123 
124         public bool AllowMediaStoreReferences
125         {
126             get { return fAllowMediaStoreReferences; }
127             set { fAllowMediaStoreReferences = value; }
128         }
129 
130         public bool AllowMediaStoreRelativeReferences
131         {
132             get { return fAllowMediaStoreRelativeReferences; }
133             set { fAllowMediaStoreRelativeReferences = value; }
134         }
135 
136         public bool AutoCheckUpdates
137         {
138             get { return fAutoCheckUpdates; }
139             set { fAutoCheckUpdates = value; }
140         }
141 
142         public bool Autosave
143         {
144             get { return fAutosave; }
145             set { fAutosave = value; }
146         }
147 
148         public int AutosaveInterval
149         {
150             get { return fAutosaveInterval; }
151             set { fAutosaveInterval = value; }
152         }
153 
154         public bool AutoSortChildren
155         {
156             get { return fAutoSortChildren; }
157             set { fAutoSortChildren = value; }
158         }
159 
160         public bool AutoSortSpouses
161         {
162             get { return fAutoSortSpouses; }
163             set { fAutoSortSpouses = value; }
164         }
165 
166         public bool CharsetDetection
167         {
168             get { return fCharsetDetection; }
169             set { fCharsetDetection = value; }
170         }
171 
172         public bool CheckTreeSize
173         {
174             get { return fCheckTreeSize; }
175             set { fCheckTreeSize = value; }
176         }
177 
178         public CircleChartOptions CircleChartOptions
179         {
180             get { return fCircleChartOptions; }
181         }
182 
183         public GEDCOMCharacterSet DefCharacterSet
184         {
185             get { return GEDCOMCharacterSet.csUTF8; }
186         }
187 
188         public DateFormat DefDateFormat
189         {
190             get { return fDefDateFormat; }
191             set { fDefDateFormat = value; }
192         }
193 
194         public NameFormat DefNameFormat
195         {
196             get { return fDefNameFormat; }
197             set { fDefNameFormat = value; }
198         }
199 
200         public bool DeleteMediaFileWithoutConfirm
201         {
202             get { return fDeleteMediaFileWithoutConfirm; }
203             set { fDeleteMediaFileWithoutConfirm = value; }
204         }
205 
206         public bool DialogClosingWarn
207         {
208             get { return fDialogClosingWarn; }
209             set { fDialogClosingWarn = value; }
210         }
211 
212         public bool EmbeddedMediaPlayer
213         {
214             get { return fEmbeddedMediaPlayer; }
215             set { fEmbeddedMediaPlayer = value; }
216         }
217 
218         public StringList EventFilters
219         {
220             get { return fEventFilters; }
221         }
222 
223         // TODO: Need to make a decision on additional types of names:
224         // religious and according to the census (see GDMPersonalNamePieces)
225         public bool ExtendedNames
226         {
227             get { return fExtendedNames; }
228             set { fExtendedNames = value; }
229         }
230 
231         public FileBackup FileBackup
232         {
233             get { return fFileBackup; }
234             set { fFileBackup = value; }
235         }
236 
237         public int FileBackupEachRevisionMaxCount
238         {
239             get { return fFileBackupEachRevisionMaxCount; }
240             set { fFileBackupEachRevisionMaxCount = value; }
241         }
242 
243         public bool FirstCapitalLetterInNames
244         {
245             get { return fFirstCapitalLetterInNames; }
246             set { fFirstCapitalLetterInNames = value; }
247         }
248 
249         public string Geocoder
250         {
251             get { return fGeocoder; }
252             set { fGeocoder = value; }
253         }
254 
255         public string GeoSearchCountry
256         {
257             get { return fGeoSearchCountry; }
258             set { fGeoSearchCountry = value; }
259         }
260 
261         public ListColumns IndividualListColumns
262         {
263             get { return fIndividualListColumns; }
264         }
265 
266         public int InterfaceLang
267         {
268             get { return fInterfaceLang; }
269             set { fInterfaceLang = value; }
270         }
271 
272         public IList<LangRecord> Languages
273         {
274             get { return fLanguages; }
275         }
276 
277         public string LastDir
278         {
279             get { return fLastDir; }
280             set { fLastDir = value; }
281         }
282 
283         public bool ListHighlightUnmarriedPersons
284         {
285             get { return fListHighlightUnmarriedPersons; }
286             set { fListHighlightUnmarriedPersons = value; }
287         }
288 
289         public bool ListHighlightUnparentedPersons
290         {
291             get { return fListHighlightUnparentedPersons; }
292             set { fListHighlightUnparentedPersons = value; }
293         }
294 
295         public ListOptionsCollection ListOptions
296         {
297             get { return fListOptions; }
298         }
299 
300         public bool LoadRecentFiles
301         {
302             get { return fLoadRecentFiles; }
303             set { fLoadRecentFiles = value; }
304         }
305 
306         public MediaStoreType MediaStoreDefault
307         {
308             get { return fMediaStoreDefault; }
309             set { fMediaStoreDefault = value; }
310         }
311 
312         public List<MRUFile> MRUFiles
313         {
314             get { return fMRUFiles; }
315         }
316 
317         public ExtRect MWinRect
318         {
319             get { return fMWinRect; }
320             set { fMWinRect = value; }
321         }
322 
323         public WindowState MWinState
324         {
325             get { return fMWinState; }
326             set { fMWinState = value; }
327         }
328 
329         public StringList NameFilters
330         {
331             get { return fNameFilters; }
332         }
333 
334         public PedigreeOptions PedigreeOptions
335         {
336             get { return fPedigreeOptions; }
337         }
338 
339         public bool PlacesWithAddress
340         {
341             get { return fPlacesWithAddress; }
342             set { fPlacesWithAddress = value; }
343         }
344 
345         public ProxyOptions Proxy
346         {
347             get { return fProxy; }
348         }
349 
350         public bool ReadabilityHighlightRows
351         {
352             get { return fReadabilityHighlightRows; }
353             set { fReadabilityHighlightRows = value; }
354         }
355 
356         public StringList Relations
357         {
358             get { return fRelations; }
359         }
360 
361         public bool RemovableMediaWarning
362         {
363             get { return fRemovableMediaWarning; }
364             set { fRemovableMediaWarning = value; }
365         }
366 
367         public StringList ResidenceFilters
368         {
369             get { return fResidenceFilters; }
370         }
371 
372         public bool ShortKinshipForm
373         {
374             get { return fShortKinshipForm; }
375             set { fShortKinshipForm = value; }
376         }
377 
378         public bool ShowDatesCalendar
379         {
380             get { return fShowDatesCalendar; }
381             set { fShowDatesCalendar = value; }
382         }
383 
384         public bool ShowDatesSign
385         {
386             get { return fShowDatesSign; }
387             set { fShowDatesSign = value; }
388         }
389 
390         public bool ShowTips
391         {
392             get { return fShowTips; }
393             set { fShowTips = value; }
394         }
395 
396         public bool SurnameFirstInOrder
397         {
398             get { return fSurnameFirstInOrder; }
399             set { fSurnameFirstInOrder = value; }
400         }
401 
402         public TreeChartOptions TreeChartOptions
403         {
404             get { return fTreeChartOptions; }
405         }
406 
407         public bool UseExtendedNotes
408         {
409             get { return fUseExtendedNotes; }
410             set { fUseExtendedNotes = value; }
411         }
412 
413         public WomanSurnameFormat WomanSurnameFormat
414         {
415             get { return fWomanSurnameFormat; }
416             set { fWomanSurnameFormat = value; }
417         }
418 
419 
GlobalOptions()420         private GlobalOptions()
421         {
422             fTreeChartOptions = new TreeChartOptions();
423             fEventFilters = new StringList();
424             fMRUFiles = new List<MRUFile>();
425             fNameFilters = new StringList();
426             fResidenceFilters = new StringList();
427             fPedigreeOptions = new PedigreeOptions();
428             fProxy = new ProxyOptions();
429             fRelations = new StringList();
430             fCircleChartOptions = new CircleChartOptions();
431             fGeocoder = "Google";
432             fRemovableMediaWarning = true;
433             fLoadRecentFiles = true;
434             fEmbeddedMediaPlayer = true;
435             fAllowMediaStoreReferences = false;
436             fAllowMediaStoreRelativeReferences = true;
437             fMediaStoreDefault = 0;
438             fAllowDeleteMediaFileFromStgArc = true;
439             fAllowDeleteMediaFileFromRefs = false;
440             fDeleteMediaFileWithoutConfirm = false;
441             fUseExtendedNotes = false;
442 
443             fAutoCheckUpdates = true;
444             fAutoSortChildren = true;
445             fAutoSortSpouses = false;
446             fCheckTreeSize = true;
447 
448             fIndividualListColumns = IndividualListMan.CreateIndividualListColumns();
449             fIndividualListColumns.ResetDefaults();
450 
451             fLanguages = new List<LangRecord>();
452             fLastBases = new StringList();
453 
454             fAutosave = false;
455             fAutosaveInterval = 10;
456 
457             fListOptions = new ListOptionsCollection();
458             fReadabilityHighlightRows = true;
459             fShortKinshipForm = false;
460             fSurnameFirstInOrder = true;
461 
462             fCharsetDetection = false;
463             fFirstCapitalLetterInNames = false;
464             fGeoSearchCountry = string.Empty;
465         }
466 
Dispose(bool disposing)467         protected override void Dispose(bool disposing)
468         {
469             if (disposing) {
470                 fLastBases.Dispose();
471                 //fLanguages.Dispose();
472                 fRelations.Dispose();
473 
474                 fResidenceFilters.Dispose();
475                 fNameFilters.Dispose();
476                 //FMRUFiles.Dispose();
477                 fEventFilters.Dispose();
478 
479                 fProxy.Dispose();
480                 fPedigreeOptions.Dispose();
481                 fTreeChartOptions.Dispose();
482             }
483             base.Dispose(disposing);
484         }
485 
LngPrepareProc(string fileName)486         private void LngPrepareProc(string fileName)
487         {
488             try {
489                 using (StreamReader lngFile = new StreamReader(fileName, Encoding.UTF8)) {
490                     string st = lngFile.ReadLine(); // header
491 
492                     if (!string.IsNullOrEmpty(st) && st[0] == ';') {
493                         st = st.Remove(0, 1);
494                         string[] lngParams = st.Split(',');
495                         if (lngParams.Length < 3)
496                             throw new GKException("Header is incorrect");
497 
498                         string lngCode = lngParams[0];
499                         string lngSign = lngParams[1];
500                         string lngName = lngParams[2];
501 
502                         bool xt = (lngParams.Length == 4 && lngParams[3] == "xt");
503 
504                         LangRecord lngRec = new LangRecord((ushort)int.Parse(lngCode), lngSign, lngName, fileName);
505                         fLanguages.Add(lngRec);
506                     }
507                 }
508             } catch (Exception ex) {
509                 Logger.WriteError("GlobalOptions.LngPrepareProc(" + fileName + ")", ex);
510             }
511         }
512 
FindLanguages()513         public void FindLanguages()
514         {
515             try {
516                 string path = GKUtils.GetLangsPath();
517                 string[] langFiles = Directory.GetFiles(path, "*.lng", SearchOption.TopDirectoryOnly);
518                 for (int i = 0; i < langFiles.Length; i++) LngPrepareProc(langFiles[i]);
519             } catch (Exception ex) {
520                 Logger.WriteError("GlobalOptions.FindLanguages()", ex);
521             }
522         }
523 
LoadLanguage(int langCode)524         public void LoadLanguage(int langCode)
525         {
526             if (langCode != LangMan.LS_DEF_CODE) {
527                 bool loaded = false;
528 
529                 foreach (LangRecord langRec in fLanguages) {
530                     if (langRec.Code == langCode) {
531                         loaded = LangMan.LoadFromFile(langRec.FileName);
532                         break;
533                     }
534                 }
535 
536                 if (!loaded) langCode = LangMan.LS_DEF_CODE;
537             }
538 
539             if (langCode == LangMan.LS_DEF_CODE) {
540                 LangMan.DefInit();
541             }
542 
543             fInterfaceLang = (ushort)langCode;
544         }
545 
GetLangByCode(int code)546         public LangRecord GetLangByCode(int code)
547         {
548             foreach (LangRecord lngRec in fLanguages) {
549                 if (lngRec.Code == code) {
550                     return lngRec;
551                 }
552             }
553 
554             return null;
555         }
556 
GetLanguageSign()557         public string GetLanguageSign()
558         {
559             LangRecord lngrec = GetLangByCode(InterfaceLang);
560             string lngSign = (lngrec == null) ? LangMan.LS_DEF_SIGN : lngrec.Sign;
561             return lngSign;
562         }
563 
GetCurrentItfLang()564         public GDMLanguageID GetCurrentItfLang()
565         {
566             if (InterfaceLang == LangMan.LS_DEF_CODE) {
567                 return GDMLanguageID.English;
568             } else {
569                 LangRecord langRec = GetLangByCode(InterfaceLang);
570                 return (langRec == null) ? GDMLanguageID.English : langRec.LangID;
571             }
572         }
573 
GetLastBase(int index)574         public string GetLastBase(int index)
575         {
576             return fLastBases[index];
577         }
578 
GetLastBasesCount()579         public int GetLastBasesCount()
580         {
581             return fLastBases.Count;
582         }
583 
MRUFiles_IndexOf(string fileName)584         public int MRUFiles_IndexOf(string fileName)
585         {
586             int num = fMRUFiles.Count;
587             for (int i = 0; i < num; i++) {
588                 if (fMRUFiles[i].FileName == fileName) {
589                     return i;
590                 }
591             }
592 
593             return -1;
594         }
595 
AddLastBase(string fileName)596         public void AddLastBase(string fileName)
597         {
598             fLastBases.Add(fileName);
599         }
600 
ClearLastBases()601         public void ClearLastBases()
602         {
603             fLastBases.Clear();
604         }
605 
606 
LoadMRUFromFile(IniFile ini, List<MRUFile> mruFiles)607         public static void LoadMRUFromFile(IniFile ini, List<MRUFile> mruFiles)
608         {
609             int cnt = ini.ReadInteger("Common", "MRUFiles_Count", 0);
610             for (int i = 0; i < cnt; i++) {
611                 string sect = "MRUFile_" + i.ToString();
612                 string fn = ini.ReadString(sect, "FileName", "");
613                 if (File.Exists(fn)) {
614                     MRUFile mf = new MRUFile();
615                     mf.LoadFromFile(ini, sect);
616                     mruFiles.Add(mf);
617                 } else {
618                     MRUFile.DeleteKeys(ini, sect);
619                 }
620             }
621         }
622 
LoadPluginsFromFile(IniFile ini)623         public void LoadPluginsFromFile(IniFile ini)
624         {
625             if (ini == null)
626                 throw new ArgumentNullException("ini");
627 
628             int num = AppHost.Plugins.Count;
629             for (int i = 0; i < num; i++) {
630                 var plugin = AppHost.Plugins[i];
631 
632                 var dlgPlugin = plugin as IDialogReplacement;
633                 if (dlgPlugin != null) {
634                     var plgName = plugin.GetType().Name;
635                     dlgPlugin.Enabled = ini.ReadBool("Plugins", plgName + ".Enabled", false);
636                 }
637             }
638         }
639 
SavePluginsToFile(IniFile ini)640         public void SavePluginsToFile(IniFile ini)
641         {
642             if (ini == null)
643                 throw new ArgumentNullException("ini");
644 
645             int num = AppHost.Plugins.Count;
646             for (int i = 0; i < num; i++) {
647                 var plugin = AppHost.Plugins[i];
648 
649                 var dlgPlugin = plugin as IDialogReplacement;
650                 if (dlgPlugin != null) {
651                     var plgName = plugin.GetType().Name;
652                     ini.WriteBool("Plugins", plgName + ".Enabled", dlgPlugin.Enabled);
653                 }
654             }
655         }
656 
LoadFromFile(IniFile ini)657         public void LoadFromFile(IniFile ini)
658         {
659             if (ini == null)
660                 throw new ArgumentNullException("ini");
661 
662             int optsVersion = ini.ReadInteger("Common", "OptsVersion", 0);
663 
664             fDefNameFormat = (NameFormat)ini.ReadInteger("Common", "DefNameFormat", 0);
665             fDefDateFormat = (DateFormat)ini.ReadInteger("Common", "DefDateFormat", 0);
666             fLastDir = ini.ReadString("Common", "LastDir", "");
667             fPlacesWithAddress = ini.ReadBool("Common", "PlacesWithAddress", false);
668             fShowTips = ini.ReadBool("Common", "ShowTips", true);
669             fInterfaceLang = (ushort)ini.ReadInteger("Common", "InterfaceLang", 0);
670             fFileBackup = (FileBackup)ini.ReadInteger("Common", "FileBackup", 0);
671             fFileBackupEachRevisionMaxCount = ini.ReadInteger("Common", "FileBackupEachRevisionMaxCount", 0);
672             fShowDatesCalendar = ini.ReadBool("Common", "ShowDatesCalendar", false);
673             fShowDatesSign = ini.ReadBool("Common", "ShowDatesSigns", false);
674             fRemovableMediaWarning = ini.ReadBool("Common", "RemovableMediaWarning", true);
675             fLoadRecentFiles = ini.ReadBool("Common", "LoadRecentFiles", true);
676             fEmbeddedMediaPlayer = ini.ReadBool("Common", "EmbeddedMediaPlayer", true);
677             fAllowMediaStoreReferences = ini.ReadBool("Common", "AllowMediaStoreReferences", false);
678             fAllowMediaStoreRelativeReferences = ini.ReadBool("Common", "AllowMediaStoreRelativeReferences", true); // only when AllowMediaStoreReferences is true
679             fMediaStoreDefault = (MediaStoreType)ini.ReadInteger("Common", "MediaStoreDefault", 0); // (int)MediaStoreType.mstReference
680             fAllowDeleteMediaFileFromStgArc = ini.ReadBool("Common", "AllowDeleteMediaFileFromStgArc", true);
681             fAllowDeleteMediaFileFromRefs = ini.ReadBool("Common", "AllowDeleteMediaFileFromRefs", false);
682             fDeleteMediaFileWithoutConfirm = ini.ReadBool("Common", "DeleteMediaFileWithoutConfirm", false);
683             fAutoCheckUpdates = ini.ReadBool("Common", "AutoCheckUpdates", true);
684             fAutoSortChildren = ini.ReadBool("Common", "AutoSortChildren", true);
685             fAutoSortSpouses = ini.ReadBool("Common", "AutoSortSpouses", false);
686             fCharsetDetection = ini.ReadBool("Common", "CharsetDetection", false);
687             fFirstCapitalLetterInNames = ini.ReadBool("Common", "FirstCapitalLetterInNames", false);
688             fDialogClosingWarn = ini.ReadBool("Common", "DialogClosingWarn", false);
689             fShortKinshipForm = ini.ReadBool("Common", "ShortKinshipForm", false);
690             fSurnameFirstInOrder = ini.ReadBool("Common", "SurnameFirstInOrder", true);
691 
692             fAutosave = ini.ReadBool("Common", "Autosave", false);
693             fAutosaveInterval = ini.ReadInteger("Common", "AutosaveInterval", 10);
694 
695             fExtendedNames = ini.ReadBool("Common", "ExtendedNames", false);
696             fWomanSurnameFormat = (WomanSurnameFormat)ini.ReadInteger("Common", "WomanSurnameFormat", 0);
697 
698             fGeocoder = ini.ReadString("Common", "Geocoder", "Google");
699             fGeoSearchCountry = ini.ReadString("Common", "GeoSearchCountry", "");
700 
701             int kl = ini.ReadInteger("Common", "KeyLayout", AppHost.Instance.GetKeyLayout());
702             AppHost.Instance.SetKeyLayout(kl);
703 
704             fTreeChartOptions.LoadFromFile(ini);
705             fPedigreeOptions.LoadFromFile(ini);
706             fProxy.LoadFromFile(ini);
707 
708             int cnt = ini.ReadInteger("NameFilters", "Count", 0);
709             for (int i = 0; i < cnt; i++)
710             {
711                 string st = ini.ReadString("NameFilters", "Filter_" + i.ToString(), "");
712                 if (st != "") fNameFilters.Add(st);
713             }
714 
715             cnt = ini.ReadInteger("ResidenceFilters", "Count", 0);
716             for (int i = 0; i < cnt; i++)
717             {
718                 fResidenceFilters.Add(ini.ReadString("ResidenceFilters", "Filter_" + i.ToString(), ""));
719             }
720 
721             cnt = ini.ReadInteger("EventFilters", "Count", 0);
722             for (int i = 0; i < cnt; i++)
723             {
724                 fEventFilters.Add(ini.ReadString("EventFilters", "EventVal_" + i.ToString(), ""));
725             }
726 
727             LoadMRUFromFile(ini, fMRUFiles);
728 
729             cnt = ini.ReadInteger("Relations", "Count", 0);
730             for (int i = 0; i < cnt; i++)
731             {
732                 fRelations.Add(ini.ReadString("Relations", "Relation_" + i.ToString(), ""));
733             }
734 
735             fIndividualListColumns.LoadFromFile(ini, "PersonsColumns");
736 
737             fListHighlightUnmarriedPersons = ini.ReadBool("ListPersons", "HighlightUnmarried", false);
738             fListHighlightUnparentedPersons = ini.ReadBool("ListPersons", "HighlightUnparented", false);
739 
740             fMWinRect.Left = ini.ReadInteger("Common", "MWinL", -1);
741             fMWinRect.Top = ini.ReadInteger("Common", "MWinT", -1);
742             fMWinRect.Right = ini.ReadInteger("Common", "MWinW", -1);
743             fMWinRect.Bottom = ini.ReadInteger("Common", "MWinH", -1);
744             fMWinState = (WindowState)((uint)ini.ReadInteger("Common", "MWinState", 0));
745 
746             cnt = ini.ReadInteger("LastBases", "Count", 0);
747             for (int i = 0; i < cnt; i++)
748             {
749                 string st = ini.ReadString("LastBases", "LB" + i.ToString(), "");
750                 AddLastBase(st);
751             }
752 
753             fCircleChartOptions.LoadFromFile(ini);
754 
755             fListOptions.LoadFromFile(ini);
756 
757             LoadPluginsFromFile(ini);
758         }
759 
LoadFromFile(string fileName)760         public void LoadFromFile(string fileName)
761         {
762             if (string.IsNullOrEmpty(fileName))
763                 throw new ArgumentNullException("fileName");
764 
765             try {
766                 IniFile ini = new IniFile(fileName);
767                 try {
768                     LoadFromFile(ini);
769                 } finally {
770                     ini.Dispose();
771                 }
772             } catch (Exception ex) {
773                 Logger.WriteError("GlobalOptions.LoadFromFile()", ex);
774             }
775         }
776 
777 
SaveToFile(IniFile ini)778         public void SaveToFile(IniFile ini)
779         {
780             if (ini == null)
781                 throw new ArgumentNullException("ini");
782 
783             ini.WriteInteger("Common", "OptsVersion", OPTS_VERSION);
784 
785             ini.WriteInteger("Common", "DefNameFormat", (int)fDefNameFormat);
786             ini.WriteInteger("Common", "DefDateFormat", (int)fDefDateFormat);
787             ini.WriteString("Common", "LastDir", fLastDir);
788             ini.WriteBool("Common", "PlacesWithAddress", fPlacesWithAddress);
789             ini.WriteBool("Common", "ShowTips", fShowTips);
790             ini.WriteInteger("Common", "InterfaceLang", fInterfaceLang);
791             ini.WriteInteger("Common", "FileBackup", (int)fFileBackup);
792             ini.WriteInteger("Common", "FileBackupEachRevisionMaxCount", fFileBackupEachRevisionMaxCount);
793             ini.WriteBool("Common", "ShowDatesCalendar", fShowDatesCalendar);
794             ini.WriteBool("Common", "ShowDatesSigns", fShowDatesSign);
795             ini.WriteBool("Common", "RemovableMediaWarning", fRemovableMediaWarning);
796             ini.WriteBool("Common", "LoadRecentFiles", fLoadRecentFiles);
797             ini.WriteBool("Common", "EmbeddedMediaPlayer", fEmbeddedMediaPlayer);
798             ini.WriteBool("Common", "AllowMediaStoreReferences", fAllowMediaStoreReferences);
799             ini.WriteBool("Common", "AllowMediaStoreRelativeReferences", fAllowMediaStoreRelativeReferences);
800             ini.WriteInteger("Common", "MediaStoreDefault", (int)fMediaStoreDefault);
801             ini.WriteBool("Common", "AllowDeleteMediaFileFromStgArc", fAllowDeleteMediaFileFromStgArc);
802             ini.WriteBool("Common", "AllowDeleteMediaFileFromRefs", fAllowDeleteMediaFileFromRefs);
803             ini.WriteBool("Common", "DeleteMediaFileWithoutConfirm", fDeleteMediaFileWithoutConfirm);
804             ini.WriteBool("Common", "AutoCheckUpdates", fAutoCheckUpdates);
805             ini.WriteBool("Common", "AutoSortChildren", fAutoSortChildren);
806             ini.WriteBool("Common", "AutoSortSpouses", fAutoSortSpouses);
807             ini.WriteBool("Common", "CharsetDetection", fCharsetDetection);
808             ini.WriteBool("Common", "FirstCapitalLetterInNames", fFirstCapitalLetterInNames);
809             ini.WriteBool("Common", "DialogClosingWarn", fDialogClosingWarn);
810             ini.WriteBool("Common", "ShortKinshipForm", fShortKinshipForm);
811             ini.WriteBool("Common", "SurnameFirstInOrder", fSurnameFirstInOrder);
812 
813             ini.WriteInteger("Common", "KeyLayout", AppHost.Instance.GetKeyLayout());
814 
815             ini.WriteBool("Common", "Autosave", fAutosave);
816             ini.WriteInteger("Common", "AutosaveInterval", fAutosaveInterval);
817 
818             ini.WriteBool("Common", "ExtendedNames", fExtendedNames);
819             ini.WriteInteger("Common", "WomanSurnameFormat", (int)fWomanSurnameFormat);
820 
821             ini.WriteString("Common", "Geocoder", fGeocoder);
822             ini.WriteString("Common", "GeoSearchCountry", fGeoSearchCountry);
823 
824             fTreeChartOptions.SaveToFile(ini);
825             fPedigreeOptions.SaveToFile(ini);
826             fProxy.SaveToFile(ini);
827 
828             fNameFilters.Sort();
829 
830             int cnt = fNameFilters.Count;
831             ini.WriteInteger("NameFilters", "Count", cnt);
832             for (int i = 0; i < cnt; i++)
833             {
834                 ini.WriteString("NameFilters", "Filter_" + i.ToString(), fNameFilters[i]);
835             }
836 
837             cnt = fResidenceFilters.Count;
838             ini.WriteInteger("ResidenceFilters", "Count", cnt);
839             for (int i = 0; i < cnt; i++)
840             {
841                 ini.WriteString("ResidenceFilters", "Filter_" + i.ToString(), fResidenceFilters[i]);
842             }
843 
844             cnt = fEventFilters.Count;
845             ini.WriteInteger("EventFilters", "Count", cnt);
846             for (int i = 0; i < cnt; i++)
847             {
848                 ini.WriteString("EventFilters", "EventVal_" + i.ToString(), fEventFilters[i]);
849             }
850 
851             cnt = fMRUFiles.Count;
852             ini.WriteInteger("Common", "MRUFiles_Count", cnt);
853             for (int i = 0; i < cnt; i++)
854             {
855                 fMRUFiles[i].SaveToFile(ini, "MRUFile_" + i.ToString());
856             }
857 
858             cnt = fRelations.Count;
859             ini.WriteInteger("Relations", "Count", cnt);
860             for (int i = 0; i < cnt; i++)
861             {
862                 ini.WriteString("Relations", "Relation_" + i.ToString(), fRelations[i]);
863             }
864 
865             fIndividualListColumns.SaveToFile(ini, "PersonsColumns");
866 
867             ini.WriteBool("ListPersons", "HighlightUnmarried", fListHighlightUnmarriedPersons);
868             ini.WriteBool("ListPersons", "HighlightUnparented", fListHighlightUnparentedPersons);
869 
870             //------------------------------------------------------------------
871             // 2016-09-30 Ruslan Garipov <brigadir15@gmail.com>
872             // FIXME: If `Control::Left`, `Control::Top`, `Control::Width` and
873             // `Control::Height` return physical values (device depended), code
874             // here must convert members of `fMWinRect` to logical values
875             // (device independed) before storing it as the application
876             // settings. Had GK been a native Windows application, it had to do
877             // that. But since it's a .NET application I don't know is it a
878             // true. See also implementation of `GKCore::GKUtils::GetFormRect`
879             // member.
880             //------------------------------------------------------------------
881             ini.WriteInteger("Common", "MWinL", fMWinRect.Left);
882             ini.WriteInteger("Common", "MWinT", fMWinRect.Top);
883             ini.WriteInteger("Common", "MWinW", fMWinRect.Right);
884             ini.WriteInteger("Common", "MWinH", fMWinRect.Bottom);
885             ini.WriteInteger("Common", "MWinState", (int)fMWinState);
886 
887             cnt = fLastBases.Count;
888             ini.WriteInteger("LastBases", "Count", cnt);
889             for (int i = 0; i < cnt; i++) {
890                 ini.WriteString("LastBases", "LB" + i.ToString(), fLastBases[i]);
891             }
892 
893             fCircleChartOptions.SaveToFile(ini);
894 
895             fListOptions.SaveToFile(ini);
896 
897             SavePluginsToFile(ini);
898         }
899 
SaveToFile(string fileName)900         public void SaveToFile(string fileName)
901         {
902             if (string.IsNullOrEmpty(fileName))
903                 throw new ArgumentNullException("fileName");
904 
905             try {
906                 IniFile ini = new IniFile(fileName);
907 
908                 try {
909                     SaveToFile(ini);
910                 } finally {
911                     ini.Dispose();
912                 }
913             } catch (Exception ex) {
914                 Logger.WriteError("GlobalOptions.SaveToFile()", ex);
915             }
916         }
917     }
918 }
919