• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

HicServices / RDMP / 13318089130

13 Feb 2025 10:13PM UTC coverage: 57.398% (+0.004%) from 57.394%
13318089130

Pull #2134

github

jas88
Update ChildProviderTests.cs

Fix up TestUpTo method
Pull Request #2134: CodeQL fixups

11346 of 21308 branches covered (53.25%)

Branch coverage included in aggregate %.

104 of 175 new or added lines in 45 files covered. (59.43%)

362 existing lines in 23 files now uncovered.

32218 of 54590 relevant lines covered (59.02%)

17091.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

36.84
/Rdmp.Core/ReusableLibraryCode/Settings/UserSettings.cs
1
// Copyright (c) The University of Dundee 2018-2024
2
// This file is part of the Research Data Management Platform (RDMP).
3
// RDMP 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.
4
// RDMP 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.
5
// You should have received a copy of the GNU General Public License along with RDMP. If not, see <https://www.gnu.org/licenses/>.
6

7
using System;
8
using System.Collections.Generic;
9
using System.IO;
10
using System.Linq;
11
using System.Threading;
12
using FAnsi.Discovery;
13
using Rdmp.Core.ReusableLibraryCode.Checks;
14

15
namespace Rdmp.Core.ReusableLibraryCode.Settings;
16

17
/// <summary>
18
/// This is the Settings static class that can be used in your Core solution or in any
19
/// of your client applications. All settings are laid out the same exact way with getters
20
/// and setters.
21
/// </summary>
22
public static class UserSettings
23
{
24
    private static readonly Lazy<RDMPApplicationSettings> Implementation =
4✔
25
        new(static () => new RDMPApplicationSettings(), System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);
8✔
26

27
    private static RDMPApplicationSettings AppSettings => Implementation.Value ??
48,528!
28
                                                          throw new NotImplementedException(
48,528✔
29
                                                              "Isolated Storage does not work in this environment...");
48,528✔
30

31

32
    public static bool UseLocalFileSystem
33
    {
34
        get => AppSettings.GetValueOrDefault("UseLocalFileSystem", false);
×
35
        set => AppSettings.AddOrUpdateValue("UseLocalFileSystem", value);
×
36
    }
37

38
    public static string LocalFileSystemLocation 
39
    {
40
        get => AppSettings.GetValueOrDefault("LocalFileSystemLocation", Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "rdmp")); 
×
41
        set => AppSettings.AddOrUpdateValue("LocalFileSystemLocation", value);
×
42
    }
43

44
    /// <summary>
45
    /// Show a Yes/No confirmation dialog box when closing RDMP
46
    /// </summary>
47
    public static bool ConfirmApplicationExiting
48
    {
49
        get => AppSettings.GetValueOrDefault("ConfirmExit", true);
×
50
        set => AppSettings.AddOrUpdateValue("ConfirmExit", value);
×
51
    }
52

53
    /// <summary>
54
    /// True if the user has accepted the open source license agreements for RDMP and
55
    /// dependencies used in the software (i.e. MIT and GNU licenses).
56
    /// </summary>
57
    public static string LicenseAccepted
58
    {
59
        get => AppSettings.GetValueOrDefault("LicenseAccepted", null);
×
60
        set => AppSettings.AddOrUpdateValue("LicenseAccepted", value);
×
61
    }
62

63
    /// <summary>
64
    /// Automatically launch the RDMP Home Screen on launch of the RDMP application, regardless of the last window you viewed.
65
    /// </summary>
66
    public static bool ShowHomeOnStartup
67
    {
68
        get => AppSettings.GetValueOrDefault("ShowHomeOnStartup", false);
×
69
        set => AppSettings.AddOrUpdateValue("ShowHomeOnStartup", value);
×
70
    }
71

72
    /// <summary>
73
    /// If checked series included in graphs that have no values will not be displayed
74
    /// </summary>
75
    public static bool IncludeZeroSeriesInGraphs
76
    {
77
        get => AppSettings.GetValueOrDefault("IncludeZeroSeriesInGraphs", true);
4✔
78
        set => AppSettings.AddOrUpdateValue("IncludeZeroSeriesInGraphs", value);
6✔
79
    }
80

81
    /// <summary>
82
    /// Adds an additional behaviour when changing tabs that highlights the tree view
83
    /// collection that has that object visible in it.
84
    /// </summary>
85
    public static bool EmphasiseOnTabChanged
86
    {
87
        get => AppSettings.GetValueOrDefault("EmphasiseOnTabChanged", false);
×
88
        set => AppSettings.AddOrUpdateValue("EmphasiseOnTabChanged", value);
×
89
    }
90

91
    /// <summary>
92
    /// True to disable any auto starting tutorials
93
    /// </summary>
94
    public static bool DisableTutorials
95
    {
96
        get => AppSettings.GetValueOrDefault("DisableTutorials", false);
×
97
        set => AppSettings.AddOrUpdateValue("DisableTutorials", value);
×
98
    }
99

100
    /// <summary>
101
    /// The connection string to the main RDMP platform database
102
    /// </summary>
103
    public static string CatalogueConnectionString
104
    {
105
        get => AppSettings.GetValueOrDefault("CatalogueConnectionString", "");
×
106
        set => AppSettings.AddOrUpdateValue("CatalogueConnectionString", value);
×
107
    }
108

109
    /// <summary>
110
    /// The connection string to the data export RDMP platform database.  This database will contain
111
    /// references to objects in the <see cref="CatalogueConnectionString"/> database
112
    /// </summary>
113
    public static string DataExportConnectionString
114
    {
115
        get => AppSettings.GetValueOrDefault("DataExportConnectionString", "");
×
116
        set => AppSettings.AddOrUpdateValue("DataExportConnectionString", value);
×
117
    }
118

119
    /// <summary>
120
    /// The colour scheme and format for the RDMP gui client application
121
    /// </summary>
122
    public static string Theme
123
    {
124
        get => AppSettings.GetValueOrDefault("Theme", "ResearchDataManagementPlatform.Theme.MyVS2015BlueTheme");
×
125
        set => AppSettings.AddOrUpdateValue("Theme", value);
×
126
    }
127

128
    /// <summary>
129
    /// When selecting a result from the Find dialog the selected item is pinned in the corresponding view.
130
    /// </summary>
131
    public static bool FindShouldPin
132
    {
133
        get => AppSettings.GetValueOrDefault("FindShouldPin", true);
×
134
        set => AppSettings.AddOrUpdateValue("FindShouldPin", value);
×
135
    }
136

137
    /// <summary>
138
    /// Set the amount of time (in seconds) that the Create Database processes should wait before timing out.
139
    /// </summary>
140
    public static int CreateDatabaseTimeout
141
    {
142
        get => AppSettings.GetValueOrDefault("CreateDatabaseTimeout", 30);
16✔
143
        set => AppSettings.AddOrUpdateValue("CreateDatabaseTimeout",
×
144
            DiscoveredServerHelper.CreateDatabaseTimeoutInSeconds = Math.Max(value, 30));
×
145
    }
146

147
    /// <summary>
148
    /// Set the amount of time (in milliseconds) that tooltips should take to appear in the tree collection views (e.g. list of Catalogues etc)
149
    /// </summary>
150
    public static int TooltipAppearDelay
151
    {
152
        get => AppSettings.GetValueOrDefault("TooltipAppearDelay", 750);
20✔
153
        set => AppSettings.AddOrUpdateValue("TooltipAppearDelay", Math.Max(10, value));
×
154
    }
155

156
    /// <summary>
157
    /// When using the Find feature this option will automatically filter out any cohort set containers (i.e. UNION / INTERSECT / EXCEPT containers)
158
    /// </summary>
159
    public static bool ScoreZeroForCohortAggregateContainers
160
    {
161
        get => AppSettings.GetValueOrDefault("ScoreZeroForCohortAggregateContainers", false);
50✔
162
        set => AppSettings.AddOrUpdateValue("ScoreZeroForCohortAggregateContainers", value);
8✔
163
    }
164

165
    /// <summary>
166
    /// Create audit objects for specific objects/changes (e.g. changes to Catalogue Deprecated status).
167
    /// </summary>
168
    public static bool EnableCommits
