mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Further Refactor UI Code and Implement Engine Selection and Everything Setting UI
This commit is contained in:
parent
70e9a0ca84
commit
d36d15c887
13 changed files with 714 additions and 329 deletions
|
|
@ -8,6 +8,7 @@
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
||||||
|
<Nullable>warnings</Nullable>
|
||||||
<ApplicationIcon />
|
<ApplicationIcon />
|
||||||
<StartupObject />
|
<StartupObject />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
using Flow.Launcher.Plugin.Everything.Everything;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Flow.Launcher.Plugin.Explorer.Helper;
|
||||||
|
|
||||||
|
public static class SortOptionTranslationHelper
|
||||||
|
{
|
||||||
|
[CanBeNull]
|
||||||
|
public static IPublicAPI API { get; internal set; }
|
||||||
|
|
||||||
|
public static string GetTranslatedName(this SortOption sortOption)
|
||||||
|
{
|
||||||
|
const string prefix = "flowlauncher_plugin_everything_sort_by_";
|
||||||
|
|
||||||
|
ArgumentNullException.ThrowIfNull(API);
|
||||||
|
|
||||||
|
var enumName = Enum.GetName(sortOption);
|
||||||
|
var splited = enumName.Split('_');
|
||||||
|
var name = string.Join('_', splited[..^1]);
|
||||||
|
var direction = splited[^1];
|
||||||
|
|
||||||
|
return $"{API.GetTranslation(prefix + name.ToLower())} {API.GetTranslation(prefix + direction.ToLower())}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,7 +24,12 @@
|
||||||
<system:String x:Key="plugin_explorer_generalsetting_header">General Setting</system:String>
|
<system:String x:Key="plugin_explorer_generalsetting_header">General Setting</system:String>
|
||||||
<system:String x:Key="plugin_explorer_manageactionkeywords_header">Customise Action Keywords</system:String>
|
<system:String x:Key="plugin_explorer_manageactionkeywords_header">Customise Action Keywords</system:String>
|
||||||
<system:String x:Key="plugin_explorer_quickaccesslinks_header">Quick Access Links</system:String>
|
<system:String x:Key="plugin_explorer_quickaccesslinks_header">Quick Access Links</system:String>
|
||||||
|
<system:String x:Key="plugin_explorer_everything_setting_header">Everything Setting</system:String>
|
||||||
|
<system:String x:Key="plugin_explorer_everything_sort_option">Sort Option:</system:String>
|
||||||
|
<system:String x:Key="plugin_explorer_launch_hidden">Launch Hidden</system:String>
|
||||||
|
<system:String x:Key="plugin_explorer_editor_path">Editor Path</system:String>
|
||||||
<system:String x:Key="plugin_explorer_indexsearchexcludedpaths_header">Index Search Excluded Paths</system:String>
|
<system:String x:Key="plugin_explorer_indexsearchexcludedpaths_header">Index Search Excluded Paths</system:String>
|
||||||
|
<system:String x:Key="plugin_explorer_use_location_as_working_dir">Use search result's location as executable working directory</system:String>
|
||||||
<system:String x:Key="plugin_explorer_usewindowsindexfordirectorysearch">Use Index Search For Path Search</system:String>
|
<system:String x:Key="plugin_explorer_usewindowsindexfordirectorysearch">Use Index Search For Path Search</system:String>
|
||||||
<system:String x:Key="plugin_explorer_usewindowsindexfordirectorysearch_tooltip">Turning this on will return indexed directories/files faster, but if a directory/file is not indexed it will not show up. If a directory/file has been added to Index Search Excluded Path then it will still show up even if this option is on</system:String>
|
<system:String x:Key="plugin_explorer_usewindowsindexfordirectorysearch_tooltip">Turning this on will return indexed directories/files faster, but if a directory/file is not indexed it will not show up. If a directory/file has been added to Index Search Excluded Path then it will still show up even if this option is on</system:String>
|
||||||
<system:String x:Key="plugin_explorer_manageindexoptions">Indexing Options</system:String>
|
<system:String x:Key="plugin_explorer_manageindexoptions">Indexing Options</system:String>
|
||||||
|
|
@ -37,7 +42,11 @@
|
||||||
<system:String x:Key="plugin_explorer_actionkeyword_done">Done</system:String>
|
<system:String x:Key="plugin_explorer_actionkeyword_done">Done</system:String>
|
||||||
<system:String x:Key="plugin_explorer_actionkeyword_enabled">Enabled</system:String>
|
<system:String x:Key="plugin_explorer_actionkeyword_enabled">Enabled</system:String>
|
||||||
<system:String x:Key="plugin_explorer_actionkeyword_enabled_tooltip">When disabled Flow will not execute this search option, and will additionally revert back to '*' to free up the action keyword</system:String>
|
<system:String x:Key="plugin_explorer_actionkeyword_enabled_tooltip">When disabled Flow will not execute this search option, and will additionally revert back to '*' to free up the action keyword</system:String>
|
||||||
|
<system:String x:Key="plugin_explorer_engine_everything">Everything</system:String>
|
||||||
|
<system:String x:Key="plugin_explorer_engine_windows_index">Windows Index</system:String>
|
||||||
|
<system:String x:Key="plugin_explorer_path_enumeration_engine_none">Direct Enumeration</system:String>
|
||||||
|
|
||||||
|
|
||||||
<!--Plugin Infos-->
|
<!--Plugin Infos-->
|
||||||
<system:String x:Key="plugin_explorer_plugin_name">Explorer</system:String>
|
<system:String x:Key="plugin_explorer_plugin_name">Explorer</system:String>
|
||||||
<system:String x:Key="plugin_explorer_plugin_description">Search and manage files and folders. Explorer utilises Windows Index Search</system:String>
|
<system:String x:Key="plugin_explorer_plugin_description">Search and manage files and folders. Explorer utilises Windows Index Search</system:String>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using Flow.Launcher.Infrastructure.Storage;
|
using Flow.Launcher.Infrastructure.Storage;
|
||||||
|
using Flow.Launcher.Plugin.Explorer.Helper;
|
||||||
using Flow.Launcher.Plugin.Explorer.Search;
|
using Flow.Launcher.Plugin.Explorer.Search;
|
||||||
using Flow.Launcher.Plugin.Explorer.Search.Everything;
|
using Flow.Launcher.Plugin.Explorer.Search.Everything;
|
||||||
using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks;
|
using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks;
|
||||||
|
|
@ -16,7 +17,7 @@ namespace Flow.Launcher.Plugin.Explorer
|
||||||
{
|
{
|
||||||
public class Main : ISettingProvider, IAsyncPlugin, IContextMenu, IPluginI18n
|
public class Main : ISettingProvider, IAsyncPlugin, IContextMenu, IPluginI18n
|
||||||
{
|
{
|
||||||
internal PluginInitContext Context { get; set; }
|
internal static PluginInitContext Context { get; set; }
|
||||||
|
|
||||||
internal Settings Settings;
|
internal Settings Settings;
|
||||||
|
|
||||||
|
|
@ -50,6 +51,9 @@ namespace Flow.Launcher.Plugin.Explorer
|
||||||
contextMenu = new ContextMenu(Context, Settings, viewModel);
|
contextMenu = new ContextMenu(Context, Settings, viewModel);
|
||||||
searchManager = new SearchManager(Settings, Context);
|
searchManager = new SearchManager(Settings, Context);
|
||||||
ResultManager.Init(Context, Settings);
|
ResultManager.Init(Context, Settings);
|
||||||
|
|
||||||
|
SortOptionTranslationHelper.API = context.API;
|
||||||
|
|
||||||
EverythingApiDllImport.Load(Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK",
|
EverythingApiDllImport.Load(Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK",
|
||||||
Environment.Is64BitProcess ? "Everything64.dll" : "Everything86.dll"));
|
Environment.Is64BitProcess ? "Everything64.dll" : "Everything86.dll"));
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
|
||||||
|
|
@ -83,17 +83,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo
|
||||||
{
|
{
|
||||||
Log.Exception(nameof(DirectoryInfoSearch), "Error occured while searching path", e);
|
Log.Exception(nameof(DirectoryInfoSearch), "Error occured while searching path", e);
|
||||||
|
|
||||||
results.Add(
|
throw;
|
||||||
new Result
|
|
||||||
{
|
|
||||||
Title = string.Format(SearchManager.Context.API.GetTranslation(
|
|
||||||
"plugin_explorer_directoryinfosearch_error"),
|
|
||||||
e.Message),
|
|
||||||
Score = 501,
|
|
||||||
IcoPath = Constants.ExplorerIconImagePath
|
|
||||||
});
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initial ordering, this order can be updated later by UpdateResultView.MainViewModel based on history of user selection.
|
// Initial ordering, this order can be updated later by UpdateResultView.MainViewModel based on history of user selection.
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,9 @@ namespace Flow.Launcher.Plugin.Explorer.Search
|
||||||
if (string.IsNullOrEmpty(query.Search))
|
if (string.IsNullOrEmpty(query.Search))
|
||||||
return QuickAccess.AccessLinkListAll(query, Settings.QuickAccessLinks);
|
return QuickAccess.AccessLinkListAll(query, Settings.QuickAccessLinks);
|
||||||
|
|
||||||
var quickaccessLinks = QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks);
|
var quickAccessLinks = QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks);
|
||||||
|
|
||||||
results.UnionWith(quickaccessLinks);
|
results.UnionWith(quickAccessLinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<SearchResult> searchResults;
|
IEnumerable<SearchResult> searchResults;
|
||||||
|
|
@ -164,7 +164,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
|
||||||
|
|
||||||
var recursiveIndicatorIndex = query.Search.IndexOf('>');
|
var recursiveIndicatorIndex = query.Search.IndexOf('>');
|
||||||
|
|
||||||
if (recursiveIndicatorIndex > 0 && Settings.PathEnumerationEngine != Settings.PathTraversalEngineOption.Direct)
|
if (recursiveIndicatorIndex > 0 && Settings.PathEnumerationEngine != Settings.PathEnumerationEngineOption.Direct)
|
||||||
{
|
{
|
||||||
directoryResult =
|
directoryResult =
|
||||||
await Settings.PathEnumerator.EnumerateAsync(query.Search[..recursiveIndicatorIndex],
|
await Settings.PathEnumerator.EnumerateAsync(query.Search[..recursiveIndicatorIndex],
|
||||||
|
|
@ -176,7 +176,23 @@ namespace Flow.Launcher.Plugin.Explorer.Search
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
directoryResult = DirectoryInfoSearch.TopLevelDirectorySearch(query, query.Search, token);
|
try
|
||||||
|
{
|
||||||
|
directoryResult = DirectoryInfoSearch.TopLevelDirectorySearch(query, query.Search, token);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
results.Add(
|
||||||
|
new Result
|
||||||
|
{
|
||||||
|
Title = string.Format(SearchManager.Context.API.GetTranslation(
|
||||||
|
"plugin_explorer_directoryinfosearch_error"),
|
||||||
|
e.Message),
|
||||||
|
Score = 501,
|
||||||
|
IcoPath = Constants.ExplorerIconImagePath
|
||||||
|
});
|
||||||
|
directoryResult = new List<SearchResult>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,9 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
|
||||||
///</summary>
|
///</summary>
|
||||||
public string QueryForAllFilesAndFolders(string userSearchString)
|
public string QueryForAllFilesAndFolders(string userSearchString)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrEmpty(userSearchString))
|
||||||
|
userSearchString = "*";
|
||||||
|
|
||||||
// Generate SQL from constructed parameters, converting the userSearchString from AQS->WHERE clause
|
// Generate SQL from constructed parameters, converting the userSearchString from AQS->WHERE clause
|
||||||
return CreateBaseQuery().GenerateSQLFromUserQuery(userSearchString) + " AND " + QueryWhereRestrictionsForAllFilesAndFoldersSearch
|
return CreateBaseQuery().GenerateSQLFromUserQuery(userSearchString) + " AND " + QueryWhereRestrictionsForAllFilesAndFoldersSearch
|
||||||
+ QueryOrderByFileNameRestriction;
|
+ QueryOrderByFileNameRestriction;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
|
@ -15,14 +16,22 @@ namespace Flow.Launcher.Plugin.Explorer
|
||||||
{
|
{
|
||||||
public int MaxResult { get; set; } = 100;
|
public int MaxResult { get; set; } = 100;
|
||||||
|
|
||||||
public ObservableCollection<AccessLink> QuickAccessLinks { get; set; } = new ();
|
public ObservableCollection<AccessLink> QuickAccessLinks { get; set; } = new();
|
||||||
|
|
||||||
// as at v1.7.0 this is to maintain backwards compatibility, need to be removed afterwards.
|
// as at v1.7.0 this is to maintain backwards compatibility, need to be removed afterwards.
|
||||||
public ObservableCollection<AccessLink> QuickFolderAccessLinks { get; set; } = new ();
|
public ObservableCollection<AccessLink> QuickFolderAccessLinks { get; set; } = new();
|
||||||
|
|
||||||
|
public ObservableCollection<AccessLink> IndexSearchExcludedSubdirectoryPaths { get; set; } = new ObservableCollection<AccessLink>();
|
||||||
|
|
||||||
|
public string EditorPath { get; set; } = "";
|
||||||
|
|
||||||
|
|
||||||
|
public bool UseLocationAsWorkingDir { get; set; } = false;
|
||||||
|
|
||||||
|
public bool ShowWindowsContextMenu { get; set; } = true;
|
||||||
|
|
||||||
public bool UseWindowsIndexForDirectorySearch { get; set; } = false;
|
public bool UseWindowsIndexForDirectorySearch { get; set; } = false;
|
||||||
|
|
||||||
public ObservableCollection<AccessLink> IndexSearchExcludedSubdirectoryPaths { get; set; } = new ObservableCollection<AccessLink>();
|
|
||||||
|
|
||||||
public string SearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign;
|
public string SearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign;
|
||||||
|
|
||||||
|
|
@ -44,76 +53,86 @@ namespace Flow.Launcher.Plugin.Explorer
|
||||||
|
|
||||||
public bool QuickAccessKeywordEnabled { get; set; }
|
public bool QuickAccessKeywordEnabled { get; set; }
|
||||||
|
|
||||||
|
public bool LaunchHidden { get; set; } = false;
|
||||||
|
|
||||||
|
|
||||||
public bool WarnWindowsSearchServiceOff { get; set; } = true;
|
public bool WarnWindowsSearchServiceOff { get; set; } = true;
|
||||||
|
|
||||||
private IReadOnlyList<IIndexProvider> _indexProviders;
|
private EverythingSearchManager _everythingManagerInstance;
|
||||||
private IReadOnlyList<IContentIndexProvider> _fileContentIndexProviders;
|
private WindowsIndexSearchManager _windowsIndexSearchManager;
|
||||||
private IReadOnlyList<IPathEnumerable> _pathEnumerables;
|
|
||||||
public Settings()
|
#region SearchEngine
|
||||||
{
|
|
||||||
var everythingManager = new EverythingSearchManager(this);
|
public PathEnumerationEngineOption PathEnumerationEngine { get; set; }
|
||||||
var windowsIndexManager = new WindowsIndexSearchManager(this);
|
|
||||||
|
private EverythingSearchManager EverythingManagerInstance => _everythingManagerInstance ??= new EverythingSearchManager(this);
|
||||||
_indexProviders = new List<IIndexProvider>()
|
private WindowsIndexSearchManager WindowsIndexSearchManager => _windowsIndexSearchManager ??= new WindowsIndexSearchManager(this);
|
||||||
{
|
|
||||||
everythingManager,
|
|
||||||
windowsIndexManager
|
|
||||||
};
|
|
||||||
|
|
||||||
_pathEnumerables = new List<IPathEnumerable>()
|
|
||||||
{
|
|
||||||
everythingManager,
|
|
||||||
windowsIndexManager
|
|
||||||
};
|
|
||||||
|
|
||||||
_fileContentIndexProviders = new List<IContentIndexProvider>
|
|
||||||
{
|
|
||||||
windowsIndexManager,
|
|
||||||
everythingManager,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public IndexSearchEngineOption IndexSearchEngine { get; set; }
|
public IndexSearchEngineOption IndexSearchEngine { get; set; }
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IIndexProvider IndexProvider => _indexProviders[(int)IndexSearchEngine];
|
public IIndexProvider IndexProvider => IndexSearchEngine switch
|
||||||
|
{
|
||||||
public PathTraversalEngineOption PathEnumerationEngine { get; set; }
|
IndexSearchEngineOption.Everything => EverythingManagerInstance,
|
||||||
|
IndexSearchEngineOption.WindowsIndex => WindowsIndexSearchManager,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(IndexSearchEngine))
|
||||||
|
};
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IPathEnumerable PathEnumerator => _pathEnumerables[(int)PathEnumerationEngine];
|
public IPathEnumerable PathEnumerator => PathEnumerationEngine switch
|
||||||
|
{
|
||||||
|
PathEnumerationEngineOption.Everything => EverythingManagerInstance,
|
||||||
|
PathEnumerationEngineOption.WindowsIndex => WindowsIndexSearchManager,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(PathEnumerationEngine))
|
||||||
|
};
|
||||||
|
|
||||||
public ContentIndexSearchEngineOption ContentSearchEngine { get; set; }
|
public ContentIndexSearchEngineOption ContentSearchEngine { get; set; }
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IContentIndexProvider ContentIndexProvider => _fileContentIndexProviders[(int)ContentSearchEngine];
|
public IContentIndexProvider ContentIndexProvider => ContentSearchEngine switch
|
||||||
|
|
||||||
public enum PathTraversalEngineOption
|
|
||||||
{
|
{
|
||||||
|
ContentIndexSearchEngineOption.Everything => EverythingManagerInstance,
|
||||||
|
ContentIndexSearchEngineOption.WindowsIndex => WindowsIndexSearchManager,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(ContentSearchEngine))
|
||||||
|
};
|
||||||
|
|
||||||
|
public enum PathEnumerationEngineOption
|
||||||
|
{
|
||||||
|
[Description("plugin_explorer_engine_everything")]
|
||||||
Everything,
|
Everything,
|
||||||
|
[Description("plugin_explorer_engine_windows_index")]
|
||||||
WindowsIndex,
|
WindowsIndex,
|
||||||
|
[Description("plugin_explorer_path_enumeration_engine_none")]
|
||||||
Direct
|
Direct
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum IndexSearchEngineOption
|
public enum IndexSearchEngineOption
|
||||||
{
|
{
|
||||||
|
[Description("plugin_explorer_engine_everything")]
|
||||||
Everything,
|
Everything,
|
||||||
|
[Description("plugin_explorer_engine_windows_index")]
|
||||||
WindowsIndex
|
WindowsIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ContentIndexSearchEngineOption
|
public enum ContentIndexSearchEngineOption
|
||||||
{
|
{
|
||||||
|
[Description("plugin_explorer_engine_everything")]
|
||||||
Everything,
|
Everything,
|
||||||
|
[Description("plugin_explorer_engine_windows_index")]
|
||||||
WindowsIndex
|
WindowsIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool LaunchHidden { get; set; } = false;
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Everything Settings
|
#region Everything Settings
|
||||||
|
|
||||||
public string EverythingInstalledPath { get; set; }
|
public string EverythingInstalledPath { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
public SortOption[] SortOptions { get; set; } = Enum.GetValues<SortOption>();
|
public SortOption[] SortOptions { get; set; } = Enum.GetValues<SortOption>();
|
||||||
|
|
||||||
public SortOption SortOption { get; set; } = SortOption.NAME_ASCENDING;
|
public SortOption SortOption { get; set; } = SortOption.NAME_ASCENDING;
|
||||||
|
|
||||||
public bool EnableEverythingContentSearch { get; set; } = false;
|
public bool EnableEverythingContentSearch { get; set; } = false;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Flow.Launcher.Plugin.Explorer.ViewModels;
|
||||||
|
|
||||||
|
public class EnumBindingModel<T> where T : struct, Enum
|
||||||
|
{
|
||||||
|
public static IReadOnlyList<EnumBindingModel<T>> CreateList()
|
||||||
|
{
|
||||||
|
return Enum.GetValues<T>()
|
||||||
|
.Select(value => new EnumBindingModel<T>
|
||||||
|
{
|
||||||
|
Value = value, LocalizationKey = GetDescriptionAttr(value)
|
||||||
|
})
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnumBindingModel<T> From(T value)
|
||||||
|
{
|
||||||
|
var name = value.ToString();
|
||||||
|
var description = GetDescriptionAttr(value);
|
||||||
|
|
||||||
|
return new EnumBindingModel<T>
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
LocalizationKey = description,
|
||||||
|
Value = value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetDescriptionAttr(T source)
|
||||||
|
{
|
||||||
|
var fi = source.GetType().GetField(source.ToString());
|
||||||
|
|
||||||
|
var attributes = (DescriptionAttribute[])fi?.GetCustomAttributes(
|
||||||
|
typeof(DescriptionAttribute), false);
|
||||||
|
|
||||||
|
return attributes is { Length: > 0 } ? attributes[0].Description : source.ToString();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
private string LocalizationKey { get; set; }
|
||||||
|
public string Description => Main.Context.API.GetTranslation(LocalizationKey);
|
||||||
|
public T Value { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -1,27 +1,41 @@
|
||||||
using Flow.Launcher.Core.Plugin;
|
using Flow.Launcher.Core.Plugin;
|
||||||
using Flow.Launcher.Infrastructure.Storage;
|
using Flow.Launcher.Infrastructure.Storage;
|
||||||
using Flow.Launcher.Plugin.Explorer.Search;
|
using Flow.Launcher.Plugin.Explorer.Search;
|
||||||
|
using Flow.Launcher.Plugin.Explorer.Search.Everything;
|
||||||
|
using Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions;
|
||||||
using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks;
|
using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks;
|
||||||
using Flow.Launcher.Plugin.Explorer.Views;
|
using Flow.Launcher.Plugin.Explorer.Views;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
using MessageBox = System.Windows.Forms.MessageBox;
|
||||||
|
|
||||||
namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
||||||
{
|
{
|
||||||
public class SettingsViewModel
|
public class SettingsViewModel : BaseModel
|
||||||
{
|
{
|
||||||
public Settings Settings { get; set; }
|
public Settings Settings { get; set; }
|
||||||
|
|
||||||
internal PluginInitContext Context { get; set; }
|
internal PluginInitContext Context { get; set; }
|
||||||
|
|
||||||
|
public IReadOnlyList<EnumBindingModel<Settings.IndexSearchEngineOption>> IndexSearchEngines { get; set; }
|
||||||
|
public IReadOnlyList<EnumBindingModel<Settings.ContentIndexSearchEngineOption>> ContentIndexSearchEngines { get; set; }
|
||||||
|
public IReadOnlyList<EnumBindingModel<Settings.PathEnumerationEngineOption>> PathEnumerationEngines { get; set; }
|
||||||
|
|
||||||
public SettingsViewModel(PluginInitContext context, Settings settings)
|
public SettingsViewModel(PluginInitContext context, Settings settings)
|
||||||
{
|
{
|
||||||
Context = context;
|
Context = context;
|
||||||
Settings = settings;
|
Settings = settings;
|
||||||
|
|
||||||
|
InitializeEngineSelection();
|
||||||
|
InitializeActionKeywordModels();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -30,17 +44,84 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
||||||
Context.API.SaveSettingJsonStorage<Settings>();
|
Context.API.SaveSettingJsonStorage<Settings>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Engine Selection
|
||||||
|
|
||||||
|
private EnumBindingModel<Settings.IndexSearchEngineOption> _selectedIndexSearchEngine;
|
||||||
|
private EnumBindingModel<Settings.ContentIndexSearchEngineOption> _selectedContentSearchEngine;
|
||||||
|
private EnumBindingModel<Settings.PathEnumerationEngineOption> _selectedPathEnumerationEngine;
|
||||||
|
|
||||||
|
|
||||||
|
public EnumBindingModel<Settings.IndexSearchEngineOption> SelectedIndexSearchEngine
|
||||||
|
{
|
||||||
|
get => _selectedIndexSearchEngine;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_selectedIndexSearchEngine = value;
|
||||||
|
Settings.IndexSearchEngine = value.Value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnumBindingModel<Settings.ContentIndexSearchEngineOption> SelectedContentSearchEngine
|
||||||
|
{
|
||||||
|
get => _selectedContentSearchEngine;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_selectedContentSearchEngine = value;
|
||||||
|
Settings.ContentSearchEngine = value.Value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnumBindingModel<Settings.PathEnumerationEngineOption> SelectedPathEnumerationEngine
|
||||||
|
{
|
||||||
|
get => _selectedPathEnumerationEngine;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_selectedPathEnumerationEngine = value;
|
||||||
|
Settings.PathEnumerationEngine = value.Value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeEngineSelection()
|
||||||
|
{
|
||||||
|
IndexSearchEngines = EnumBindingModel<Settings.IndexSearchEngineOption>.CreateList();
|
||||||
|
ContentIndexSearchEngines = EnumBindingModel<Settings.ContentIndexSearchEngineOption>.CreateList();
|
||||||
|
PathEnumerationEngines = EnumBindingModel<Settings.PathEnumerationEngineOption>.CreateList();
|
||||||
|
|
||||||
|
SelectedIndexSearchEngine = IndexSearchEngines.FirstOrDefault(x => x.Value == Settings.IndexSearchEngine);
|
||||||
|
_selectedContentSearchEngine = ContentIndexSearchEngines.FirstOrDefault(x => x.Value == Settings.ContentSearchEngine);
|
||||||
|
_selectedPathEnumerationEngine = PathEnumerationEngines.FirstOrDefault(x => x.Value == Settings.PathEnumerationEngine);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region ActionKeyword
|
||||||
|
|
||||||
|
private void InitializeActionKeywordModels()
|
||||||
|
{
|
||||||
|
ActionKeywordsModels = new List<ActionKeywordModel>
|
||||||
|
{
|
||||||
|
new(Settings.ActionKeyword.SearchActionKeyword,
|
||||||
|
Context.API.GetTranslation("plugin_explorer_actionkeywordview_search")),
|
||||||
|
new(Settings.ActionKeyword.FileContentSearchActionKeyword,
|
||||||
|
Context.API.GetTranslation("plugin_explorer_actionkeywordview_filecontentsearch")),
|
||||||
|
new(Settings.ActionKeyword.PathSearchActionKeyword,
|
||||||
|
Context.API.GetTranslation("plugin_explorer_actionkeywordview_pathsearch")),
|
||||||
|
new(Settings.ActionKeyword.IndexSearchActionKeyword,
|
||||||
|
Context.API.GetTranslation("plugin_explorer_actionkeywordview_indexsearch")),
|
||||||
|
new(Settings.ActionKeyword.QuickAccessActionKeyword,
|
||||||
|
Context.API.GetTranslation("plugin_explorer_actionkeywordview_quickaccess"))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public IReadOnlyList<ActionKeywordModel> ActionKeywordsModels { get; set; }
|
||||||
|
|
||||||
public AccessLink SelectedQuickAccessLink { get; set; }
|
|
||||||
public AccessLink SelectedIndexSearchExcludedPath { get; set; }
|
|
||||||
public ActionKeywordModel SelectedActionKeyword { get; set; }
|
public ActionKeywordModel SelectedActionKeyword { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public ICommand RemoveLinkCommand => new RelayCommand(RemoveLink);
|
|
||||||
public ICommand EditLinkCommand => new RelayCommand(EditLink);
|
|
||||||
public ICommand AddLinkCommand => new RelayCommand(AddLink);
|
|
||||||
|
|
||||||
public ICommand EditActionKeywordCommand => new RelayCommand(EditActionKeyword);
|
public ICommand EditActionKeywordCommand => new RelayCommand(EditActionKeyword);
|
||||||
|
|
||||||
private void EditActionKeyword(object obj)
|
private void EditActionKeyword(object obj)
|
||||||
|
|
@ -53,130 +134,116 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
||||||
|
|
||||||
var actionKeywordWindow = new ActionKeywordSetting(actionKeyword, Context.API);
|
var actionKeywordWindow = new ActionKeywordSetting(actionKeyword, Context.API);
|
||||||
|
|
||||||
if (actionKeywordWindow.ShowDialog() ?? false)
|
if (!(actionKeywordWindow.ShowDialog() ?? false))
|
||||||
{
|
{
|
||||||
if (actionKeyword.Enabled && !actionKeywordWindow.KeywordEnabled)
|
return;
|
||||||
{
|
}
|
||||||
|
|
||||||
|
switch (actionKeyword.Enabled, actionKeywordWindow.KeywordEnabled)
|
||||||
|
{
|
||||||
|
case (true, false):
|
||||||
Context.API.RemoveActionKeyword(Context.CurrentPluginMetadata.ID, actionKeyword.Keyword);
|
Context.API.RemoveActionKeyword(Context.CurrentPluginMetadata.ID, actionKeyword.Keyword);
|
||||||
}
|
break;
|
||||||
else if (!actionKeyword.Enabled && actionKeywordWindow.KeywordEnabled)
|
case (true, true):
|
||||||
{
|
|
||||||
Context.API.AddActionKeyword(Context.CurrentPluginMetadata.ID, actionKeyword.Keyword);
|
|
||||||
}
|
|
||||||
else if (actionKeyword.Enabled && actionKeywordWindow.KeywordEnabled)
|
|
||||||
{
|
|
||||||
// same keyword will have dialog result false
|
// same keyword will have dialog result false
|
||||||
Context.API.RemoveActionKeyword(Context.CurrentPluginMetadata.ID, actionKeyword.Keyword);
|
Context.API.RemoveActionKeyword(Context.CurrentPluginMetadata.ID, actionKeyword.Keyword);
|
||||||
Context.API.AddActionKeyword(Context.CurrentPluginMetadata.ID, actionKeywordWindow.ActionKeyword);
|
Context.API.AddActionKeyword(Context.CurrentPluginMetadata.ID, actionKeywordWindow.ActionKeyword);
|
||||||
}
|
break;
|
||||||
|
case (false, true):
|
||||||
(actionKeyword.Keyword, actionKeyword.Enabled) = (actionKeywordWindow.ActionKeyword, actionKeywordWindow.KeywordEnabled);
|
Context.API.AddActionKeyword(Context.CurrentPluginMetadata.ID, actionKeyword.Keyword);
|
||||||
|
break;
|
||||||
|
case (false, false):
|
||||||
|
throw new ArgumentException(
|
||||||
|
$"Both false in {nameof(actionKeyword)}.{nameof(actionKeyword.Enabled)} and {nameof(actionKeywordWindow)}.{nameof(actionKeywordWindow.KeywordEnabled)} should suggest that the ShowDialog() result is false");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(actionKeyword.Keyword, actionKeyword.Enabled) = (actionKeywordWindow.ActionKeyword, actionKeywordWindow.KeywordEnabled);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccessLink? PromptUserSelectPath(ResultType type, string initialDirectory = null)
|
#endregion
|
||||||
|
|
||||||
|
#region AccessLinks
|
||||||
|
|
||||||
|
public AccessLink SelectedQuickAccessLink { get; set; }
|
||||||
|
public AccessLink SelectedIndexSearchExcludedPath { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public ICommand RemoveLinkCommand => new RelayCommand(RemoveLink);
|
||||||
|
public ICommand EditLinkCommand => new RelayCommand(EditLink);
|
||||||
|
public ICommand AddLinkCommand => new RelayCommand(AddLink);
|
||||||
|
|
||||||
|
public void AppendLink(string containerName, AccessLink link)
|
||||||
{
|
{
|
||||||
AccessLink newAccessLink = null;
|
var container = containerName switch
|
||||||
|
|
||||||
if (type is ResultType.Folder)
|
|
||||||
{
|
{
|
||||||
var folderBrowserDialog = new FolderBrowserDialog();
|
"QuickAccessLink" => Settings.QuickAccessLinks,
|
||||||
|
"IndexSearchExcludedPath" => Settings.IndexSearchExcludedSubdirectoryPaths,
|
||||||
if (initialDirectory is not null)
|
_ => throw new ArgumentException($"Unknown container name: {containerName}")
|
||||||
folderBrowserDialog.InitialDirectory = initialDirectory;
|
};
|
||||||
|
container.Add(link);
|
||||||
if (folderBrowserDialog.ShowDialog() != DialogResult.OK)
|
|
||||||
return newAccessLink;
|
|
||||||
|
|
||||||
newAccessLink = new AccessLink { Path = folderBrowserDialog.SelectedPath };
|
|
||||||
}
|
|
||||||
else if (type is ResultType.File)
|
|
||||||
{
|
|
||||||
var openFileDialog = new OpenFileDialog();
|
|
||||||
if (initialDirectory is not null)
|
|
||||||
openFileDialog.InitialDirectory = initialDirectory;
|
|
||||||
|
|
||||||
if (openFileDialog.ShowDialog() != DialogResult.OK)
|
|
||||||
return newAccessLink;
|
|
||||||
|
|
||||||
newAccessLink = new AccessLink { Path = openFileDialog.FileName };
|
|
||||||
}
|
|
||||||
return newAccessLink;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EditLink(object obj)
|
private void EditLink(object commandParameter)
|
||||||
{
|
{
|
||||||
if (obj is not string container) return;
|
(AccessLink selectedLink, ObservableCollection<AccessLink> collection) = commandParameter switch
|
||||||
|
|
||||||
AccessLink selectedLink;
|
|
||||||
ObservableCollection<AccessLink> collection;
|
|
||||||
|
|
||||||
switch (container)
|
|
||||||
{
|
{
|
||||||
case "QuickAccessLink":
|
"QuickAccessLink" => (SelectedQuickAccessLink, Settings.QuickAccessLinks),
|
||||||
if (SelectedQuickAccessLink == null)
|
"IndexSearchExcludedPath" => (SelectedIndexSearchExcludedPath, Settings.IndexSearchExcludedSubdirectoryPaths),
|
||||||
{
|
_ => throw new ArgumentOutOfRangeException(nameof(commandParameter))
|
||||||
ShowUnselectedMessage();
|
};
|
||||||
return;
|
|
||||||
}
|
if (selectedLink is null)
|
||||||
selectedLink = SelectedQuickAccessLink;
|
{
|
||||||
collection = Settings.QuickAccessLinks;
|
ShowUnselectedMessage();
|
||||||
break;
|
return;
|
||||||
case "IndexSearchExcludedPaths":
|
|
||||||
if (SelectedIndexSearchExcludedPath == null)
|
|
||||||
{
|
|
||||||
ShowUnselectedMessage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
selectedLink = SelectedIndexSearchExcludedPath;
|
|
||||||
collection = Settings.IndexSearchExcludedSubdirectoryPaths;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var link = PromptUserSelectPath(selectedLink.Type,
|
var path = PromptUserSelectPath(selectedLink.Type,
|
||||||
selectedLink.Type == ResultType.Folder
|
selectedLink.Type == ResultType.Folder
|
||||||
? selectedLink.Path
|
? selectedLink.Path
|
||||||
: Path.GetDirectoryName(selectedLink.Path));
|
: Path.GetDirectoryName(selectedLink.Path));
|
||||||
|
|
||||||
if (link is null)
|
if (path is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
collection.Remove(selectedLink);
|
collection.Remove(selectedLink);
|
||||||
collection.Add(link);
|
collection.Add(new AccessLink
|
||||||
|
{
|
||||||
|
Path = path, Type = selectedLink.Type,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowUnselectedMessage()
|
private void ShowUnselectedMessage()
|
||||||
{
|
{
|
||||||
string warning = Context.API.GetTranslation("plugin_explorer_make_selection_warning");
|
var warning = Context.API.GetTranslation("plugin_explorer_make_selection_warning");
|
||||||
MessageBox.Show(warning);
|
MessageBox.Show(warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddLink(object obj)
|
|
||||||
|
private void AddLink(object commandParameter)
|
||||||
{
|
{
|
||||||
if (obj is not string container) return;
|
var container = commandParameter switch
|
||||||
|
{
|
||||||
|
"QuickAccessLink" => Settings.QuickAccessLinks,
|
||||||
|
"IndexSearchExcludedPaths" => Settings.IndexSearchExcludedSubdirectoryPaths,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(commandParameter))
|
||||||
|
};
|
||||||
|
|
||||||
|
ArgumentNullException.ThrowIfNull(container);
|
||||||
|
|
||||||
var folderBrowserDialog = new FolderBrowserDialog();
|
var folderBrowserDialog = new FolderBrowserDialog();
|
||||||
|
|
||||||
if (folderBrowserDialog.ShowDialog() != DialogResult.OK)
|
if (folderBrowserDialog.ShowDialog() != DialogResult.OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var newAccessLink = new AccessLink { Path = folderBrowserDialog.SelectedPath };
|
var newAccessLink = new AccessLink
|
||||||
|
|
||||||
|
|
||||||
switch (container)
|
|
||||||
{
|
{
|
||||||
case "QuickAccessLink":
|
Path = folderBrowserDialog.SelectedPath
|
||||||
if (SelectedQuickAccessLink == null) return;
|
};
|
||||||
Settings.QuickAccessLinks.Add(newAccessLink);
|
|
||||||
break;
|
container.Add(newAccessLink);
|
||||||
case "IndexSearchExcludedPaths":
|
|
||||||
if (SelectedIndexSearchExcludedPath == null) return;
|
|
||||||
Settings.IndexSearchExcludedSubdirectoryPaths.Add(newAccessLink);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveLink(object obj)
|
private void RemoveLink(object obj)
|
||||||
|
|
@ -197,11 +264,38 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private string? PromptUserSelectPath(ResultType type, string initialDirectory = null)
|
||||||
|
{
|
||||||
|
string path = null;
|
||||||
|
|
||||||
internal void RemoveLinkFromQuickAccess(AccessLink selectedRow) => Settings.QuickAccessLinks.Remove(selectedRow);
|
if (type is ResultType.Folder)
|
||||||
|
{
|
||||||
|
var folderBrowserDialog = new FolderBrowserDialog();
|
||||||
|
|
||||||
|
if (initialDirectory is not null)
|
||||||
|
folderBrowserDialog.InitialDirectory = initialDirectory;
|
||||||
|
|
||||||
|
if (folderBrowserDialog.ShowDialog() != DialogResult.OK)
|
||||||
|
return path;
|
||||||
|
|
||||||
|
path = folderBrowserDialog.SelectedPath;
|
||||||
|
}
|
||||||
|
else if (type is ResultType.File)
|
||||||
|
{
|
||||||
|
var openFileDialog = new OpenFileDialog();
|
||||||
|
if (initialDirectory is not null)
|
||||||
|
openFileDialog.InitialDirectory = initialDirectory;
|
||||||
|
|
||||||
|
if (openFileDialog.ShowDialog() != DialogResult.OK)
|
||||||
|
return path;
|
||||||
|
|
||||||
|
path = openFileDialog.FileName;
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
internal void RemoveAccessLinkFromExcludedIndexPaths(AccessLink selectedRow) => Settings.IndexSearchExcludedSubdirectoryPaths.Remove(selectedRow);
|
|
||||||
|
|
||||||
internal static void OpenWindowsIndexingOptions()
|
internal static void OpenWindowsIndexingOptions()
|
||||||
{
|
{
|
||||||
|
|
@ -215,22 +309,69 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
||||||
Process.Start(psi);
|
Process.Start(psi);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void UpdateActionKeyword(Settings.ActionKeyword modifiedActionKeyword, string newActionKeyword, string oldActionKeyword) =>
|
public bool UseWindowsIndexForDirectorySearch
|
||||||
PluginManager.ReplaceActionKeyword(Context.CurrentPluginMetadata.ID, oldActionKeyword, newActionKeyword);
|
{
|
||||||
|
get => Settings.UseWindowsIndexForDirectorySearch;
|
||||||
|
set => Settings.UseWindowsIndexForDirectorySearch = value;
|
||||||
|
}
|
||||||
|
public ICommand OpenEditorPath => new RelayCommand(_ =>
|
||||||
|
{
|
||||||
|
var path = PromptUserSelectPath(ResultType.File, Settings.EditorPath != null ? Path.GetDirectoryName(Settings.EditorPath) : null);
|
||||||
|
if (path is null)
|
||||||
|
return;
|
||||||
|
|
||||||
internal bool IsActionKeywordAlreadyAssigned(string newActionKeyword) => PluginManager.ActionKeywordRegistered(newActionKeyword);
|
EditorPath = path;
|
||||||
|
});
|
||||||
|
|
||||||
internal bool IsNewActionKeywordGlobal(string newActionKeyword) => newActionKeyword == Query.GlobalPluginWildcardSign;
|
public string EditorPath
|
||||||
|
{
|
||||||
public bool UseWindowsIndexForDirectorySearch {
|
get => Settings.EditorPath;
|
||||||
get
|
|
||||||
{
|
|
||||||
return Settings.UseWindowsIndexForDirectorySearch;
|
|
||||||
}
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Settings.UseWindowsIndexForDirectorySearch = value;
|
Settings.EditorPath = value;
|
||||||
|
OnPropertyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region Everything FastSortWarning
|
||||||
|
|
||||||
|
public Visibility FastSortWarningVisibility
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return EverythingApi.IsFastSortOption(Settings.SortOption) ? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
}
|
||||||
|
catch (IPCErrorException)
|
||||||
|
{
|
||||||
|
// this error occurs if the Everything service is not running, in this instance show the warning and
|
||||||
|
// update the message to let user know in the settings panel.
|
||||||
|
return Visibility.Visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string SortOptionWarningMessage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// this method is used to determine if Everything service is running because as at Everything v1.4.1
|
||||||
|
// the sdk does not provide a dedicated interface to determine if it is running.
|
||||||
|
return EverythingApi.IsFastSortOption(Settings.SortOption) ? string.Empty
|
||||||
|
: Context.API.GetTranslation("flowlauncher_plugin_everything_nonfastsort_warning");
|
||||||
|
}
|
||||||
|
catch (IPCErrorException)
|
||||||
|
{
|
||||||
|
return Context.API.GetTranslation("flowlauncher_plugin_everything_is_not_running");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
using Flow.Launcher.Plugin.Everything.Everything;
|
||||||
|
using Flow.Launcher.Plugin.Explorer.Helper;
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace Flow.Launcher.Plugin.Explorer.Views.Converters;
|
||||||
|
|
||||||
|
public class EnumNameConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
return value is SortOption option ? option.GetTranslatedName() : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
xmlns:qa="clr-namespace:Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks"
|
xmlns:qa="clr-namespace:Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks"
|
||||||
xmlns:viewModels="clr-namespace:Flow.Launcher.Plugin.Explorer.ViewModels"
|
xmlns:viewModels="clr-namespace:Flow.Launcher.Plugin.Explorer.ViewModels"
|
||||||
xmlns:views="clr-namespace:Flow.Launcher.Plugin.Explorer.Views"
|
xmlns:views="clr-namespace:Flow.Launcher.Plugin.Explorer.Views"
|
||||||
|
xmlns:converters="clr-namespace:Flow.Launcher.Plugin.Explorer.Views.Converters"
|
||||||
d:DataContext="{d:DesignInstance viewModels:SettingsViewModel}"
|
d:DataContext="{d:DesignInstance viewModels:SettingsViewModel}"
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
|
|
@ -15,7 +16,7 @@
|
||||||
<DataTemplate x:Key="ListViewTemplateAccessLinks" DataType="qa:AccessLink">
|
<DataTemplate x:Key="ListViewTemplateAccessLinks" DataType="qa:AccessLink">
|
||||||
<TextBlock Margin="0,5,0,5" Text="{Binding Path, Mode=OneTime}" />
|
<TextBlock Margin="0,5,0,5" Text="{Binding Path, Mode=OneTime}" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
<DataTemplate x:Key="ListViewActionKeywords" DataType="views:ActionKeywordView">
|
<DataTemplate x:Key="ListViewActionKeywords" DataType="{x:Type views:ActionKeywordModel}">
|
||||||
<Grid>
|
<Grid>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="0,5,0,0"
|
Margin="0,5,0,0"
|
||||||
|
|
@ -53,6 +54,7 @@
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
<converters:EnumNameConverter x:Key="EnumNameConverter" />
|
||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
<Grid Margin="10">
|
<Grid Margin="10">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
|
|
@ -61,32 +63,145 @@
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<StackPanel Grid.Row="0" Margin="20,35,0,0">
|
<StackPanel Grid.Row="0" Margin="20,35,0,0">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<Expander
|
<Expander
|
||||||
Header="{DynamicResource plugin_explorer_generalsetting_header}">
|
Margin="15"
|
||||||
|
Header="{DynamicResource plugin_explorer_generalsetting_header}"
|
||||||
|
Expanded="SettingExpander_OnExpanded"
|
||||||
|
Collapsed="SettingExpander_OnCollapsed">
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
|
<StackPanel.Resources>
|
||||||
|
<DataTemplate x:Key="EnumBindingModelItemTemplate">
|
||||||
|
<TextBlock Text="{Binding Description}" />
|
||||||
|
</DataTemplate>
|
||||||
|
</StackPanel.Resources>
|
||||||
<CheckBox
|
<CheckBox
|
||||||
Name="UseWindowsIndexForDirectorySearch"
|
|
||||||
Margin="12,10,0,0"
|
Margin="12,10,0,0"
|
||||||
Content="{DynamicResource plugin_explorer_usewindowsindexfordirectorysearch}"
|
Content="{DynamicResource plugin_explorer_usewindowsindexfordirectorysearch}"
|
||||||
IsChecked="{Binding UseWindowsIndexForDirectorySearch}"
|
IsChecked="{Binding UseWindowsIndexForDirectorySearch}"
|
||||||
ToolTip="{DynamicResource plugin_explorer_usewindowsindexfordirectorysearch_tooltip}" />
|
ToolTip="{DynamicResource plugin_explorer_usewindowsindexfordirectorysearch_tooltip}" />
|
||||||
<ComboBox
|
<CheckBox
|
||||||
Width="200"
|
Margin="12,10,0,0"
|
||||||
ItemsSource="{Binding Settings.SortOptions, Mode=OneWay}"
|
HorizontalAlignment="Left"
|
||||||
SelectedItem="{Binding Settings.SortOption}" />
|
Content="{DynamicResource plugin_explorer_use_location_as_working_dir}"
|
||||||
|
IsChecked="{Binding Settings.UseLocationAsWorkingDir}" />
|
||||||
|
<CheckBox
|
||||||
|
Margin="12,10,0,0"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Content="{DynamicResource plugin_explorer_launch_hidden}"
|
||||||
|
IsChecked="{Binding Settings.LaunchHidden}" />
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock
|
||||||
|
Margin="10,6,6,6"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="{DynamicResource plugin_explorer_editor_path}" />
|
||||||
|
<TextBox
|
||||||
|
Margin="15"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
TextWrapping="NoWrap"
|
||||||
|
MaxWidth="250"
|
||||||
|
Text="{Binding EditorPath}" />
|
||||||
|
<Button
|
||||||
|
MinWidth="50"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Margin="15"
|
||||||
|
Command="{Binding OpenEditorPath}"
|
||||||
|
Content="..." />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="Index Search Engine" />
|
||||||
|
<ComboBox
|
||||||
|
Margin="15"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Width="250"
|
||||||
|
ItemsSource="{Binding IndexSearchEngines }"
|
||||||
|
SelectedItem="{Binding SelectedIndexSearchEngine}"
|
||||||
|
ItemTemplate="{StaticResource EnumBindingModelItemTemplate}">
|
||||||
|
</ComboBox>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="Content Search Engine" />
|
||||||
|
<ComboBox
|
||||||
|
Margin="15"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Width="250"
|
||||||
|
ItemsSource="{Binding ContentIndexSearchEngines }"
|
||||||
|
SelectedItem="{Binding SelectedContentSearchEngine}"
|
||||||
|
ItemTemplate="{StaticResource EnumBindingModelItemTemplate}">
|
||||||
|
</ComboBox>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="Path Enumeration Engine" />
|
||||||
|
<ComboBox
|
||||||
|
Margin="15"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Width="250"
|
||||||
|
ItemsSource="{Binding PathEnumerationEngines }"
|
||||||
|
SelectedItem="{Binding SelectedPathEnumerationEngine}"
|
||||||
|
ItemTemplate="{StaticResource EnumBindingModelItemTemplate}">
|
||||||
|
</ComboBox>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Button
|
||||||
|
Margin="15"
|
||||||
|
Content="Open Window Index Option"
|
||||||
|
Click="btnOpenIndexingOptions_Click"/>
|
||||||
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Expander>
|
</Expander>
|
||||||
<Expander
|
<Expander
|
||||||
Name="expActionKeywords"
|
Margin="15"
|
||||||
|
Header="{DynamicResource plugin_explorer_everything_setting_header}"
|
||||||
|
Expanded="SettingExpander_OnExpanded"
|
||||||
|
Collapsed="SettingExpander_OnCollapsed">
|
||||||
|
<DockPanel>
|
||||||
|
<TextBlock
|
||||||
|
Text="{DynamicResource plugin_explorer_everything_sort_option}"
|
||||||
|
Margin="15" />
|
||||||
|
<ComboBox
|
||||||
|
DockPanel.Dock="Left"
|
||||||
|
Width="200"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
ItemsSource="{Binding Settings.SortOptions, Mode=OneWay}"
|
||||||
|
SelectedItem="{Binding Settings.SortOption}"
|
||||||
|
SelectionChanged="EverythingSortOptionChanged">
|
||||||
|
<ComboBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid>
|
||||||
|
<TextBlock Text="{Binding Converter={StaticResource EnumNameConverter}}" />
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ComboBox.ItemTemplate>
|
||||||
|
</ComboBox>
|
||||||
|
<TextBlock
|
||||||
|
Name="tbFastSortWarning"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
Margin="0 0 10 0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="Orange"
|
||||||
|
Text="{Binding SortOptionWarningMessage, Mode=OneTime}"
|
||||||
|
TextAlignment="Left"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Visibility="{Binding FastSortWarningVisibility, Mode=OneTime}" />
|
||||||
|
</DockPanel>
|
||||||
|
</Expander>
|
||||||
|
<Expander
|
||||||
|
Margin="15"
|
||||||
Height="auto"
|
Height="auto"
|
||||||
Expanded="expActionKeywords_Click"
|
Expanded="SettingExpander_OnExpanded"
|
||||||
|
Collapsed="SettingExpander_OnCollapsed"
|
||||||
Header="{DynamicResource plugin_explorer_manageactionkeywords_header}">
|
Header="{DynamicResource plugin_explorer_manageactionkeywords_header}">
|
||||||
<DockPanel HorizontalAlignment="Stretch">
|
<DockPanel HorizontalAlignment="Stretch">
|
||||||
<ListView
|
<ListView
|
||||||
x:Name="lbxActionKeywords"
|
|
||||||
DockPanel.Dock="Top"
|
DockPanel.Dock="Top"
|
||||||
ItemTemplate="{StaticResource ListViewActionKeywords}"
|
ItemTemplate="{StaticResource ListViewActionKeywords}"
|
||||||
SelectedItem="{Binding SelectedActionKeyword}"/>
|
ItemsSource="{Binding ActionKeywordsModels}"
|
||||||
|
SelectedItem="{Binding SelectedActionKeyword}" />
|
||||||
<Button
|
<Button
|
||||||
MinWidth="100"
|
MinWidth="100"
|
||||||
Margin="10"
|
Margin="10"
|
||||||
|
|
@ -95,81 +210,89 @@
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</Expander>
|
</Expander>
|
||||||
<Expander
|
<Expander
|
||||||
|
Margin="15"
|
||||||
|
Expanded="SettingExpander_OnExpanded"
|
||||||
|
Collapsed="SettingExpander_OnCollapsed"
|
||||||
Name="expAccessLinks"
|
Name="expAccessLinks"
|
||||||
Margin="0,10,0,0"
|
|
||||||
Header="{DynamicResource plugin_explorer_quickaccesslinks_header}">
|
Header="{DynamicResource plugin_explorer_quickaccesslinks_header}">
|
||||||
<DockPanel HorizontalAlignment="Stretch">
|
<ScrollViewer>
|
||||||
<ListView
|
<DockPanel HorizontalAlignment="Stretch">
|
||||||
x:Name="lbxAccessLinks"
|
<ListView
|
||||||
Height="200"
|
x:Name="lbxAccessLinks"
|
||||||
AllowDrop="True"
|
Height="200"
|
||||||
DockPanel.Dock="Top"
|
AllowDrop="True"
|
||||||
ItemTemplate="{StaticResource ListViewTemplateAccessLinks}"
|
DragEnter="lbxAccessLinks_DragEnter"
|
||||||
ItemsSource="{Binding Settings.QuickAccessLinks}"
|
Drop="LbxAccessLinks_OnDrop"
|
||||||
SelectedItem="{Binding SelectedQuickAccessLink}" />
|
DockPanel.Dock="Top"
|
||||||
<StackPanel
|
ItemTemplate="{StaticResource ListViewTemplateAccessLinks}"
|
||||||
HorizontalAlignment="Right"
|
ItemsSource="{Binding Settings.QuickAccessLinks}"
|
||||||
DockPanel.Dock="Bottom"
|
SelectedItem="{Binding SelectedQuickAccessLink}" />
|
||||||
Orientation="Horizontal">
|
<StackPanel
|
||||||
<Button
|
HorizontalAlignment="Right"
|
||||||
MinWidth="100"
|
DockPanel.Dock="Bottom"
|
||||||
Margin="10"
|
Orientation="Horizontal">
|
||||||
Command="{Binding RemoveLinkCommand}"
|
<Button
|
||||||
CommandParameter="QuickAccessLink"
|
MinWidth="100"
|
||||||
Content="{DynamicResource plugin_explorer_delete}" />
|
Margin="10"
|
||||||
<Button
|
Command="{Binding RemoveLinkCommand}"
|
||||||
MinWidth="100"
|
CommandParameter="QuickAccessLink"
|
||||||
Margin="10"
|
Content="{DynamicResource plugin_explorer_delete}" />
|
||||||
Command="{Binding EditLinkCommand}"
|
<Button
|
||||||
CommandParameter="QuickAccessLink"
|
MinWidth="100"
|
||||||
Content="{DynamicResource plugin_explorer_edit}" />
|
Margin="10"
|
||||||
<Button
|
Command="{Binding EditLinkCommand}"
|
||||||
MinWidth="100"
|
CommandParameter="QuickAccessLink"
|
||||||
Margin="10"
|
Content="{DynamicResource plugin_explorer_edit}" />
|
||||||
Command="{Binding AddLinkCommand}"
|
<Button
|
||||||
CommandParameter="QuickAccessLink"
|
MinWidth="100"
|
||||||
Content="{DynamicResource plugin_explorer_add}" />
|
Margin="10"
|
||||||
</StackPanel>
|
Command="{Binding AddLinkCommand}"
|
||||||
</DockPanel>
|
CommandParameter="QuickAccessLink"
|
||||||
|
Content="{DynamicResource plugin_explorer_add}" />
|
||||||
|
</StackPanel>
|
||||||
|
</DockPanel></ScrollViewer>
|
||||||
</Expander>
|
</Expander>
|
||||||
<Expander
|
<Expander
|
||||||
x:Name="expExcludedPaths"
|
Margin="15"
|
||||||
Margin="0,10,0,0"
|
Expanded="SettingExpander_OnExpanded"
|
||||||
|
Collapsed="SettingExpander_OnCollapsed"
|
||||||
Header="{DynamicResource plugin_explorer_indexsearchexcludedpaths_header}">
|
Header="{DynamicResource plugin_explorer_indexsearchexcludedpaths_header}">
|
||||||
<DockPanel HorizontalAlignment="Stretch">
|
<ScrollViewer>
|
||||||
<ListView
|
<DockPanel HorizontalAlignment="Stretch">
|
||||||
Name="lbxExcludedPaths"
|
<ListView
|
||||||
AllowDrop="True"
|
Name="lbxExcludedPaths"
|
||||||
DockPanel.Dock="Top"
|
AllowDrop="True"
|
||||||
DragEnter="lbxAccessLinks_DragEnter"
|
DockPanel.Dock="Top"
|
||||||
Drop="lbxAccessLinks_Drop"
|
DragEnter="lbxAccessLinks_DragEnter"
|
||||||
ItemTemplate="{StaticResource ListViewActionKeywords}"
|
Drop="LbxExcludedPaths_OnDrop"
|
||||||
ItemsSource="{Binding Settings.IndexSearchExcludedSubdirectoryPaths}"
|
ItemTemplate="{StaticResource ListViewActionKeywords}"
|
||||||
SelectedItem="{Binding SelectedIndexSearchExcludedPath}" />
|
ItemsSource="{Binding Settings.IndexSearchExcludedSubdirectoryPaths}"
|
||||||
<StackPanel
|
SelectedItem="{Binding SelectedIndexSearchExcludedPath}" />
|
||||||
HorizontalAlignment="Right"
|
<StackPanel
|
||||||
DockPanel.Dock="Bottom"
|
HorizontalAlignment="Right"
|
||||||
Orientation="Horizontal">
|
DockPanel.Dock="Bottom"
|
||||||
<Button
|
Orientation="Horizontal">
|
||||||
MinWidth="100"
|
<Button
|
||||||
Margin="10"
|
MinWidth="100"
|
||||||
Command="{Binding RemoveLinkCommand}"
|
Margin="10"
|
||||||
CommandParameter="IndexSearchExcludedPaths"
|
Command="{Binding RemoveLinkCommand}"
|
||||||
Content="{DynamicResource plugin_explorer_delete}" />
|
CommandParameter="IndexSearchExcludedPaths"
|
||||||
<Button
|
Content="{DynamicResource plugin_explorer_delete}" />
|
||||||
MinWidth="100"
|
<Button
|
||||||
Margin="10"
|
MinWidth="100"
|
||||||
Command="{Binding EditLinkCommand}"
|
Margin="10"
|
||||||
CommandParameter="IndexSearchExcludedPaths"
|
Command="{Binding EditLinkCommand}"
|
||||||
Content="{DynamicResource plugin_explorer_edit}" />
|
CommandParameter="IndexSearchExcludedPaths"
|
||||||
<Button
|
Content="{DynamicResource plugin_explorer_edit}" />
|
||||||
MinWidth="100"
|
<Button
|
||||||
Margin="10"
|
MinWidth="100"
|
||||||
Command="{Binding AddLinkCommand}"
|
Margin="10"
|
||||||
CommandParameter="IndexSearchExcludedPaths"
|
Command="{Binding AddLinkCommand}"
|
||||||
Content="{DynamicResource plugin_explorer_add}" />
|
CommandParameter="IndexSearchExcludedPaths"
|
||||||
</StackPanel>
|
Content="{DynamicResource plugin_explorer_add}" />
|
||||||
</DockPanel>
|
</StackPanel>
|
||||||
|
</DockPanel>
|
||||||
|
</ScrollViewer>
|
||||||
</Expander>
|
</Expander>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,14 @@ using System.ComponentModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
using DataFormats = System.Windows.DataFormats;
|
using DataFormats = System.Windows.DataFormats;
|
||||||
using DragDropEffects = System.Windows.DragDropEffects;
|
using DragDropEffects = System.Windows.DragDropEffects;
|
||||||
using DragEventArgs = System.Windows.DragEventArgs;
|
using DragEventArgs = System.Windows.DragEventArgs;
|
||||||
|
using ListView = System.Windows.Controls.ListView;
|
||||||
using MessageBox = System.Windows.MessageBox;
|
using MessageBox = System.Windows.MessageBox;
|
||||||
|
|
||||||
namespace Flow.Launcher.Plugin.Explorer.Views
|
namespace Flow.Launcher.Plugin.Explorer.Views
|
||||||
|
|
@ -23,6 +27,7 @@ namespace Flow.Launcher.Plugin.Explorer.Views
|
||||||
|
|
||||||
private List<ActionKeywordModel> actionKeywordsListView;
|
private List<ActionKeywordModel> actionKeywordsListView;
|
||||||
|
|
||||||
|
|
||||||
public ExplorerSettings(SettingsViewModel viewModel)
|
public ExplorerSettings(SettingsViewModel viewModel)
|
||||||
{
|
{
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
|
|
@ -33,105 +38,36 @@ namespace Flow.Launcher.Plugin.Explorer.Views
|
||||||
|
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
|
|
||||||
lbxAccessLinks.ItemsSource = this.viewModel.Settings.QuickAccessLinks;
|
|
||||||
|
|
||||||
lbxExcludedPaths.ItemsSource = this.viewModel.Settings.IndexSearchExcludedSubdirectoryPaths;
|
|
||||||
|
|
||||||
actionKeywordsListView = new List<ActionKeywordModel>
|
|
||||||
{
|
|
||||||
new(Settings.ActionKeyword.SearchActionKeyword,
|
|
||||||
viewModel.Context.API.GetTranslation("plugin_explorer_actionkeywordview_search")),
|
|
||||||
new(Settings.ActionKeyword.FileContentSearchActionKeyword,
|
|
||||||
viewModel.Context.API.GetTranslation("plugin_explorer_actionkeywordview_filecontentsearch")),
|
|
||||||
new(Settings.ActionKeyword.PathSearchActionKeyword,
|
|
||||||
viewModel.Context.API.GetTranslation("plugin_explorer_actionkeywordview_pathsearch")),
|
|
||||||
new(Settings.ActionKeyword.IndexSearchActionKeyword,
|
|
||||||
viewModel.Context.API.GetTranslation("plugin_explorer_actionkeywordview_indexsearch")),
|
|
||||||
new(Settings.ActionKeyword.QuickAccessActionKeyword,
|
|
||||||
viewModel.Context.API.GetTranslation("plugin_explorer_actionkeywordview_quickaccess"))
|
|
||||||
};
|
|
||||||
|
|
||||||
lbxActionKeywords.ItemsSource = actionKeywordsListView;
|
|
||||||
|
|
||||||
ActionKeywordModel.Init(viewModel.Settings);
|
ActionKeywordModel.Init(viewModel.Settings);
|
||||||
|
|
||||||
lbxAccessLinks.Items.SortDescriptions.Add(new SortDescription("Path", ListSortDirection.Ascending));
|
lbxAccessLinks.Items.SortDescriptions.Add(new SortDescription("Path", ListSortDirection.Ascending));
|
||||||
|
|
||||||
lbxExcludedPaths.Items.SortDescriptions.Add(new SortDescription("Path", ListSortDirection.Ascending));
|
lbxExcludedPaths.Items.SortDescriptions.Add(new SortDescription("Path", ListSortDirection.Ascending));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void expActionKeywords_Click(object sender, RoutedEventArgs e)
|
|
||||||
|
|
||||||
|
private void AccessLinkDragDrop(string containerName, DragEventArgs e)
|
||||||
{
|
{
|
||||||
if (expExcludedPaths.IsExpanded)
|
var files = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||||
expExcludedPaths.IsExpanded = false;
|
|
||||||
|
|
||||||
if (expAccessLinks.IsExpanded)
|
if (files == null || !files.Any())
|
||||||
expAccessLinks.IsExpanded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void expAccessLinks_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
if (expExcludedPaths.IsExpanded)
|
|
||||||
expExcludedPaths.IsExpanded = false;
|
|
||||||
|
|
||||||
if (expActionKeywords.IsExpanded)
|
|
||||||
expActionKeywords.IsExpanded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void expExcludedPaths_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
if (expAccessLinks.IsExpanded)
|
|
||||||
expAccessLinks.IsExpanded = false;
|
|
||||||
|
|
||||||
if (expActionKeywords.IsExpanded)
|
|
||||||
expActionKeywords.IsExpanded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void lbxAccessLinks_Drop(object sender, DragEventArgs e)
|
|
||||||
{
|
|
||||||
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
|
|
||||||
|
|
||||||
if (files != null && files.Count() > 0)
|
|
||||||
{
|
{
|
||||||
if (expAccessLinks.IsExpanded && viewModel.Settings.QuickAccessLinks == null)
|
return;
|
||||||
viewModel.Settings.QuickAccessLinks = new();
|
}
|
||||||
|
foreach (var s in files)
|
||||||
foreach (string s in files)
|
{
|
||||||
|
if (Directory.Exists(s))
|
||||||
{
|
{
|
||||||
if (Directory.Exists(s))
|
var newFolderLink = new AccessLink
|
||||||
{
|
{
|
||||||
var newFolderLink = new AccessLink { Path = s };
|
Path = s
|
||||||
|
};
|
||||||
AddAccessLink(newFolderLink);
|
viewModel.AppendLink(containerName, newFolderLink);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddAccessLink(AccessLink newAccessLink)
|
|
||||||
{
|
|
||||||
if (expAccessLinks.IsExpanded
|
|
||||||
&& !viewModel.Settings.QuickAccessLinks.Any(x => x.Path == newAccessLink.Path))
|
|
||||||
{
|
|
||||||
if (viewModel.Settings.QuickAccessLinks == null)
|
|
||||||
viewModel.Settings.QuickAccessLinks = new();
|
|
||||||
|
|
||||||
viewModel.Settings.QuickAccessLinks.Add(newAccessLink);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expExcludedPaths.IsExpanded
|
|
||||||
&& !viewModel.Settings.IndexSearchExcludedSubdirectoryPaths.Any(x => x.Path == newAccessLink.Path))
|
|
||||||
{
|
|
||||||
if (viewModel.Settings.IndexSearchExcludedSubdirectoryPaths == null)
|
|
||||||
viewModel.Settings.IndexSearchExcludedSubdirectoryPaths = new ();
|
|
||||||
|
|
||||||
viewModel.Settings.IndexSearchExcludedSubdirectoryPaths.Add(newAccessLink);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void lbxAccessLinks_DragEnter(object sender, DragEventArgs e)
|
private void lbxAccessLinks_DragEnter(object sender, DragEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||||
|
|
@ -148,5 +84,53 @@ namespace Flow.Launcher.Plugin.Explorer.Views
|
||||||
{
|
{
|
||||||
SettingsViewModel.OpenWindowsIndexingOptions();
|
SettingsViewModel.OpenWindowsIndexingOptions();
|
||||||
}
|
}
|
||||||
|
private void EverythingSortOptionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (tbFastSortWarning is not null)
|
||||||
|
{
|
||||||
|
tbFastSortWarning.Visibility = viewModel.FastSortWarningVisibility;
|
||||||
|
tbFastSortWarning.Text = viewModel.SortOptionWarningMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void SettingExpander_OnExpanded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is not Expander expander)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var parentContainer = VisualTreeHelper.GetParent(expander);
|
||||||
|
|
||||||
|
if (parentContainer is not StackPanel stackPanel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (UIElement child in stackPanel.Children)
|
||||||
|
{
|
||||||
|
if (child != expander)
|
||||||
|
child.Visibility = Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void SettingExpander_OnCollapsed(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is not Expander expander)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var parentContainer = VisualTreeHelper.GetParent(expander);
|
||||||
|
|
||||||
|
if (parentContainer is not StackPanel stackPanel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (UIElement child in stackPanel.Children)
|
||||||
|
{
|
||||||
|
if (child != expander)
|
||||||
|
child.Visibility = Visibility.Visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void LbxAccessLinks_OnDrop(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
AccessLinkDragDrop("QuickAccessLink", e);
|
||||||
|
}
|
||||||
|
private void LbxExcludedPaths_OnDrop(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
AccessLinkDragDrop("IndexSearchExcludedPath", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue