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

HicServices / RDMP / 9251646467

27 May 2024 08:23AM UTC coverage: 56.916% (+0.002%) from 56.914%
9251646467

push

github

web-flow
Marge v8.1.6 into main (#1842)

* bump to net8

* add sqlcli

* Bump Autoupdater.NET.Official from 1.8.4 to 1.8.5

Bumps [Autoupdater.NET.Official](https://github.com/ravibpatel/AutoUpdater.NET) from 1.8.4 to 1.8.5.
- [Release notes](https://github.com/ravibpatel/AutoUpdater.NET/releases)
- [Commits](https://github.com/ravibpatel/AutoUpdater.NET/compare/v1.8.4...v1.8.5)

---
updated-dependencies:
- dependency-name: Autoupdater.NET.Official
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Delete .nuget/packages.config (#1758)

* Delete .nuget/packages.config

Remove  hopefully obsolete package list confusing dependency tracking

* Remove .nuget folder

---------

Co-authored-by: James A Sutherland <>

* Bump svenstaro/upload-release-action from 2.7.0 to 2.9.0 (#1759)

* Bump shogo82148/actions-setup-perl from 1.28.0 to 1.29.0 (#1751)

Bumps [shogo82148/actions-setup-perl](https://github.com/shogo82148/actions-setup-perl) from 1.28.0 to 1.29.0.
- [Release notes](https://github.com/shogo82148/actions-setup-perl/releases)
- [Commits](https://github.com/shogo82148/actions-setup-perl/compare/v1.28.0...v1.29.0)

---
updated-dependencies:
- dependency-name: shogo82148/actions-setup-perl
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: James Friel <jfriel001@dundee.ac.uk>

* Bump CsvHelper from 30.0.3 to 30.1.0 (#1737)

Bumps [CsvHelper](https://github.com/JoshClose/CsvHelper) from 30.0.3 to 30.1.0.
- [Commits](https://github.com/JoshClose/CsvHelper/compare/30.0.3...30.1.0)

---
updated-dependencies:
- dependency-name: CsvHelper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by... (continued)

10836 of 20512 branches covered (52.83%)

Branch coverage included in aggregate %.

46 of 53 new or added lines in 8 files covered. (86.79%)

1 existing line in 1 file now uncovered.

30865 of 52756 relevant lines covered (58.51%)

7396.37 hits per line

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

37.23
/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 FAnsi.Discovery;
12
using Rdmp.Core.ReusableLibraryCode.Checks;
13

14
namespace Rdmp.Core.ReusableLibraryCode.Settings;
15

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

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

30

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

173

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

180

181
    #region Catalogue flag visibility settings
182

183
    public static bool ShowInternalCatalogues
184
    {
185
        get => AppSettings.GetValueOrDefault("ShowInternalCatalogues", true);
40✔
186
        set => AppSettings.AddOrUpdateValue("ShowInternalCatalogues", value);
48✔
187
    }
188

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

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

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

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

213
    /// <summary>
214
    /// True to apply theme changes to context menus and tool strips.
215
    /// </summary>
216
    public static bool ApplyThemeToMenus
217
    {
218
        get => AppSettings.GetValueOrDefault("ApplyThemeToMenus", true);
×
219
        set => AppSettings.AddOrUpdateValue("ApplyThemeToMenus", value);
×
220
    }
221

222
    /// <summary>
223
    /// Determines line wrapping in multi line editor controls when lines stretch off the control client area
224
    /// </summary>
225
    public static int WrapMode
226
    {
227
        get => AppSettings.GetValueOrDefault("WrapMode", 0);
40✔
228
        set => AppSettings.AddOrUpdateValue("WrapMode", value);
×
229
    }
230

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

244
    /// <summary>
245
    /// <para>Adds a 5 second delay after startup</para>
246
    /// <para>Use this option to add a delay that can be helpful for troubleshooting issues on RDMP startup. </para>
247
    /// </summary>
248
    public static bool Wait5SecondsAfterStartupUI
249
    {
250
        get => AppSettings.GetValueOrDefault("Wait5SecondsAfterStartupUI", true);
10✔
251
        set => AppSettings.AddOrUpdateValue("Wait5SecondsAfterStartupUI", value);
12✔
252
    }
253

254
    /// <summary>
255
    /// True to show the cohort creation wizard when creating new cohorts.  False to create
256
    /// a default empty configuration.
257
    /// </summary>
258
    public static bool ShowCohortWizard
259
    {
260
        get => AppSettings.GetValueOrDefault("ShowCohortWizard", false);
×
261
        set => AppSettings.AddOrUpdateValue("ShowCohortWizard", value);
×
262
    }
263

264
    /// <summary>
265
    /// <para>True to enable "stirct validation" for containers in Cohort Builder Queries.</para>
266
    ///
267
    /// <para>Will not allow empty sets, or sets that only have one item.</para>
268
    /// </summary>
269
    public static bool StrictValidationForCohortBuilderContainers
270
    {
271
        get => AppSettings.GetValueOrDefault("StrictValidationForCohortBuilderContainers", true);
38✔
272
        set => AppSettings.AddOrUpdateValue("StrictValidationForCohortBuilderContainers", value);
×
273
    }
274

275
    /// <summary>
276
    /// Changes the behaviour of mouse double clicks in tree views.  When enabled double
277
    /// click expands nodes instead of opening the double clicked object (the default behaviour).
278
    /// </summary>
279
    public static bool DoubleClickToExpand
280
    {
281
        get => AppSettings.GetValueOrDefault("DoubleClickToExpand", false);
×
282
        set => AppSettings.AddOrUpdateValue("DoubleClickToExpand", value);
×
283
    }
284

285
    public static string RecentHistory
286
    {
287
        get => AppSettings.GetValueOrDefault("RecentHistory", "");
60✔
288
        set => AppSettings.AddOrUpdateValue("RecentHistory", value);
18✔
289
    }
290

291
    /// <summary>
292
    /// <para>When enabled RDMP will record certain performance related metrics (how long refresh takes etc).</para>
293
    /// <para>These figures are completely internal to the application and are not transmitted anywhere.You can view the results in the toolbar.</para>
294
    /// </summary>
295
    public static bool DebugPerformance
296
    {
297
        get => AppSettings.GetValueOrDefault("DebugPerformance", false);
30,378✔
298
        set => AppSettings.AddOrUpdateValue("DebugPerformance", value);
×
299
    }
300

301
    /// <summary>
302
    /// <para>Automatically resize columns in the RDMP user interface with fit contents.</para>
303
    /// <para>Can be disabled if problems arrise with column content or header visibility</para>
304
    /// </summary>
305
    public static bool AutoResizeColumns
306
    {
307
        get => AppSettings.GetValueOrDefault("AutoResizeColumns", true);
30✔
308
        set => AppSettings.AddOrUpdateValue("AutoResizeColumns", value);
×
309
    }
310

311

312
    /// <summary>
313
    /// Show a popup confirmation dialog at the end of a pipeline completing execution
314
    /// </summary>
315
    public static bool ShowPipelineCompletedPopup
316
    {
317
        get => AppSettings.GetValueOrDefault("ShowPipelineCompletedPopup", true);
×
318
        set => AppSettings.AddOrUpdateValue("ShowPipelineCompletedPopup", value);
×
319
    }
320

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

331
    public static string ConsoleColorScheme
332
    {
333
        get => AppSettings.GetValueOrDefault("ConsoleColorScheme", "default");
×
334
        set => AppSettings.AddOrUpdateValue("ConsoleColorScheme", value);
×
335
    }
336

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

347
    /// <summary>
348
    /// <para>Enables additional Find filters for objects that are in:</para>
349
    /// <para>Cold Storage, Internal, Deprecated, Project Specific and Non Extractable</para>
350
    /// </summary>
351
    public static bool AdvancedFindFilters
352
    {
353
        get => AppSettings.GetValueOrDefault("AdvancedFindFilters", false);
×
354
        set => AppSettings.AddOrUpdateValue("AdvancedFindFilters", value);
×
355
    }
356

357
    /// <summary>
358
    /// Timeout in seconds to allow for creating archive trigger, index etc
359
    /// </summary>
360
    public static int ArchiveTriggerTimeout
361
    {
362
        get => AppSettings.GetValueOrDefault("ArchiveTriggerTimeout", 30);
1,198✔
363
        set => AppSettings.AddOrUpdateValue("ArchiveTriggerTimeout", value);
×
364
    }
365

366
    public static int FindWindowWidth
367
    {
368
        get => AppSettings.GetValueOrDefault("FindWindowWidth", 730);
×
369
        set => AppSettings.AddOrUpdateValue("FindWindowWidth", value);
×
370
    }
371

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

378
    /// <summary>
379
    /// Enable to refresh only objects which you make changes to instead of
380
    /// fetching all database changes since your last edit.  This improves
381
    /// performance in large RDMP deployments with thousands of Projects configured.
382
    /// </summary>
383
    public static bool SelectiveRefresh
384
    {
385
        get => AppSettings.GetValueOrDefault("SelectiveRefresh", false);
154✔
386
        set => AppSettings.AddOrUpdateValue("SelectiveRefresh", value);
×
387
    }
388

389
    /// <summary>
390
    /// Set to true to always attempt to force joins on all tables under a Catalogue
391
    /// when building queries (in Cohort Builder).  This makes it impossible to untick
392
    /// force joins.
393
    /// </summary>
394
    public static bool AlwaysJoinEverything
395
    {
396
        get => AppSettings.GetValueOrDefault("AlwaysJoinEverything", false);
648✔
397
        set => AppSettings.AddOrUpdateValue("AlwaysJoinEverything", value);
×
398
    }
399

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

414
    /// <summary>
415
    /// Enable to automatically expand the tree when opening or creating cohorts in
416
    /// Cohort Builder
417
    /// </summary>
418
    public static bool ExpandAllInCohortBuilder
419
    {
420
        get => AppSettings.GetValueOrDefault("ExpandAllInCohortBuilder", true);
2✔
421
        set => AppSettings.AddOrUpdateValue("ExpandAllInCohortBuilder", value);
×
422
    }
423

424
    /// <summary>
425
    /// True to show ProjectSpecific Catalogues' columns in extraction configuration user interface
426
    /// </summary>
427
    public static bool ShowProjectSpecificColumns
428
    {
429
        get => AppSettings.GetValueOrDefault("ShowProjectSpecificColumns", true);
18✔
430
        set => AppSettings.AddOrUpdateValue("ShowProjectSpecificColumns", value);
×
431
    }
432

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

447
    #endregion
448

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

459
        return Enum.Parse<CheckResult>(result);
32✔
460
    }
461

462
    /// <summary>
463
    /// Changes the reporting level of the given error to <paramref name="value"/> instead of its <see cref="ErrorCode.DefaultTreatment"/>
464
    /// </summary>
465
    /// <param name="errorCode"></param>
466
    /// <param name="value"></param>
467
    public static void SetErrorReportingLevelFor(ErrorCode errorCode, CheckResult value)
468
    {
469
        AppSettings.AddOrUpdateValue($"EC_{errorCode.Code}", value.ToString());
16✔
470
    }
16✔
471

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

475
    public static void SetTutorialDone(Guid tutorialGuid, bool value)
476
    {
477
        if (tutorialGuid == Guid.Empty)
×
478
            return;
×
479

480
        AppSettings.AddOrUpdateValue($"T_{tutorialGuid:N}", value);
×
481
    }
×
482

483
    public static void SetColumnWidth(Guid columnGuid, int width)
484
    {
485
        if (columnGuid == Guid.Empty)
3,132!
486
            return;
×
487
        SetColumnWidth(columnGuid.ToString("N"), width);
3,132✔
488
    }
3,132✔
489

490
    public static void SetColumnWidth(string colIdentifier, int width)
491
    {
492
        AppSettings.AddOrUpdateValue($"ColW_{colIdentifier}", width);
3,132✔
493
    }
3,132✔
494

495
    public static void SetColumnVisible(Guid columnGuid, bool visible)
496
    {
497
        if (columnGuid == Guid.Empty)
×
498
            return;
×
499

500
        SetColumnVisible(columnGuid.ToString("N"), visible);
×
501
    }
×
502

503
    public static void SetColumnVisible(string colIdentifier, bool visible)
504
    {
505
        AppSettings.AddOrUpdateValue($"ColV_{colIdentifier}", visible);
×
506
    }
×
507

508
    public static int GetColumnWidth(Guid columnGuid) =>
509
        columnGuid == Guid.Empty ? 100 : GetColumnWidth(columnGuid.ToString("N"));
128!
510

511
    public static int GetColumnWidth(string colIdentifier) =>
512
        AppSettings.GetValueOrDefault($"ColW_{colIdentifier}", 100);
128✔
513

514
    public static bool GetColumnVisible(Guid columnGuid) =>
515
        columnGuid == Guid.Empty || GetColumnVisible(columnGuid.ToString("N"));
128!
516

517
    public static bool GetColumnVisible(string colIdentifier) =>
518
        AppSettings.GetValueOrDefault($"ColV_{colIdentifier}", true);
128✔
519

520
    public static string[] GetHistoryForControl(Guid controlGuid)
521
    {
522
        return AppSettings.GetValueOrDefault($"A_{controlGuid:N}", "").Split(new[] { "#!#" }, StringSplitOptions.None);
22✔
523
    }
524

525
    public static void SetHistoryForControl(Guid controlGuid, IEnumerable<string> history)
526
    {
527
        AppSettings.AddOrUpdateValue($"A_{controlGuid:N}", string.Join("#!#", history));
204✔
528
    }
204✔
529

530
    public static void AddHistoryForControl(Guid guid, string v)
531
    {
532
        if (string.IsNullOrWhiteSpace(v))
×
533
            return;
×
534

535
        var l = GetHistoryForControl(guid).ToList();
×
536

537
        if (l.Contains(v))
×
538
            return;
×
539

540
        l.Add(v);
×
541

542
        SetHistoryForControl(guid, l.Distinct().ToList());
×
543
    }
×
544

545
    public static Tuple<string, bool> GetLastColumnSortForCollection(Guid controlGuid)
546
    {
547
        lock (_oLockUserSettings)
2✔
548
        {
549
            var value = AppSettings.GetValueOrDefault($"LastColumnSort_{controlGuid:N}", null);
2✔
550

551
            //if we don't have a value
552
            if (string.IsNullOrWhiteSpace(value))
2!
553
                return null;
2✔
554

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

557
            //or it doesn't split properly
558
            if (args.Length != 2)
×
559
                return null;
×
560

561
            //or either element is null
562
            if (string.IsNullOrWhiteSpace(args[0]) || string.IsNullOrWhiteSpace(args[1]))
×
563
                return null;
×
564

565
            if (bool.TryParse(args[1], out var ascending))
×
566
                return Tuple.Create(args[0], ascending);
×
567
        }
×
568

569
        return null;
×
570
    }
2✔
571

572
    private static object _oLockUserSettings = new();
4✔
573

574
    public static void SetLastColumnSortForCollection(Guid controlGuid, string columnName, bool ascending)
575
    {
576
        lock (_oLockUserSettings)
2✔
577
        {
578
            AppSettings.AddOrUpdateValue($"LastColumnSort_{controlGuid:N}", $"{columnName}#!#{ascending}");
2✔
579
        }
2✔
580
    }
2✔
581

582

583
    /// <summary>
584
    /// Returns the last known manually set splitter distance for the Control who is
585
    /// identified by <paramref name="controlGuid"/> or -1 if none set yet
586
    /// </summary>
587
    /// <param name="controlGuid"></param>
588
    /// <returns></returns>
589
    public static int GetSplitterDistance(Guid controlGuid) =>
590
        AppSettings.GetValueOrDefault($"SplitterDistance_{controlGuid:N}", -1);
×
591

592
    /// <summary>
593
    /// Records that the user has manaully changed the splitter distance of the Control
594
    /// who is identified by <paramref name="controlGuid"/>
595
    /// </summary>
596
    /// <param name="controlGuid"></param>
597
    /// <param name="splitterDistance"></param>
598
    public static void SetSplitterDistance(Guid controlGuid, int splitterDistance)
599
    {
600
        lock (_oLockUserSettings)
×
601
        {
602
            AppSettings.AddOrUpdateValue($"SplitterDistance_{controlGuid:N}", splitterDistance);
×
603
        }
×
604
    }
×
605

606
    public static void ClearUserSettings()
607
    {
608
        AppSettings.Clear();
2✔
609
    }
2✔
610
}
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