169
    {
170
        get => AppSettings.GetValueOrDefault("EnableCommits", true);
26✔
171
        set => AppSettings.AddOrUpdateValue("EnableCommits", value);
×
172
    }
173

174

175
    public static bool PromptRenameOnCohortFilterChange
176
    {
177
        get => AppSettings.GetValueOrDefault("PromptRenameOnCohortFilterChange", true);
×
178
        set => AppSettings.AddOrUpdateValue("PromptRenameOnCohortFilterChange", value);
×
179
    }
180

181
    public static bool NewFindAndReplace
182
    {
183
        get => AppSettings.GetValueOrDefault("NewFindAndReplace", false);
×
184
        set => AppSettings.AddOrUpdateValue("NewFindAndReplace", value);
×
185
    }
186

187

188
    #region Catalogue flag visibility settings
189

190
    public static bool ShowInternalCatalogues
191
    {
192
        get => AppSettings.GetValueOrDefault("ShowInternalCatalogues", true);
40✔
193
        set => AppSettings.AddOrUpdateValue("ShowInternalCatalogues", value);
48✔
194
    }
195

196
    public static bool ShowDeprecatedCatalogues
197
    {
198
        get => AppSettings.GetValueOrDefault("ShowDeprecatedCatalogues", true);
40✔
199
        set => AppSettings.AddOrUpdateValue("ShowDeprecatedCatalogues", value);
48✔
200
    }
201

202
    public static bool ShowColdStorageCatalogues
203
    {
204
        get => AppSettings.GetValueOrDefault("ShowColdStorageCatalogues", true);
40✔
205
        set => AppSettings.AddOrUpdateValue("ShowColdStorageCatalogues", value);
48✔
206
    }
207

208
    public static bool ShowProjectSpecificCatalogues
209
    {
210
        get => AppSettings.GetValueOrDefault("ShowProjectSpecificCatalogues", true);
40✔
211
        set => AppSettings.AddOrUpdateValue("ShowProjectSpecificCatalogues", value);
48✔
212
    }
213

214
    public static bool ShowNonExtractableCatalogues
215
    {
216
        get => AppSettings.GetValueOrDefault("ShowNonExtractableCatalogues", true);
40✔
217
        set => AppSettings.AddOrUpdateValue("ShowNonExtractableCatalogues", value);
48✔
218
    }
219

220
    /// <summary>
221
    /// True to apply theme changes to context menus and tool strips.
222
    /// </summary>
223
    public static bool ApplyThemeToMenus
224
    {
225
        get => AppSettings.GetValueOrDefault("ApplyThemeToMenus", true);
×
226
        set => AppSettings.AddOrUpdateValue("ApplyThemeToMenus", value);
×
227
    }
228

229
    /// <summary>
230
    /// Determines line wrapping in multi line editor controls when lines stretch off the control client area
231
    /// </summary>
232
    public static int WrapMode
233
    {
234
        get => AppSettings.GetValueOrDefault("WrapMode", 0);
40✔
235
        set => AppSettings.AddOrUpdateValue("WrapMode", value);
×
236
    }
237

238
    /// <summary>
239
    /// <para>Base colours used for generating heatmaps in HEX format.  Colour intensity will vary
240
    /// from the first color to the second.</para>
241
    /// 
242
    /// <para>The first colour represents the lowest values and should
243
    /// typically be darker than the second which represents high values.</para>
244
    /// </summary>
245
    public static string HeatMapColours
246
    {
247
        get => AppSettings.GetValueOrDefault("HeatMapColours", null);
×
248
        set => AppSettings.AddOrUpdateValue("HeatMapColours", value);
×
249
    }
250

251
    /// <summary>
252
    /// <para>Adds a 5 second delay after startup</para>
253
    /// <para>Use this option to add a delay that can be helpful for troubleshooting issues on RDMP startup. </para>
254
    /// </summary>
255
    public static bool Wait5SecondsAfterStartupUI
256
    {
257
        get => AppSettings.GetValueOrDefault("Wait5SecondsAfterStartupUI", true);
10✔
258
        set => AppSettings.AddOrUpdateValue("Wait5SecondsAfterStartupUI", value);
12✔
259
    }
