Skip to content

Commit

Permalink
Add dropdown to package preferences dialog for package paths for down…
Browse files Browse the repository at this point in the history
…load (#11747)

* add dropdown for package paths for package download

* change dropdown width to Auto

* handle selected package path property change event

* filter out paths that are files

* add label above dropdown

* rename resource

* filter programdata path from dropdown list

* add tooltip to combobox

* attempt to set package download directory using selected path from dropdown

* change how default package directory is set in PackageLoader

* attempted fixes to set package download path in PathLoader

* update default package install directory in path manager when selected in UI

* no need to reset DefaultPackageDirectory of PackageLoader

* Revert "no need to reset DefaultPackageDirectory of PackageLoader"

This reverts commit cd2ed3c.

* align package upload directory with selected package install dir

* review comments

* address more review comments

* do not hardcode user data dir to AppData

* cleanup and docs

* remove unused usings

* add unit tests

* review comments

* refactor based on review comments
  • Loading branch information
aparajit-pratap authored Jun 22, 2021
1 parent bdd63b6 commit b069b24
Show file tree
Hide file tree
Showing 17 changed files with 293 additions and 48 deletions.
31 changes: 22 additions & 9 deletions src/DynamoCore/Configuration/PathManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class PathManager : IPathManager
private readonly HashSet<string> preloadedLibraries;
private readonly HashSet<string> extensionsDirectories;
private readonly HashSet<string> viewExtensionsDirectories;
private readonly IPathResolver pathResolver;

#endregion

Expand Down Expand Up @@ -148,9 +149,21 @@ public string LogDirectory
get { return logDirectory; }
}

/// <summary>
/// Default directory where new packages are downloaded to.
/// This directory path is user configurable and if set to something other than the default,
/// the currently selected path can be obtained from preference settings.
/// </summary>
public string DefaultPackagesDirectory
{
get { return TransformPath(RootDirectories.First(), PackagesDirectoryName); }
get
{
if (Preferences is PreferenceSettings preferences)
{
return TransformPath(preferences.SelectedPackagePathForInstall, PackagesDirectoryName);
}
return TransformPath(RootDirectories.First(), PackagesDirectoryName);
}
}

public IEnumerable<string> PackagesDirectories
Expand Down Expand Up @@ -295,7 +308,7 @@ public bool ResolveDocumentPath(ref string document)
internal PathManager(PathManagerParams pathManagerParams)
{
var corePath = pathManagerParams.CorePath;
var pathResolver = pathManagerParams.PathResolver;
pathResolver = pathManagerParams.PathResolver;

if (string.IsNullOrEmpty(corePath) || !Directory.Exists(corePath))
{
Expand Down Expand Up @@ -339,7 +352,7 @@ internal PathManager(PathManagerParams pathManagerParams)
}

// Current user specific directories.
userDataDir = GetUserDataFolder(pathResolver);
userDataDir = GetUserDataFolder();

// When running as a headless process, put the logs directory in a consistent
// location that doesn't change every time the version number changes.
Expand All @@ -352,7 +365,7 @@ internal PathManager(PathManagerParams pathManagerParams)
backupDirectory = Path.Combine(userDataDirNoVersion, BackupDirectoryName);

// Common directories.
commonDataDir = GetCommonDataFolder(pathResolver);
commonDataDir = GetCommonDataFolder();

commonDefinitions = Path.Combine(commonDataDir, DefinitionsDirectoryName);
commonPackages = Path.Combine(commonDataDir, PackagesDirectoryName);
Expand All @@ -369,7 +382,7 @@ internal PathManager(PathManagerParams pathManagerParams)

preloadedLibraries = new HashSet<string>();
additionalResolutionPaths = new HashSet<string>();
LoadPathsFromResolver(pathResolver);
LoadPathsFromResolver();
}

/// <summary>
Expand Down Expand Up @@ -460,7 +473,7 @@ internal bool BackupXMLFile(XmlDocument xmlDoc, string filePath)

#region Private Class Helper Methods

private void LoadPathsFromResolver(IPathResolver pathResolver)
private void LoadPathsFromResolver()
{
if (pathResolver == null) // No optional path resolver is specified...
return;
Expand Down Expand Up @@ -490,7 +503,7 @@ private void LoadPathsFromResolver(IPathResolver pathResolver)
}
}

internal string GetUserDataFolder(IPathResolver pathResolver = null)
internal string GetUserDataFolder()
{
if (pathResolver != null && !string.IsNullOrEmpty(pathResolver.UserDataRootFolder))
return GetDynamoDataFolder(pathResolver.UserDataRootFolder);
Expand All @@ -502,7 +515,7 @@ internal string GetUserDataFolder(IPathResolver pathResolver = null)
return GetDynamoDataFolder(Path.Combine(folder, "Dynamo", "Dynamo Core"));
}

private string GetCommonDataFolder(IPathResolver pathResolver)
private string GetCommonDataFolder()
{
if (pathResolver != null && !string.IsNullOrEmpty(pathResolver.CommonDataRootFolder))
return GetDynamoDataFolder(pathResolver.CommonDataRootFolder);
Expand All @@ -516,7 +529,7 @@ private string GetDynamoDataFolder(string folder)
return Path.Combine(folder,
String.Format("{0}.{1}", majorFileVersion, minorFileVersion));
}

// This method is used to get the locations of packages folder or custom
// nodes folder given the root path. This is necessary because the packages
// may be in the root folder or in a packages subfolder of the root folder.
Expand Down
29 changes: 29 additions & 0 deletions src/DynamoCore/Configuration/PreferenceSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,34 @@ public string DefaultPythonEngine
/// </summary>
private static string defaultPythonEngine;

internal event Func<string> RequestUserDataFolder;
internal string OnRequestUserDataFolder()
{
return RequestUserDataFolder?.Invoke();
}

private string selectedPackagePathForInstall;
// TODO: Add this to IPreferences in Dynamo 3.0
/// <summary>
/// Currently selected package path where all packages downloaded from the Package Manager
/// will be installed. The default package path for install is the user data directory
/// currently used by the Dynamo environment.
/// </summary>
public string SelectedPackagePathForInstall {
get
{
if (string.IsNullOrEmpty(selectedPackagePathForInstall))
{
selectedPackagePathForInstall = OnRequestUserDataFolder();
}
return selectedPackagePathForInstall;
}
set
{
selectedPackagePathForInstall = value;
}
}

/// <summary>
/// Indicates (if any) which namespaces should not be displayed in the Dynamo node library.
/// String format: "[library name]:[fully qualified namespace]"
Expand Down Expand Up @@ -439,6 +467,7 @@ public PreferenceSettings()
EnableNodeAutoComplete = true;
DefaultPythonEngine = string.Empty;
ViewExtensionSettings = new List<ViewExtensionSettings>();

}

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/DynamoCore/Models/DynamoModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,7 @@ protected DynamoModel(IStartConfiguration config)
}

pathManager.Preferences = PreferenceSettings;
PreferenceSettings.RequestUserDataFolder += pathManager.GetUserDataFolder;

SearchModel = new NodeSearchModel(Logger);
SearchModel.ItemProduced +=
Expand Down Expand Up @@ -1114,6 +1115,7 @@ public void Dispose()
if (PreferenceSettings != null)
{
PreferenceSettings.PropertyChanged -= PreferenceSettings_PropertyChanged;
PreferenceSettings.RequestUserDataFolder -= pathManager.GetUserDataFolder;
}

LogWarningMessageEvents.LogWarningMessage -= LogWarningMessage;
Expand Down
18 changes: 18 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.en-US.resx
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,10 @@ You will get a chance to save your work.</value>
<value>Number Format</value>
<comment>Setting menu | Number format</comment>
</data>
<data name="PreferencesViewSelectedPackagePathForDownload" xml:space="preserve">
<value>Selected package path for download</value>
<comment>Preferences | Package Manager | Node and Package Paths | New Package Download Directory | Selected package path for download</comment>
</data>
<data name="DynamoViewSettingMenuSquareCentimeter" xml:space="preserve">
<value>Square Centimeter</value>
<comment>Setting menu | Square centimeter</comment>
Expand Down Expand Up @@ -2256,6 +2260,10 @@ Uninstall the following packages: {0}?</value>
<value>Default Python Engine</value>
<comment>Preferences | Features | Python | Default Python Engine</comment>
</data>
<data name="PreferencesViewPackageDownloadDirectory" xml:space="preserve">
<value>New Package Download Directory</value>
<comment>Preferences | Package Manager | Node and Package Paths | New Package Download Directory</comment>
</data>
<data name="DefaultPythonEngineNone" xml:space="preserve">
<value>Use System Default</value>
<comment>Preferences | Features | Python | Default Python Engine</comment>
Expand Down
8 changes: 8 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,10 @@
<value>Number Format</value>
<comment>Setting menu | Number format</comment>
</data>
<data name="PreferencesViewSelectedPackagePathForDownload" xml:space="preserve">
<value>Selected package path for download</value>
<comment>Preferences | Package Manager | Node and Package Paths | New Package Download Directory | Selected package path for download</comment>
</data>
<data name="DynamoViewSettingMenuSquareCentimeter" xml:space="preserve">
<value>Square Centimeter</value>
<comment>Setting menu | Square centimeter</comment>
Expand Down Expand Up @@ -2264,6 +2268,10 @@ Uninstall the following packages: {0}?</value>
<value>Default Python Engine</value>
<comment>Preferences | Features | Python | Default Python Engine</comment>
</data>
<data name="PreferencesViewPackageDownloadDirectory" xml:space="preserve">
<value>New Package Download Directory</value>
<comment>Preferences | Package Manager | Node and Package Paths | New Package Download Directory</comment>
</data>
<data name="DefaultPythonEngineNone" xml:space="preserve">
<value>Use System Default</value>
<comment>Preferences | Features | Python | Default Python Engine</comment>
Expand Down
70 changes: 67 additions & 3 deletions src/DynamoCoreWpf/ViewModels/Menu/PreferencesViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using Dynamo.Configuration;
Expand Down Expand Up @@ -32,11 +33,12 @@ public class PreferencesViewModel : ViewModelBase, INotifyPropertyChanged
private string savedChangesLabel;
private string savedChangesTooltip;
private ObservableCollection<string> languagesList;
private ObservableCollection<string> packagePathsForInstall;
private ObservableCollection<string> fontSizeList;
private ObservableCollection<string> numberFormatList;
private ObservableCollection<StyleItem> styleItemsList;
private StyleItem addStyleControl;
private ObservableCollection<string> _pythonEngineList;
private ObservableCollection<string> pythonEngineList;

