Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Source/NETworkManager.Controls/GroupExpandedChangedArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;

namespace NETworkManager.Controls
{
public class GroupExpandedChangedArgs(string groupName, bool isExpanded) : EventArgs
{
public string GroupName { get; } = groupName;
public bool IsExpanded { get; } = isExpanded;
}
}
2 changes: 1 addition & 1 deletion Source/NETworkManager.Controls/GroupExpander.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class GroupExpander : Expander
{
public static readonly DependencyProperty StateStoreProperty =
DependencyProperty.Register(
"StateStore",
nameof(StateStore),
typeof(GroupExpanderStateStore),
typeof(GroupExpander),
new PropertyMetadata(null, OnStateStoreChanged));
Expand Down
26 changes: 25 additions & 1 deletion Source/NETworkManager.Controls/GroupExpanderStateStore.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;

Expand All @@ -8,6 +9,11 @@ public class GroupExpanderStateStore : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

/// <summary>
/// Occurs when a single group's expansion state changes via the indexer (not raised by <see cref="LoadState"/>).
/// </summary>
public event EventHandler<GroupExpandedChangedArgs> GroupExpandedChanged;

protected void OnPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

Expand Down Expand Up @@ -40,7 +46,25 @@ public bool this[string groupName]

_states[groupName] = value;
OnPropertyChanged($"Item[{groupName}]");
GroupExpandedChanged?.Invoke(this, new GroupExpandedChangedArgs(groupName, value));
}
}

/// <summary>
/// Replaces all stored states with the given ones (e.g. bulk-loading previously persisted state).
/// Does not raise <see cref="PropertyChanged"/> or <see cref="GroupExpandedChanged"/> - consumers
/// (e.g. <see cref="GroupExpander"/>) read the current state fresh whenever they bind, so no
/// notification is needed, and this avoids a load-triggers-save feedback loop.
/// </summary>
public void LoadState(IReadOnlyDictionary<string, bool> state)
{
_states.Clear();

if (state == null)
return;

foreach (var kvp in state)
_states[kvp.Key] = kvp.Value;
}
}
}
7 changes: 0 additions & 7 deletions Source/NETworkManager.Profiles/ProfileInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,6 @@ public ProfileInfo(ProfileInfo profile)
SNMP_PrivacyProvider = profile.SNMP_PrivacyProvider;
SNMP_Priv = profile.SNMP_Priv;

// Firewall
Firewall_Enabled = profile.Firewall_Enabled;
//Firewall_Rules = profile.Firewall_Rules;

// Wake on LAN
WakeOnLAN_Enabled = profile.WakeOnLAN_Enabled;
WakeOnLAN_MACAddress = profile.WakeOnLAN_MACAddress;
Expand Down Expand Up @@ -486,9 +482,6 @@ public ProfileInfo(ProfileInfo profile)
public SNMPV3PrivacyProvider SNMP_PrivacyProvider { get; set; } = GlobalStaticConfiguration.SNMP_PrivacyProvider;
[XmlIgnore] public SecureString SNMP_Priv { get; set; }

public bool Firewall_Enabled { get; set; }
//public List<FirewallRule> Firewall_Rules { get; set; }