260

261
    /// <summary>
262
    /// True to show the cohort creation wizard when creating new cohorts.  False to create
263
    /// a default empty configuration.
264
    /// </summary>
265
    public static bool ShowCohortWizard
266
    {
267
        get => AppSettings.GetValueOrDefault("ShowCohortWizard", false);
×
268
        set => AppSettings.AddOrUpdateValue("ShowCohortWizard", value);
×
269
    }
270

271
    /// <summary>
272
    /// <para>True to enable "stirct validation" for containers in Cohort Builder Queries.</para>
273
    ///
274
    /// <para>Will not allow empty sets, or sets that only have one item.</para>
275
    /// </summary>
276
    public static bool StrictValidationForCohortBuilderContainers
277
    {
278
        get => AppSettings.GetValueOrDefault("StrictValidationForCohortBuilderContainers", true);
38✔
279
        set => AppSettings.AddOrUpdateValue("StrictValidationForCohortBuilderContainers", value);
×
280
    }
281

282
    /// <summary>
283
    /// Changes the behaviour of mouse double clicks in tree views.  When enabled double
284
    /// click expands nodes instead of opening the double clicked object (the default behaviour).
285
    /// </summary>
286
    public static bool DoubleClickToExpand
287
    {
288
        get => AppSettings.GetValueOrDefault("DoubleClickToExpand", false);
×
289
        set => AppSettings.AddOrUpdateValue("DoubleClickToExpand", value);
×
290
    }
291

292
    public static string RecentHistory
293
    {
294
        get => AppSettings.GetValueOrDefault("RecentHistory", "");
60✔
295
        set => AppSettings.AddOrUpdateValue("RecentHistory", value);
18✔
296
    }
297

298
    /// <summary>
299
    /// <para>When enabled RDMP will record certain performance related metrics (how long refresh takes etc).</para>
300
    /// <para>These figures are completely internal to the application and are not transmitted anywhere.You can view the results in the toolbar.</para>
301
    /// </summary>
302
    public static bool DebugPerformance
303
    {
304
        get => AppSettings.GetValueOrDefault("DebugPerformance", false);
41,474✔
305
        set => AppSettings.AddOrUpdateValue("DebugPerformance", value);
×
306
    }
307

308
    /// <summary>
309
    /// <para>Automatically resize columns in the RDMP user interface with fit contents.</para>
310
    /// <para>Can be disabled if problems arise with column content or header visibility</para>
311
    /// </summary>
312
    public static bool AutoResizeColumns
313
    {
314
        get => AppSettings.GetValueOrDefault("AutoResizeColumns", true);
30✔
315
        set => AppSettings.AddOrUpdateValue("AutoResizeColumns", value);
×
316
    }
317

318

319
    /// <summary>
320
    /// Show a popup confirmation dialog at the end of a pipeline completing execution
321
    /// </summary>
322
    public static bool ShowPipelineCompletedPopup
323
    {
324
        get => AppSettings.GetValueOrDefault("ShowPipelineCompletedPopup", true);
×
325
        set => AppSettings.AddOrUpdateValue("ShowPipelineCompletedPopup", value);
×
326
    }
327

328
    /// <summary>
329
    /// <para>Enable to skip the checking stage of pipeline source component CohortIdentificationConfigurationSource.</para>
330
    /// <para>In slow computer, or contesest databases this can take a while to compile. This option lets you disable it.</para>
331
    /// </summary>
332
    public static bool SkipCohortBuilderValidationOnCommit
333
    {
334
        get => AppSettings.GetValueOrDefault("SkipCohortBuilderValidationOnCommit", false);
×
335
        set => AppSettings.AddOrUpdateValue("SkipCohortBuilderValidationOnCommit", value);
×
336
    }
337

338
    public static string ConsoleColorScheme
339
    {
340
        get => AppSettings.GetValueOrDefault("ConsoleColorScheme", "default");
×
341
        set => AppSettings.AddOrUpdateValue("ConsoleColorScheme", value);
×
342
    }
343

344
    /// <summary>