private string selectedLanguage;
private string selectedFontSize;
Expand Down Expand Up @@ -260,6 +262,63 @@ public ObservableCollection<string> LanguagesList
}
}

/// <summary>
/// PackagePathsForInstall contains the list of all package paths where
/// packages can be installed.
/// </summary>
public ObservableCollection<string> PackagePathsForInstall
{
get
{
if (packagePathsForInstall == null || !packagePathsForInstall.Any())
{
var programDataPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
// Filter Std lib and ProgramData paths from list of paths for download
var customPaths = preferenceSettings.CustomPackageFolders.Where(
x => x != DynamoModel.StandardLibraryToken && !x.StartsWith(programDataPath));

packagePathsForInstall = new ObservableCollection<string>();
foreach (var path in customPaths)
{
var attr = File.GetAttributes(path);

// Add only directory paths
if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
{
packagePathsForInstall.Add(path);
}
}
}
return packagePathsForInstall;
}
set
{
packagePathsForInstall = value;
RaisePropertyChanged(nameof(PackagePathsForInstall));
}
}

/// <summary>
/// Currently selected package path where new packages will be downloaded.
/// </summary>
public string SelectedPackagePathForInstall
{
get
{
return preferenceSettings.SelectedPackagePathForInstall;
}
set
{
if (preferenceSettings.SelectedPackagePathForInstall != value)
{
preferenceSettings.SelectedPackagePathForInstall = value;
dynamoViewModel.PackageManagerClientViewModel.PackageManagerExtension.PackageLoader.SetPackagesDownloadDirectory(
value, dynamoViewModel.Model.PathManager.UserDataDirectory);
RaisePropertyChanged(nameof(SelectedPackagePathForInstall));
}
}
}

/// <summary>
/// FontSizesList contains the list of sizes for fonts defined (the ones defined are Small, Medium, Large, Extra Large)
/// </summary>
Expand Down Expand Up @@ -441,11 +500,11 @@ public ObservableCollection<string> PythonEnginesList
{
get
{
return _pythonEngineList;
return pythonEngineList;
}
set
{
_pythonEngineList = value;
pythonEngineList = value;
RaisePropertyChanged(nameof(PythonEnginesList));
}
}
Expand Down Expand Up @@ -649,6 +708,8 @@ public PreferencesViewModel(DynamoViewModel dynamoViewModel)
SelectedPythonEngine = Res.DefaultPythonEngineNone :
SelectedPythonEngine = preferenceSettings.DefaultPythonEngine;

SelectedPackagePathForInstall = preferenceSettings.SelectedPackagePathForInstall;

string languages = Wpf.Properties.Resources.PreferencesWindowLanguages;
LanguagesList = new ObservableCollection<string>(languages.Split(','));
SelectedLanguage = languages.Split(',').First();
Expand Down Expand Up @@ -735,6 +796,9 @@ private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
case nameof(SelectedNumberFormat):
description = Res.DynamoViewSettingMenuNumberFormat;
goto default;
case nameof(SelectedPackagePathForInstall):
description = Res.PreferencesViewSelectedPackagePathForDownload;
goto default;
case nameof(RunSettingsIsChecked):
description = Res.PreferencesViewRunSettingsLabel;
goto default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ internal void ExecutePackageDownload(string name, PackageVersion package, string

// form header version pairs and download and install all packages
dependencyVersionHeaders
.Select((dep, i) => {
.Select((dep) => {
return new PackageDownloadHandle()
{
Id = dep.id,
Expand Down
Loading

0 comments on commit b069b24

Please sign in to comment.