public bool WakeOnLAN_Enabled { get; set; }
public string WakeOnLAN_MACAddress { get; set; }
public string WakeOnLAN_Broadcast { get; set; }
Expand Down
80 changes: 80 additions & 0 deletions Source/NETworkManager.Profiles/ProfileManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,8 @@ public static void RenameProfileFile(ProfileFileInfo profileFileInfo, string new
File.Copy(profileFileInfo.Path, newProfileFileInfo.Path);
ProfileFiles.Add(newProfileFileInfo);

MigrateGroupExpandState(profileFileInfo.Path, newProfileFileInfo.Path);

// Switch profile, if it was previously loaded
if (switchProfile)
{
Expand All @@ -407,6 +409,8 @@ public static void DeleteProfileFile(ProfileFileInfo profileFileInfo)
if (LoadedProfileFile != null && LoadedProfileFile.Equals(profileFileInfo))
LoadedProfileFileChanged(ProfileFiles.FirstOrDefault(x => !x.Equals(profileFileInfo)));

RemoveGroupExpandState(profileFileInfo.Path);

File.Delete(profileFileInfo.Path);
ProfileFiles.Remove(profileFileInfo);
}
Expand Down Expand Up @@ -478,6 +482,8 @@ public static void EnableEncryption(ProfileFileInfo profileFileInfo, SecureStrin
// Add the new profile
ProfileFiles.Add(newProfileFileInfo);

MigrateGroupExpandState(profileFileInfo.Path, newProfileFileInfo.Path);

// Switch profile, if it was previously loaded
if (switchProfile)
{
Expand Down Expand Up @@ -563,6 +569,8 @@ public static void ChangeMasterPassword(ProfileFileInfo profileFileInfo, SecureS
// Add the new profile
ProfileFiles.Add(newProfileFileInfo);

MigrateGroupExpandState(profileFileInfo.Path, newProfileFileInfo.Path);

// Switch profile, if it was previously loaded
if (switchProfile)
{
Expand Down Expand Up @@ -632,6 +640,8 @@ public static void DisableEncryption(ProfileFileInfo profileFileInfo, SecureStri
// Add the new profile
ProfileFiles.Add(newProfileFileInfo);

MigrateGroupExpandState(profileFileInfo.Path, newProfileFileInfo.Path);

// Switch profile, if it was previously loaded
if (switchProfile)
{
Expand Down Expand Up @@ -739,6 +749,8 @@ private static void Load(ProfileFileInfo profileFileInfo)
// Add the new profile
ProfileFiles.Add(newProfileFileInfo);

MigrateGroupExpandState(profileFileInfo.Path, newProfileFileInfo.Path);

// Switch profile
Log.Info($"Switching to migrated profile file: {newProfileFileInfo.Path}.");
Switch(newProfileFileInfo, false);
Expand Down Expand Up @@ -849,6 +861,70 @@ public static void Switch(ProfileFileInfo info, bool saveLoadedProfiles = true)

#endregion

#region Group expand state persistence

/// <summary>
/// Moves the persisted group-expand state (see <see cref="SettingsInfo.Profiles_GroupExpandState" />)
/// from the old to the new profile file path. No-op if the paths are equal or there is no state for
/// the old path.
/// </summary>
private static void MigrateGroupExpandState(string oldPath, string newPath)
{
if (oldPath == newPath)
return;

if (SettingsManager.Current.Profiles_GroupExpandState.Remove(oldPath, out var state))
{
SettingsManager.Current.Profiles_GroupExpandState[newPath] = state;
SettingsManager.Current.SettingsChanged = true;
}
}

/// <summary>
/// Removes the persisted group-expand state for a profile file that no longer exists.
/// </summary>
private static void RemoveGroupExpandState(string path)
{
if (SettingsManager.Current.Profiles_GroupExpandState.Remove(path))
SettingsManager.Current.SettingsChanged = true;
}

/// <summary>
/// Renames the group key inside the persisted group-expand state for the currently loaded profile file.
/// </summary>
private static void MigrateGroupExpandStateKey(string oldGroupName, string newGroupName)
{
if (oldGroupName == newGroupName)
return;

if (LoadedProfileFile == null)
return;

if (!SettingsManager.Current.Profiles_GroupExpandState.TryGetValue(LoadedProfileFile.Path, out var state))
return;

if (!state.Remove(oldGroupName, out var isExpanded))
return;

state[newGroupName] = isExpanded;
SettingsManager.Current.SettingsChanged = true;
}

/// <summary>
/// Removes the group key from the persisted group-expand state for the currently loaded profile file.
/// </summary>
private static void RemoveGroupExpandStateKey(string groupName)
{
if (LoadedProfileFile == null)
return;

if (SettingsManager.Current.Profiles_GroupExpandState.TryGetValue(LoadedProfileFile.Path, out var state)
&& state.Remove(groupName))
SettingsManager.Current.SettingsChanged = true;
}

#endregion

#region Serialize and deserialize

/// <summary>
Expand Down Expand Up @@ -1085,6 +1161,8 @@ public static void ReplaceGroup(GroupInfo oldGroup, GroupInfo newGroup)
LoadedProfileFileData.Groups.Remove(oldGroup);
LoadedProfileFileData.Groups.Add(newGroup);

MigrateGroupExpandStateKey(oldGroup.Name, newGroup.Name);

ProfilesUpdated();
}

Expand All @@ -1099,6 +1177,8 @@ public static void RemoveGroup(GroupInfo group)

LoadedProfileFileData.Groups.Remove(group);

RemoveGroupExpandStateKey(group.Name);

ProfilesUpdated();
}

Expand Down
46 changes: 20 additions & 26 deletions Source/NETworkManager.Settings/SettingsInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using NETworkManager.Utilities;
using NETworkManager.Utilities.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
Expand Down Expand Up @@ -566,6 +567,25 @@ public string Profiles_LastSelected
}
}

/// <summary>
/// Persisted collapsed/expanded state of profile groups, shared across all tools. Outer key is the
/// full profile file path, inner key is the group name. Mutated in place by callers - since nested
/// dictionary mutations don't raise <see cref="PropertyChanged" />, callers must explicitly set
/// <see cref="SettingsChanged" /> themselves.
/// </summary>
public Dictionary<string, Dictionary<string, bool>> Profiles_GroupExpandState
{
get;
set
{
if (value == field)
return;

field = value;
OnPropertyChanged();
}
} = [];

public bool Profiles_IsDailyBackupEnabled
{
get;
Expand Down Expand Up @@ -3198,32 +3218,6 @@ public ExportFileType HostsFileEditor_ExportFileType
#endregion

#region Firewall
public bool Firewall_ExpandProfileView
{
get;
set
{
if (value == field)
return;

field = value;
OnPropertyChanged();
}
} = GlobalStaticConfiguration.Profile_ExpandProfileView;

public double Firewall_ProfileWidth
{
get;
set
{
if (Math.Abs(value - field) < GlobalStaticConfiguration.FloatPointFix)
return;

field = value;
OnPropertyChanged();
}
} = GlobalStaticConfiguration.Profile_DefaultWidthExpanded;

public string Firewall_ExportFilePath
{
get;
Expand Down
3 changes: 0 additions & 3 deletions Source/NETworkManager/ProfileDialogManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,6 @@ private static ProfileInfo ParseProfileInfo(ProfileViewModel instance)
? instance.SNMP_Priv
: new SecureString(),

// Firewall
Firewall_Enabled = instance.Firewall_Enabled,

// Wake on LAN
WakeOnLAN_Enabled = instance.WakeOnLAN_Enabled,
WakeOnLAN_MACAddress = instance.WakeOnLAN_MACAddress?.Trim(),
Expand Down
Loading
Loading