345
    /// <para>When true RDMP log viewer will hide table load audits where no inserts/updates/deletes were applied.</para>
346
    /// <para>This is helpful if a load targets many tables not all of which will be updated in a given run</para>
347
    /// </summary>
348
    public static bool HideEmptyTableLoadRunAudits
349
    {
350
        get => AppSettings.GetValueOrDefault("HideEmptyTableLoadRunAudits", false);
×
351
        set => AppSettings.AddOrUpdateValue("HideEmptyTableLoadRunAudits", value);
×
352
    }
353

354
    /// <summary>
355
    /// <para>Enables additional Find filters for objects that are in:</para>
356
    /// <para>Cold Storage, Internal, Deprecated, Project Specific and Non Extractable</para>
357
    /// </summary>
358
    public static bool AdvancedFindFilters
359
    {
360
        get => AppSettings.GetValueOrDefault("AdvancedFindFilters", false);
×
361
        set => AppSettings.AddOrUpdateValue("AdvancedFindFilters", value);
×
362
    }
363

364
    /// <summary>
365
    /// Timeout in seconds to allow for creating archive trigger, index etc
366
    /// </summary>
367
    public static int ArchiveTriggerTimeout
368
    {
369
        get => AppSettings.GetValueOrDefault("ArchiveTriggerTimeout", 30);
1,380✔
370
        set => AppSettings.AddOrUpdateValue("ArchiveTriggerTimeout", value);
×
371
    }
372

373
    public static int FindWindowWidth
374
    {
375
        get => AppSettings.GetValueOrDefault("FindWindowWidth", 730);
×
376
        set => AppSettings.AddOrUpdateValue("FindWindowWidth", value);
×
377
    }
378

379
    public static int FindWindowHeight
380
    {
381
        get => AppSettings.GetValueOrDefault("FindWindowHeight", 400);
×
382
        set => AppSettings.AddOrUpdateValue("FindWindowHeight", value);
×
383
    }
384

385
    /// <summary>
386
    /// Enable to refresh only objects which you make changes to instead of
387
    /// fetching all database changes since your last edit.  This improves
388
    /// performance in large RDMP deployments with thousands of Projects configured.
389
    /// </summary>
390
    public static bool SelectiveRefresh
391
    {
392
        get => AppSettings.GetValueOrDefault("SelectiveRefresh", false);
232✔
393
        set => AppSettings.AddOrUpdateValue("SelectiveRefresh", value);
×
394
    }
395

396
    /// <summary>
397
    /// Set to true to always attempt to force joins on all tables under a Catalogue
398
    /// when building queries (in Cohort Builder).  This makes it impossible to untick
399
    /// force joins.
400
    /// </summary>
401
    public static bool AlwaysJoinEverything
402
    {
403
        get => AppSettings.GetValueOrDefault("AlwaysJoinEverything", false);
676✔
404
        set => AppSettings.AddOrUpdateValue("AlwaysJoinEverything", value);
×
405
    }
406

407
    /// <summary>
408
    /// <para>
409
    /// Determines whether queries are automatically sent and results displayed in
410
    /// data tabs in RDMP (e.g. View top 100 etc).  Enable to automatically send the
411
    /// queries.  Disable to show the SQL but require the user to press F5 or click Run
412
    /// to execute.
413
    /// </para>
414
    /// </summary>
415
    public static bool AutoRunSqlQueries
416
    {
417
        get => AppSettings.GetValueOrDefault("AutoRunSqlQueries", false);
×
418
        set => AppSettings.AddOrUpdateValue("AutoRunSqlQueries", value);
×
419
    }
420

421
    /// <summary>
422
    /// Enable to automatically expand the tree when opening or creating cohorts in
423
    /// Cohort Builder
424
    /// </summary>
425
    public static bool ExpandAllInCohortBuilder
426
    {
427
        get => AppSettings.GetValueOrDefault("ExpandAllInCohortBuilder", true);
2✔
428
        set => AppSettings.AddOrUpdateValue("ExpandAllInCohortBuilder", value);
×
429
    }
430

431
    /// <summary>
432
    /// True to show ProjectSpecific Catalogues' columns in extraction configuration user interface
433
    /// </summary>
434
    public static bool ShowProjectSpecificColumns
435
    {
436
        get => AppSettings.GetValueOrDefault("ShowProjectSpecificColumns", true);
18✔
437
        set => AppSettings.AddOrUpdateValue("ShowProjectSpecificColumns", value);
×
438
    }
439

440
    /// <summary>
441
    /// <para>When generating an aggregate graph, use the column alias instead of the select sql.  For example
442
    /// when you have the select column 'SELECT YEAR(dt) as myYear' then the GROUP BY will default to
443
    /// 'GROUP BY YEAR(dt)'.  Setting this property to true will instead use 'GROUP BY myYear'.  Typically
444
    /// this only works in MySql but it is not universally supported by all MySql versions and server settings
445
    /// </para>
446
    /// <para>Defaults to false.</para>
447
    /// </summary>
448
    public static bool UseAliasInsteadOfTransformInGroupByAggregateGraphs
449
    {
450
        get => AppSettings.GetValueOrDefault("ShowProjectSpecificColumns", false);
292✔
451
        set => AppSettings.AddOrUpdateValue("ShowProjectSpecificColumns", value);
8✔
452
    }
453

454
    #endregion
455

456
    /// <summary>
457
    /// Returns the error level the user wants for <paramref name="errorCode"/> or <see cref="ErrorCode.DefaultTreatment"/> (if no custom
458
    /// reporting level has been set up for this error code).
459
    /// </summary>
460
    /// <param name="errorCode"></param>
461
    /// <returns></returns>
462
    public static CheckResult GetErrorReportingLevelFor(ErrorCode errorCode)
463
    {
464
        var result = AppSettings.GetValueOrDefault($"EC_{errorCode.Code}", errorCode.DefaultTreatment.ToString());
32✔
465

466
        return Enum.Parse<CheckResult>(result);
32✔
467
    }
468

469
    /// <summary>
470
    /// Changes the reporting level of the given error to <paramref name="value"/> instead of its <see cref="ErrorCode.DefaultTreatment"/>
471
    /// </summary>
472
    /// <param name="errorCode"></param>
473
    /// <param name="value"></param>
474
    public static void SetErrorReportingLevelFor(ErrorCode errorCode, CheckResult value)
475
    {
476
        AppSettings.AddOrUpdateValue($"EC_{errorCode.Code}", value.ToString());
16✔
477
    }
16✔
478

479
    public static bool GetTutorialDone(Guid tutorialGuid) =>
480
        tutorialGuid != Guid.Empty && AppSettings.GetValueOrDefault($"T_{tutorialGuid:N}", false);
×
481

482
    public static void SetTutorialDone(Guid tutorialGuid, bool value)
483
    {
484
        if (tutorialGuid == Guid.Empty)
×
485
            return;
×
486

487
        AppSettings.AddOrUpdateValue($"T_{tutorialGuid:N}", value);
×
488
    }
×
489

490
    public static void SetColumnWidth(Guid columnGuid, int width)
491
    {
492
        if (columnGuid == Guid.Empty)
3,132!
493
            return;
×
494
        SetColumnWidth(columnGuid.ToString("N"), width);
3,132✔
495
    }
3,132✔
496

497
    public static void SetColumnWidth(string colIdentifier, int width)
498
    {
499
        AppSettings.AddOrUpdateValue($"ColW_{colIdentifier}", width);
3,132✔
500
    }
3,132✔
501

502
    public static void SetColumnVisible(Guid columnGuid, bool visible)
503
    {
504
        if (columnGuid == Guid.Empty)
×
505
            return;
×
506

507
        SetColumnVisible(columnGuid.ToString("N"), visible);
×
508
    }
×
509

510
    public static void SetColumnVisible(string colIdentifier, bool visible)
511
    {
512
        AppSettings.AddOrUpdateValue($"ColV_{colIdentifier}", visible);
×
513
    }
×
514

515
    public static int GetColumnWidth(Guid columnGuid) =>
516
        columnGuid == Guid.Empty ? 100 : GetColumnWidth(columnGuid.ToString("N"));
128!
517

518
    public static int GetColumnWidth(string colIdentifier) =>
519
        AppSettings.GetValueOrDefault($"ColW_{colIdentifier}", 100);
128✔
520

521
    public static bool GetColumnVisible(Guid columnGuid) =>
522
        columnGuid == Guid.Empty || GetColumnVisible(columnGuid.ToString("N"));
128!
523

524
    public static bool GetColumnVisible(string colIdentifier) =>
525
        AppSettings.GetValueOrDefault($"ColV_{colIdentifier}", true);
128✔
526

527
    public static string[] GetHistoryForControl(Guid controlGuid)
528
    {
529
        return AppSettings.GetValueOrDefault($"A_{controlGuid:N}", "").Split(new[] { "#!#" }, StringSplitOptions.None);
22✔
530
    }
531

532
    public static void SetHistoryForControl(Guid controlGuid, IEnumerable<string> history)
533
    {
534
        AppSettings.AddOrUpdateValue($"A_{controlGuid:N}", string.Join("#!#", history));
204✔
535
    }
204✔
536

537
    public static void AddHistoryForControl(Guid guid, string v)
538
    {
539
        if (string.IsNullOrWhiteSpace(v))
×
540
            return;
×
541

542
        var l = GetHistoryForControl(guid).ToList();
×
543

544
        if (l.Contains(v))
×
545
            return;
×
546

547
        l.Add(v);
×
548

549
        SetHistoryForControl(guid, l.Distinct().ToList());
×
550
    }
×
551

552
    public static Tuple<string, bool> GetLastColumnSortForCollection(Guid controlGuid)
553
    {
2✔
554
        lock (OLockUserSettings)
555
        {
556
            var value = AppSettings.GetValueOrDefault($"LastColumnSort_{controlGuid:N}", null);
2✔
557

558
            //if we don't have a value
559
            if (string.IsNullOrWhiteSpace(value))
2!
560
                return null;
2✔
561

562
            var args = value.Split(new[] { "#!#" }, StringSplitOptions.RemoveEmptyEntries);
×
563

564
            //or it doesn't split properly
565
            if (args.Length != 2)
×
566
                return null;
×
567

568
            //or either element is null
569
            if (string.IsNullOrWhiteSpace(args[0]) || string.IsNullOrWhiteSpace(args[1]))
×
570
                return null;
×
571

572
            if (bool.TryParse(args[1], out var ascending))
×
573
                return Tuple.Create(args[0], ascending);
×
574
        }
×
575

576
        return null;
×
577
    }
2✔
578

579
    private static readonly Lock OLockUserSettings = new();
4✔
580

581
    public static void SetLastColumnSortForCollection(Guid controlGuid, string columnName, bool ascending)
582
    {
2✔
583
        lock (OLockUserSettings)
584
        {
585
            AppSettings.AddOrUpdateValue($"LastColumnSort_{controlGuid:N}", $"{columnName}#!#{ascending}");
2✔
586
        }
2✔
587
    }
2✔
588

589

590
    /// <summary>
591
    /// Returns the last known manually set splitter distance for the Control who is
592
    /// identified by <paramref name="controlGuid"/> or -1 if none set yet
593
    /// </summary>
594
    /// <param name="controlGuid"></param>
595
    /// <returns></returns>
596
    public static int GetSplitterDistance(Guid controlGuid) =>
597
        AppSettings.GetValueOrDefault($"SplitterDistance_{controlGuid:N}", -1);
×
598

599
    /// <summary>
600
    /// Records that the user has manually changed the splitter distance of the Control
601
    /// who is identified by <paramref name="controlGuid"/>
602
    /// </summary>
603
    /// <param name="controlGuid"></param>
604
    /// <param name="splitterDistance"></param>
605
    public static void SetSplitterDistance(Guid controlGuid, int splitterDistance)
UNCOV
606
    {
×
607
        lock (OLockUserSettings)
608
        {
609
            AppSettings.AddOrUpdateValue($"SplitterDistance_{controlGuid:N}", splitterDistance);
×
610
        }
×
611
    }
×
612

613
    public static void ClearUserSettings()
614
    {
615
        AppSettings.Clear();
2✔
616
    }
2✔
617
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc