diff --git a/Plugins/Wox.Plugin.Program/AddProgramSource.xaml.cs b/Plugins/Wox.Plugin.Program/AddProgramSource.xaml.cs
index 063e1166a6..c79cb46cef 100644
--- a/Plugins/Wox.Plugin.Program/AddProgramSource.xaml.cs
+++ b/Plugins/Wox.Plugin.Program/AddProgramSource.xaml.cs
@@ -1,6 +1,8 @@
using System.Windows;
using System.Windows.Forms;
-using Wox.Plugin.Program.Programs;
+using Wox.Plugin.Program.Views.Models;
+using Wox.Plugin.Program.Views;
+using System.Linq;
namespace Wox.Plugin.Program
{
@@ -50,11 +52,17 @@ namespace Wox.Plugin.Program
}
if (_editing == null)
{
- var source = new Settings.ProgramSource
+ if (!ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == Directory.Text))
{
- Location = Directory.Text,
- };
- _settings.ProgramSources.Add(source);
+ var source = new ProgramSource
+ {
+ Location = Directory.Text,
+ UniqueIdentifier = Directory.Text
+ };
+
+ _settings.ProgramSources.Insert(0, source);
+ ProgramSetting.ProgramSettingDisplayList.Add(source);
+ }
}
else
{
diff --git a/Plugins/Wox.Plugin.Program/Images/disable.png b/Plugins/Wox.Plugin.Program/Images/disable.png
new file mode 100644
index 0000000000..e9d4976bcf
Binary files /dev/null and b/Plugins/Wox.Plugin.Program/Images/disable.png differ
diff --git a/Plugins/Wox.Plugin.Program/Languages/de.xaml b/Plugins/Wox.Plugin.Program/Languages/de.xaml
index 0a0f2bbe1e..cfcb43089d 100644
--- a/Plugins/Wox.Plugin.Program/Languages/de.xaml
+++ b/Plugins/Wox.Plugin.Program/Languages/de.xaml
@@ -21,7 +21,6 @@
Maximale Suchtiefe (-1 ist unlimitiert):
Bitte wähle eine Programmquelle
- Willst du wirklich {0} löschen?
Aktualisieren
Wox indexiert nur Datien mit folgenden Endungen:
diff --git a/Plugins/Wox.Plugin.Program/Languages/en.xaml b/Plugins/Wox.Plugin.Program/Languages/en.xaml
index bd75929412..bb218887c4 100644
--- a/Plugins/Wox.Plugin.Program/Languages/en.xaml
+++ b/Plugins/Wox.Plugin.Program/Languages/en.xaml
@@ -6,8 +6,10 @@
Delete
Edit
Add
+ Disable
Location
- Index file suffixes
+ All Programs
+ File Suffixes
Reindex
Indexing
Index Start Menu
@@ -21,20 +23,25 @@
Maximum Search Depth (-1 is unlimited):
Please select a program source
- Are you sure you want to delete {0}?
+ Are you sure you want to delete the selected program sources?
Update
Wox will only index files that end with the following suffixes:
- (Each suffix should split by ;)
+ (Each suffix should split by ';' )
Successfully updated file suffixes
File suffixes can't be empty
Run As Administrator
Open containing folder
+ Disable this program from displaying
Program
Search programs in Wox
Invalid Path
+
+
+ Success
+ Successfully disabled this program from displaying in your query
\ No newline at end of file
diff --git a/Plugins/Wox.Plugin.Program/Languages/pl.xaml b/Plugins/Wox.Plugin.Program/Languages/pl.xaml
index 6c01edb2b3..bb82ee8d2e 100644
--- a/Plugins/Wox.Plugin.Program/Languages/pl.xaml
+++ b/Plugins/Wox.Plugin.Program/Languages/pl.xaml
@@ -21,7 +21,6 @@
Maksymalna głębokość wyszukiwania (-1 to nieograniczona):
Musisz wybrać katalog programu
- Czy jesteś pewien że chcesz usunąć {0}?
Aktualizuj
Wox będzie indeksował tylko te pliki z podanymi rozszerzeniami:
diff --git a/Plugins/Wox.Plugin.Program/Languages/tr.xaml b/Plugins/Wox.Plugin.Program/Languages/tr.xaml
index 6ea921480d..ef01e29fd1 100644
--- a/Plugins/Wox.Plugin.Program/Languages/tr.xaml
+++ b/Plugins/Wox.Plugin.Program/Languages/tr.xaml
@@ -21,7 +21,6 @@
Maksimum Arama Derinliği (Limitsiz için -1):
İşlem yapmak istediğiniz klasörü seçin.
- {0} klasörünü silmek istediğinize emin misiniz?
Güncelle
Wox yalnızca aşağıdaki uzantılara sahip dosyaları indeksleyecektir:
diff --git a/Plugins/Wox.Plugin.Program/Languages/zh-cn.xaml b/Plugins/Wox.Plugin.Program/Languages/zh-cn.xaml
index cce2b7ac89..f41193095b 100644
--- a/Plugins/Wox.Plugin.Program/Languages/zh-cn.xaml
+++ b/Plugins/Wox.Plugin.Program/Languages/zh-cn.xaml
@@ -21,7 +21,6 @@
最大搜索深度(-1是无限的):
请先选择一项
- 你确定要删除{0}吗?
更新
Wox仅索引下列后缀的文件:
diff --git a/Plugins/Wox.Plugin.Program/Languages/zh-tw.xaml b/Plugins/Wox.Plugin.Program/Languages/zh-tw.xaml
index 631843b2f6..d3c0f18cca 100644
--- a/Plugins/Wox.Plugin.Program/Languages/zh-tw.xaml
+++ b/Plugins/Wox.Plugin.Program/Languages/zh-tw.xaml
@@ -21,7 +21,6 @@
最大搜尋深度(-1是無限的):
請先選擇一項
- 你確定要刪除{0}嗎?
更新
Wox 僅索引下列副檔名的檔案:
diff --git a/Plugins/Wox.Plugin.Program/Main.cs b/Plugins/Wox.Plugin.Program/Main.cs
index a6a891265a..e6bcc98687 100644
--- a/Plugins/Wox.Plugin.Program/Main.cs
+++ b/Plugins/Wox.Plugin.Program/Main.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
@@ -9,6 +9,7 @@ using Wox.Infrastructure;
using Wox.Infrastructure.Logger;
using Wox.Infrastructure.Storage;
using Wox.Plugin.Program.Programs;
+using Wox.Plugin.Program.Views;
using Stopwatch = Wox.Infrastructure.Stopwatch;
namespace Wox.Plugin.Program
@@ -16,14 +17,16 @@ namespace Wox.Plugin.Program
public class Main : ISettingProvider, IPlugin, IPluginI18n, IContextMenu, ISavable, IReloadable
{
private static readonly object IndexLock = new object();
- private static Win32[] _win32s;
- private static UWP.Application[] _uwps;
+ internal static Win32[] _win32s { get; set; }
+ internal static UWP.Application[] _uwps { get; set; }
+ internal static Settings _settings { get; set; }
+
+ private static bool IsStartupIndexProgramsRequired => _settings.LastIndexTime.AddDays(3) < DateTime.Today;
private static PluginInitContext _context;
private static BinaryStorage _win32Storage;
- private static BinaryStorage _uwpStorage;
- private static Settings _settings;
+ private static BinaryStorage _uwpStorage;
private readonly PluginJsonStorage _settingsStorage;
public Main()
@@ -40,10 +43,22 @@ namespace Wox.Plugin.Program
});
Log.Info($"|Wox.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Length}>");
Log.Info($"|Wox.Plugin.Program.Main|Number of preload uwps <{_uwps.Length}>");
- Task.Run(() =>
+
+ var a = Task.Run(() =>
{
- Stopwatch.Normal("|Wox.Plugin.Program.Main|Program index cost", IndexPrograms);
+ if (IsStartupIndexProgramsRequired || !_win32s.Any())
+ Stopwatch.Normal("|Wox.Plugin.Program.Main|Win32Program index cost", IndexWin32Programs);
});
+
+ var b = Task.Run(() =>
+ {
+ if (IsStartupIndexProgramsRequired || !_uwps.Any())
+ Stopwatch.Normal("|Wox.Plugin.Program.Main|Win32Program index cost", IndexUWPPrograms);
+ });
+
+ Task.WaitAll(a, b);
+
+ _settings.LastIndexTime = DateTime.Today;
}
public void Save()
@@ -57,8 +72,14 @@ namespace Wox.Plugin.Program
{
lock (IndexLock)
{
- var results1 = _win32s.AsParallel().Select(p => p.Result(query.Search, _context.API));
- var results2 = _uwps.AsParallel().Select(p => p.Result(query.Search, _context.API));
+ var results1 = _win32s.AsParallel()
+ .Where(p => p.Enabled)
+ .Select(p => p.Result(query.Search, _context.API));
+
+ var results2 = _uwps.AsParallel()
+ .Where(p => p.Enabled)
+ .Select(p => p.Result(query.Search, _context.API));
+
var result = results1.Concat(results2).Where(r => r.Score > 0).ToList();
return result;
}
@@ -69,39 +90,39 @@ namespace Wox.Plugin.Program
_context = context;
}
- public static void IndexPrograms()
+ public static void IndexWin32Programs()
{
- Win32[] w = { };
- UWP.Application[] u = { };
- var t1 = Task.Run(() =>
- {
- w = Win32.All(_settings);
- });
- var t2 = Task.Run(() =>
- {
- var windows10 = new Version(10, 0);
- var support = Environment.OSVersion.Version.Major >= windows10.Major;
- if (support)
- {
- u = UWP.All();
- }
- else
- {
- u = new UWP.Application[] { };
- }
- });
- Task.WaitAll(t1, t2);
-
lock (IndexLock)
{
- _win32s = w;
- _uwps = u;
+ _win32s = Win32.All(_settings);
}
}
+ public static void IndexUWPPrograms()
+ {
+ var windows10 = new Version(10, 0);
+ var support = Environment.OSVersion.Version.Major >= windows10.Major;
+
+ lock (IndexLock)
+ {
+ _uwps = support ? UWP.All() : new UWP.Application[] { };
+ }
+ }
+
+ public static void IndexPrograms()
+ {
+ var t1 = Task.Run(() => { IndexWin32Programs(); });
+
+ var t2 = Task.Run(() => { IndexUWPPrograms(); });
+
+ Task.WaitAll(t1, t2);
+
+ _settings.LastIndexTime = DateTime.Today;
+ }
+
public Control CreateSettingPanel()
{
- return new ProgramSetting(_context, _settings);
+ return new ProgramSetting(_context, _settings, _win32s, _uwps);
}
public string GetTranslatedPluginTitle()
@@ -116,16 +137,49 @@ namespace Wox.Plugin.Program
public List LoadContextMenus(Result selectedResult)
{
+ var menuOptions = new List();
var program = selectedResult.ContextData as IProgram;
if (program != null)
{
- var menus = program.ContextMenus(_context.API);
- return menus;
- }
- else
- {
- return new List();
+ menuOptions = program.ContextMenus(_context.API);
}
+
+ menuOptions.Add(
+ new Result
+ {
+ Title = _context.API.GetTranslation("wox_plugin_program_disable_program"),
+ Action = c =>
+ {
+ DisableProgram(program);
+ _context.API.ShowMsg(_context.API.GetTranslation("wox_plugin_program_disable_dlgtitle_success"),
+ _context.API.GetTranslation("wox_plugin_program_disable_dlgtitle_success_message"));
+ return false;
+ },
+ IcoPath = "Images/disable.png"
+ }
+ );
+
+ return menuOptions;
+ }
+
+ private void DisableProgram(IProgram ProgramToDelete)
+ {
+ if(_uwps.Any(x => x.UniqueIdentifier == ProgramToDelete.UniqueIdentifier))
+ _uwps.Where(x => x.UniqueIdentifier == ProgramToDelete.UniqueIdentifier).FirstOrDefault().Enabled = false;
+
+ if (_win32s.Any(x => x.UniqueIdentifier == ProgramToDelete.UniqueIdentifier))
+ _win32s.Where(x => x.UniqueIdentifier == ProgramToDelete.UniqueIdentifier).FirstOrDefault().Enabled = false;
+
+ _settings.DisabledProgramSources
+ .Add(
+ new Settings.DisabledProgramSource
+ {
+ Name = ProgramToDelete.Name,
+ Location = ProgramToDelete.Location,
+ UniqueIdentifier = ProgramToDelete.UniqueIdentifier,
+ Enabled = false
+ }
+ );
}
public static bool StartProcess(ProcessStartInfo info)
diff --git a/Plugins/Wox.Plugin.Program/ProgramSetting.xaml.cs b/Plugins/Wox.Plugin.Program/ProgramSetting.xaml.cs
deleted file mode 100644
index c69de7edab..0000000000
--- a/Plugins/Wox.Plugin.Program/ProgramSetting.xaml.cs
+++ /dev/null
@@ -1,149 +0,0 @@
-using System.IO;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using Wox.Plugin.Program.Programs;
-
-namespace Wox.Plugin.Program
-{
- ///
- /// Interaction logic for ProgramSetting.xaml
- ///
- public partial class ProgramSetting : UserControl
- {
- private PluginInitContext context;
- private Settings _settings;
-
- public ProgramSetting(PluginInitContext context, Settings settings)
- {
- this.context = context;
- InitializeComponent();
- Loaded += Setting_Loaded;
- _settings = settings;
- }
-
- private void Setting_Loaded(object sender, RoutedEventArgs e)
- {
- programSourceView.ItemsSource = _settings.ProgramSources;
- StartMenuEnabled.IsChecked = _settings.EnableStartMenuSource;
- RegistryEnabled.IsChecked = _settings.EnableRegistrySource;
- }
-
- private void ReIndexing()
- {
- programSourceView.Items.Refresh();
- Task.Run(() =>
- {
- Dispatcher.Invoke(() => { indexingPanel.Visibility = Visibility.Visible; });
- Main.IndexPrograms();
- Dispatcher.Invoke(() => { indexingPanel.Visibility = Visibility.Hidden; });
- });
- }
-
- private void btnAddProgramSource_OnClick(object sender, RoutedEventArgs e)
- {
- var add = new AddProgramSource(context, _settings);
- if(add.ShowDialog() ?? false)
- {
- ReIndexing();
- }
- }
-
- private void btnDeleteProgramSource_OnClick(object sender, RoutedEventArgs e)
- {
- var selectedProgramSource = programSourceView.SelectedItem as Settings.ProgramSource;
- if (selectedProgramSource != null)
- {
- string msg = string.Format(context.API.GetTranslation("wox_plugin_program_delete_program_source"), selectedProgramSource.Location);
-
- if (MessageBox.Show(msg, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
- {
- _settings.ProgramSources.Remove(selectedProgramSource);
- ReIndexing();
- }
- }
- else
- {
- string msg = context.API.GetTranslation("wox_plugin_program_pls_select_program_source");
- MessageBox.Show(msg);
- }
- }
-
- private void btnEditProgramSource_OnClick(object sender, RoutedEventArgs e)
- {
- var selectedProgramSource = programSourceView.SelectedItem as Settings.ProgramSource;
- if (selectedProgramSource != null)
- {
- var add = new AddProgramSource(selectedProgramSource, _settings);
- if (add.ShowDialog() ?? false)
- {
- ReIndexing();
- }
- }
- else
- {
- string msg = context.API.GetTranslation("wox_plugin_program_pls_select_program_source");
- MessageBox.Show(msg);
- }
- }
-
- private void btnReindex_Click(object sender, RoutedEventArgs e)
- {
- ReIndexing();
- }
-
- private void BtnProgramSuffixes_OnClick(object sender, RoutedEventArgs e)
- {
- var p = new ProgramSuffixes(context, _settings);
- if (p.ShowDialog() ?? false)
- {
- ReIndexing();
- }
- }
-
- private void programSourceView_DragEnter(object sender, DragEventArgs e)
- {
- if (e.Data.GetDataPresent(DataFormats.FileDrop))
- {
- e.Effects = DragDropEffects.Link;
- }
- else
- {
- e.Effects = DragDropEffects.None;
- }
- }
-
- private void programSourceView_Drop(object sender, DragEventArgs e)
- {
- string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
-
- if (files != null && files.Length > 0)
- {
- foreach (string s in files)
- {
- if (Directory.Exists(s))
- {
- _settings.ProgramSources.Add(new Settings.ProgramSource
- {
- Location = s
- });
-
- ReIndexing();
- }
- }
- }
- }
-
- private void StartMenuEnabled_Click(object sender, RoutedEventArgs e)
- {
- _settings.EnableStartMenuSource = StartMenuEnabled.IsChecked ?? false;
- ReIndexing();
- }
-
- private void RegistryEnabled_Click(object sender, RoutedEventArgs e)
- {
- _settings.EnableRegistrySource = RegistryEnabled.IsChecked ?? false;
- ReIndexing();
- }
- }
-}
\ No newline at end of file
diff --git a/Plugins/Wox.Plugin.Program/Programs/IProgram.cs b/Plugins/Wox.Plugin.Program/Programs/IProgram.cs
index 88d4eaaf0f..f51ab9610f 100644
--- a/Plugins/Wox.Plugin.Program/Programs/IProgram.cs
+++ b/Plugins/Wox.Plugin.Program/Programs/IProgram.cs
@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Collections.Generic;
namespace Wox.Plugin.Program.Programs
{
@@ -10,5 +6,8 @@ namespace Wox.Plugin.Program.Programs
{
List ContextMenus(IPublicAPI api);
Result Result(string query, IPublicAPI api);
+ string UniqueIdentifier { get; set; }
+ string Name { get; }
+ string Location { get; }
}
}
diff --git a/Plugins/Wox.Plugin.Program/Programs/UWP.cs b/Plugins/Wox.Plugin.Program/Programs/UWP.cs
index d5f72683f0..9a7bcccb99 100644
--- a/Plugins/Wox.Plugin.Program/Programs/UWP.cs
+++ b/Plugins/Wox.Plugin.Program/Programs/UWP.cs
@@ -160,7 +160,13 @@ namespace Wox.Plugin.Program.Programs
}
return u.Apps;
}).ToArray();
- return applications;
+
+ var updatedListWithoutDisabledApps = applications
+ .Where(t1 => !Main._settings.DisabledProgramSources
+ .Any(x => x.UniqueIdentifier == t1.UniqueIdentifier))
+ .Select(x => x);
+
+ return updatedListWithoutDisabledApps.ToArray();
}
else
{
@@ -229,11 +235,17 @@ namespace Wox.Plugin.Program.Programs
public class Application : IProgram
{
public string AppListEntry { get; set; }
+ public string UniqueIdentifier { get; set; }
public string DisplayName { get; set; }
public string Description { get; set; }
public string UserModelId { get; set; }
public string BackgroundColor { get; set; }
+ public string Name => DisplayName;
+ public string Location => Package.Location;
+
+ public bool Enabled { get; set; }
+
public string LogoUri { get; set; }
public string LogoPath { get; set; }
public UWP Package { get; set; }
@@ -321,6 +333,7 @@ namespace Wox.Plugin.Program.Programs
public Application(IAppxManifestApplication manifestApp, UWP package)
{
UserModelId = manifestApp.GetAppUserModelId();
+ UniqueIdentifier = manifestApp.GetAppUserModelId();
DisplayName = manifestApp.GetStringValue("DisplayName");
Description = manifestApp.GetStringValue("Description");
BackgroundColor = manifestApp.GetStringValue("BackgroundColor");
@@ -330,6 +343,8 @@ namespace Wox.Plugin.Program.Programs
Description = ResourceFromPri(package.FullName, Description);
LogoUri = LogoUriFromManifest(manifestApp);
LogoPath = LogoPathFromUri(LogoUri);
+
+ Enabled = true;
}
internal string ResourceFromPri(string packageFullName, string resourceReference)
diff --git a/Plugins/Wox.Plugin.Program/Programs/Win32.cs b/Plugins/Wox.Plugin.Program/Programs/Win32.cs
index 7b9b3a52f5..11ec701137 100644
--- a/Plugins/Wox.Plugin.Program/Programs/Win32.cs
+++ b/Plugins/Wox.Plugin.Program/Programs/Win32.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
@@ -18,12 +18,15 @@ namespace Wox.Plugin.Program.Programs
public class Win32 : IProgram
{
public string Name { get; set; }
+ public string UniqueIdentifier { get; set; }
public string IcoPath { get; set; }
public string FullPath { get; set; }
public string ParentDirectory { get; set; }
public string ExecutableName { get; set; }
public string Description { get; set; }
public bool Valid { get; set; }
+ public bool Enabled { get; set; }
+ public string Location => ParentDirectory;
private const string ShortcutExtension = "lnk";
private const string ApplicationReferenceExtension = "appref-ms";
@@ -127,9 +130,11 @@ namespace Wox.Plugin.Program.Programs
Name = Path.GetFileNameWithoutExtension(path),
IcoPath = path,
FullPath = path,
+ UniqueIdentifier = path,
ParentDirectory = Directory.GetParent(path).FullName,
Description = string.Empty,
- Valid = true
+ Valid = true,
+ Enabled = true
};
return p;
}
@@ -262,9 +267,16 @@ namespace Wox.Plugin.Program.Programs
private static ParallelQuery UnregisteredPrograms(List sources, string[] suffixes)
{
- var paths = sources.Where(s => Directory.Exists(s.Location))
- .SelectMany(s => ProgramPaths(s.Location, suffixes))
- .ToArray();
+ var listToAdd = new List();
+ sources.Where(s => Directory.Exists(s.Location) && s.Enabled)
+ .SelectMany(s => ProgramPaths(s.Location, suffixes))
+ .ToList()
+ .Where(t1 => !Main._settings.DisabledProgramSources.Any(x => t1 == x.UniqueIdentifier))
+ .ToList()
+ .ForEach(x => listToAdd.Add(x));
+
+ var paths = listToAdd.ToArray();
+
var programs1 = paths.AsParallel().Where(p => Extension(p) == ExeExtension).Select(ExeProgram);
var programs2 = paths.AsParallel().Where(p => Extension(p) == ShortcutExtension).Select(ExeProgram);
var programs3 = from p in paths.AsParallel()
@@ -276,11 +288,19 @@ namespace Wox.Plugin.Program.Programs
private static ParallelQuery StartMenuPrograms(string[] suffixes)
{
+ var disabledProgramsList = Main._settings.DisabledProgramSources;
+
var directory1 = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
var directory2 = Environment.GetFolderPath(Environment.SpecialFolder.CommonPrograms);
var paths1 = ProgramPaths(directory1, suffixes);
var paths2 = ProgramPaths(directory2, suffixes);
- var paths = paths1.Concat(paths2).ToArray();
+
+ var toFilter = paths1.Concat(paths2);
+ var paths = toFilter
+ .Where(t1 => !disabledProgramsList.Any(x => x.UniqueIdentifier == t1))
+ .Select(t1 => t1)
+ .ToArray();
+
var programs1 = paths.AsParallel().Where(p => Extension(p) == ShortcutExtension).Select(LnkProgram);
var programs2 = paths.AsParallel().Where(p => Extension(p) == ApplicationReferenceExtension).Select(Win32Program);
var programs = programs1.Concat(programs2).Where(p => p.Valid);
@@ -307,7 +327,12 @@ namespace Wox.Plugin.Program.Programs
programs.AddRange(ProgramsFromRegistryKey(root));
}
}
- var filtered = programs.AsParallel().Where(p => suffixes.Contains(Extension(p.ExecutableName)));
+
+ var disabledProgramsList = Main._settings.DisabledProgramSources;
+ var toFilter = programs.AsParallel().Where(p => suffixes.Contains(Extension(p.ExecutableName)));
+
+ var filtered = toFilter.Where(t1 => !disabledProgramsList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier)).Select(t1 => t1);
+
return filtered;
}
@@ -384,18 +409,20 @@ namespace Wox.Plugin.Program.Programs
public static Win32[] All(Settings settings)
{
ParallelQuery programs = new List().AsParallel();
+
+ var unregistered = UnregisteredPrograms(settings.ProgramSources, settings.ProgramSuffixes);
+ programs = programs.Concat(unregistered);
if (settings.EnableRegistrySource)
{
var appPaths = AppPathsPrograms(settings.ProgramSuffixes);
programs = programs.Concat(appPaths);
}
+
if (settings.EnableStartMenuSource)
{
var startMenu = StartMenuPrograms(settings.ProgramSuffixes);
programs = programs.Concat(startMenu);
- }
- var unregistered = UnregisteredPrograms(settings.ProgramSources, settings.ProgramSuffixes);
- programs = programs.Concat(unregistered);
+ }
//.Select(ScoreFilter);
return programs.ToArray();
}
diff --git a/Plugins/Wox.Plugin.Program/Settings.cs b/Plugins/Wox.Plugin.Program/Settings.cs
index 9c981a4e00..1ead3f9c32 100644
--- a/Plugins/Wox.Plugin.Program/Settings.cs
+++ b/Plugins/Wox.Plugin.Program/Settings.cs
@@ -1,11 +1,14 @@
-using System.Collections.Generic;
-using Wox.Plugin.Program.Programs;
+using System;
+using System.Collections.Generic;
+using System.IO;
namespace Wox.Plugin.Program
{
public class Settings
{
+ public DateTime LastIndexTime { get; set; }
public List ProgramSources { get; set; } = new List();
+ public List DisabledProgramSources { get; set; } = new List();
public string[] ProgramSuffixes { get; set; } = {"bat", "appref-ms", "exe", "lnk"};
public bool EnableStartMenuSource { get; set; } = true;
@@ -14,9 +17,24 @@ namespace Wox.Plugin.Program
internal const char SuffixSeperator = ';';
+ ///
+ /// Contains user added folder location contents as well as all user disabled applications
+ ///
+ ///
+ /// Win32 class applications set UniqueIdentifier using their full file path
+ /// UWP class applications set UniqueIdentifier using their Application User Model ID
+ /// Custom user added program sources set UniqueIdentifier using their location
+ ///
public class ProgramSource
{
+ private string name;
+
public string Location { get; set; }
+ public string Name { get => name ?? new DirectoryInfo(Location).Name; set => name = value; }
+ public bool Enabled { get; set; } = true;
+ public string UniqueIdentifier { get; set; }
}
+
+ public class DisabledProgramSource : ProgramSource { }
}
}
diff --git a/Plugins/Wox.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs b/Plugins/Wox.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs
new file mode 100644
index 0000000000..21bba677a5
--- /dev/null
+++ b/Plugins/Wox.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs
@@ -0,0 +1,149 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Wox.Plugin.Program.Views.Models;
+
+namespace Wox.Plugin.Program.Views.Commands
+{
+ internal static class ProgramSettingDisplay
+ {
+ internal static List LoadProgramSources(this List programSources)
+ {
+ var list = new List();
+
+ programSources.ForEach(x => list
+ .Add(
+ new ProgramSource
+ {
+ Enabled = x.Enabled,
+ Location = x.Location,
+ Name = x.Name,
+ UniqueIdentifier = x.UniqueIdentifier
+ }
+ ));
+
+ // Even though these are disabled, we still want to display them so users can enable later on
+ Main._settings
+ .DisabledProgramSources
+ .Where(t1 => !Main._settings
+ .ProgramSources // program sourcces added above already, so exlcude
+ .Any(x => t1.UniqueIdentifier == x.UniqueIdentifier))
+ .Select(x => x)
+ .ToList()
+ .ForEach(x => list
+ .Add(
+ new ProgramSource
+ {
+ Enabled = x.Enabled,
+ Location = x.Location,
+ Name = x.Name,
+ UniqueIdentifier = x.UniqueIdentifier
+ }
+ ));
+
+ return list;
+ }
+
+ internal static void LoadAllApplications(this List list)
+ {
+ Main._win32s
+ .Where(t1 => !ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier))
+ .ToList()
+ .ForEach(t1 => ProgramSetting.ProgramSettingDisplayList
+ .Add(
+ new ProgramSource
+ {
+ Name = t1.Name,
+ Location = t1.ParentDirectory,
+ UniqueIdentifier = t1.UniqueIdentifier,
+ Enabled = t1.Enabled
+ }
+ ));
+
+ Main._uwps
+ .Where(t1 => !ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier))
+ .ToList()
+ .ForEach(t1 => ProgramSetting.ProgramSettingDisplayList
+ .Add(
+ new ProgramSource
+ {
+ Name = t1.DisplayName,
+ Location = t1.Package.Location,
+ UniqueIdentifier = t1.UniqueIdentifier,
+ Enabled = t1.Enabled
+ }
+ ));
+ }
+
+ internal static void SetProgramSourcesStatus(this List list, List selectedProgramSourcesToDisable, bool status)
+ {
+ ProgramSetting.ProgramSettingDisplayList
+ .Where(t1 => selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier && t1.Enabled != status))
+ .ToList()
+ .ForEach(t1 => t1.Enabled = status);
+
+ Main._win32s
+ .Where(t1 => selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier && t1.Enabled != status))
+ .ToList()
+ .ForEach(t1 => t1.Enabled = status);
+
+ Main._uwps
+ .Where(t1 => selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier && t1.Enabled != status))
+ .ToList()
+ .ForEach(t1 => t1.Enabled = status);
+ }
+
+ internal static void StoreDisabledInSettings(this List list)
+ {
+ Main._settings.ProgramSources
+ .Where(t1 => ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier && !x.Enabled))
+ .ToList()
+ .ForEach(t1 => t1.Enabled = false);
+
+ ProgramSetting.ProgramSettingDisplayList
+ .Where(t1 => !t1.Enabled
+ && !Main._settings.DisabledProgramSources.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier))
+ .ToList()
+ .ForEach(x => Main._settings.DisabledProgramSources
+ .Add(
+ new Settings.DisabledProgramSource
+ {
+ Name = x.Name,
+ Location = x.Location,
+ UniqueIdentifier = x.UniqueIdentifier,
+ Enabled = false
+ }
+ ));
+ }
+
+ internal static void RemoveDisabledFromSettings(this List list)
+ {
+ Main._settings.ProgramSources
+ .Where(t1 => ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier && x.Enabled))
+ .ToList()
+ .ForEach(t1 => t1.Enabled = true);
+
+ Main._settings.DisabledProgramSources
+ .Where(t1 => ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier && x.Enabled))
+ .ToList()
+ .ForEach(x => Main._settings.DisabledProgramSources.Remove(x));
+ }
+
+ internal static bool IsReindexRequired(this List selectedItems)
+ {
+ if (selectedItems.Where(t1 => t1.Enabled && !Main._uwps.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier)).Count() > 0
+ && selectedItems.Where(t1 => t1.Enabled && !Main._win32s.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier)).Count() > 0)
+ return true;
+
+ // ProgramSources holds list of user added directories,
+ // so when we enable/disable we need to reindex to show/not show the programs
+ // that are found in those directories.
+ if (selectedItems.Where(t1 => Main._settings.ProgramSources.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier)).Count() > 0)
+ return true;
+
+ return false;
+ }
+ }
+}
diff --git a/Plugins/Wox.Plugin.Program/Views/Models/ProgramSource.cs b/Plugins/Wox.Plugin.Program/Views/Models/ProgramSource.cs
new file mode 100644
index 0000000000..c2995f74da
--- /dev/null
+++ b/Plugins/Wox.Plugin.Program/Views/Models/ProgramSource.cs
@@ -0,0 +1,5 @@
+
+namespace Wox.Plugin.Program.Views.Models
+{
+ public class ProgramSource : Settings.ProgramSource { }
+}
diff --git a/Plugins/Wox.Plugin.Program/ProgramSetting.xaml b/Plugins/Wox.Plugin.Program/Views/ProgramSetting.xaml
similarity index 56%
rename from Plugins/Wox.Plugin.Program/ProgramSetting.xaml
rename to Plugins/Wox.Plugin.Program/Views/ProgramSetting.xaml
index 2636e349f4..0fe8d3bd85 100644
--- a/Plugins/Wox.Plugin.Program/ProgramSetting.xaml
+++ b/Plugins/Wox.Plugin.Program/Views/ProgramSetting.xaml
@@ -1,4 +1,4 @@
-
-
+
-
-
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -41,9 +64,9 @@
-
-
+
+
diff --git a/Plugins/Wox.Plugin.Program/Views/ProgramSetting.xaml.cs b/Plugins/Wox.Plugin.Program/Views/ProgramSetting.xaml.cs
new file mode 100644
index 0000000000..72a4f57466
--- /dev/null
+++ b/Plugins/Wox.Plugin.Program/Views/ProgramSetting.xaml.cs
@@ -0,0 +1,307 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using Wox.Plugin.Program.Views.Models;
+using Wox.Plugin.Program.Views.Commands;
+using Wox.Plugin.Program.Programs;
+using System.ComponentModel;
+using System.Windows.Data;
+
+namespace Wox.Plugin.Program.Views
+{
+ ///
+ /// Interaction logic for ProgramSetting.xaml
+ ///
+ public partial class ProgramSetting : UserControl
+ {
+ private PluginInitContext context;
+ private Settings _settings;
+ private GridViewColumnHeader _lastHeaderClicked;
+ private ListSortDirection _lastDirection;
+
+ // We do not save all program sources to settings, so using
+ // this as temporary holder for displaying all loaded programs sources.
+ internal static List ProgramSettingDisplayList { get; set; }
+
+ public ProgramSetting(PluginInitContext context, Settings settings, Win32[] win32s, UWP.Application[] uwps)
+ {
+ this.context = context;
+ InitializeComponent();
+ Loaded += Setting_Loaded;
+ _settings = settings;
+ }
+
+ private void Setting_Loaded(object sender, RoutedEventArgs e)
+ {
+ ProgramSettingDisplayList = _settings.ProgramSources.LoadProgramSources();
+ programSourceView.ItemsSource = ProgramSettingDisplayList;
+
+ StartMenuEnabled.IsChecked = _settings.EnableStartMenuSource;
+ RegistryEnabled.IsChecked = _settings.EnableRegistrySource;
+ }
+
+ private void ReIndexing()
+ {
+ programSourceView.Items.Refresh();
+ Task.Run(() =>
+ {
+ Dispatcher.Invoke(() => { indexingPanel.Visibility = Visibility.Visible; });
+ Main.IndexPrograms();
+ Dispatcher.Invoke(() => { indexingPanel.Visibility = Visibility.Hidden; });
+ });
+ }
+
+ private void btnAddProgramSource_OnClick(object sender, RoutedEventArgs e)
+ {
+ var add = new AddProgramSource(context, _settings);
+ if(add.ShowDialog() ?? false)
+ {
+ ReIndexing();
+ }
+
+ programSourceView.Items.Refresh();
+ }
+
+ private void DeleteProgramSources(List itemsToDelete)
+ {
+ itemsToDelete.ForEach(t1 => _settings.ProgramSources
+ .Remove(_settings.ProgramSources
+ .Where(x => x.UniqueIdentifier == t1.UniqueIdentifier)
+ .FirstOrDefault()));
+ itemsToDelete.ForEach(x => ProgramSettingDisplayList.Remove(x));
+
+ ReIndexing();
+ }
+
+ private void btnEditProgramSource_OnClick(object sender, RoutedEventArgs e)
+ {
+ var selectedProgramSource = programSourceView.SelectedItem as Settings.ProgramSource;
+ if (selectedProgramSource != null)
+ {
+ var add = new AddProgramSource(selectedProgramSource, _settings);
+ if (add.ShowDialog() ?? false)
+ {
+ ReIndexing();
+ }
+ }
+ else
+ {
+ string msg = context.API.GetTranslation("wox_plugin_program_pls_select_program_source");
+ MessageBox.Show(msg);
+ }
+ }
+
+ private void btnReindex_Click(object sender, RoutedEventArgs e)
+ {
+ ReIndexing();
+ }
+
+ private void BtnProgramSuffixes_OnClick(object sender, RoutedEventArgs e)
+ {
+ var p = new ProgramSuffixes(context, _settings);
+ if (p.ShowDialog() ?? false)
+ {
+ ReIndexing();
+ }
+ }
+
+ private void programSourceView_DragEnter(object sender, DragEventArgs e)
+ {
+ if (e.Data.GetDataPresent(DataFormats.FileDrop))
+ {
+ e.Effects = DragDropEffects.Link;
+ }
+ else
+ {
+ e.Effects = DragDropEffects.None;
+ }
+ }
+
+ private void programSourceView_Drop(object sender, DragEventArgs e)
+ {
+ var directories = (string[])e.Data.GetData(DataFormats.FileDrop);
+
+ var directoriesToAdd = new List();
+
+ if (directories != null && directories.Length > 0)
+ {
+ foreach (string directory in directories)
+ {
+ if (Directory.Exists(directory) && !ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == directory))
+ {
+ var source = new ProgramSource
+ {
+ Location = directory,
+ UniqueIdentifier = directory
+ };
+
+ directoriesToAdd.Add(source);
+ }
+ }
+
+ if (directoriesToAdd.Count() > 0)
+ {
+ directoriesToAdd.ForEach(x => _settings.ProgramSources.Add(x));
+ directoriesToAdd.ForEach(x => ProgramSettingDisplayList.Add(x));
+
+ programSourceView.Items.Refresh();
+ ReIndexing();
+ }
+ }
+ }
+
+ private void StartMenuEnabled_Click(object sender, RoutedEventArgs e)
+ {
+ _settings.EnableStartMenuSource = StartMenuEnabled.IsChecked ?? false;
+ ReIndexing();
+ }
+
+ private void RegistryEnabled_Click(object sender, RoutedEventArgs e)
+ {
+ _settings.EnableRegistrySource = RegistryEnabled.IsChecked ?? false;
+ ReIndexing();
+ }
+
+ private void btnLoadAllProgramSource_OnClick(object sender, RoutedEventArgs e)
+ {
+ ProgramSettingDisplayList.LoadAllApplications();
+
+ programSourceView.Items.Refresh();
+ }
+
+ private void btnProgramSourceStatus_OnClick(object sender, RoutedEventArgs e)
+ {
+ var selectedItems = programSourceView
+ .SelectedItems.Cast()
+ .ToList();
+
+ if (selectedItems.Count() == 0)
+ {
+ string msg = context.API.GetTranslation("wox_plugin_program_pls_select_program_source");
+ MessageBox.Show(msg);
+ return;
+ }
+
+ if (selectedItems
+ .Where(t1 => !_settings
+ .ProgramSources
+ .Any(x => t1.UniqueIdentifier == x.UniqueIdentifier))
+ .Count() == 0)
+ {
+ var msg = string.Format(context.API.GetTranslation("wox_plugin_program_delete_program_source"));
+
+ if (MessageBox.Show(msg, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No)
+ {
+ return;
+ }
+
+ DeleteProgramSources(selectedItems);
+ }
+ else if (IsSelectedRowStatusEnabledMoreOrEqualThanDisabled(selectedItems))
+ {
+ ProgramSettingDisplayList.SetProgramSourcesStatus(selectedItems, false);
+
+ ProgramSettingDisplayList.StoreDisabledInSettings();
+ }
+ else
+ {
+ ProgramSettingDisplayList.SetProgramSourcesStatus(selectedItems, true);
+
+ ProgramSettingDisplayList.RemoveDisabledFromSettings();
+ }
+
+ if (selectedItems.IsReindexRequired())
+ ReIndexing();
+
+ programSourceView.SelectedItems.Clear();
+
+ programSourceView.Items.Refresh();
+ }
+
+ private void ProgramSourceView_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ programSourceView.SelectedItems.Clear();
+ }
+
+ private void GridViewColumnHeaderClickedHandler(object sender, RoutedEventArgs e)
+ {
+ var headerClicked = e.OriginalSource as GridViewColumnHeader;
+ ListSortDirection direction;
+
+ if (headerClicked != null)
+ {
+ if (headerClicked.Role != GridViewColumnHeaderRole.Padding)
+ {
+ if (headerClicked != _lastHeaderClicked)
+ {
+ direction = ListSortDirection.Ascending;
+ }
+ else
+ {
+ if (_lastDirection == ListSortDirection.Ascending)
+ {
+ direction = ListSortDirection.Descending;
+ }
+ else
+ {
+ direction = ListSortDirection.Ascending;
+ }
+ }
+
+ var columnBinding = headerClicked.Column.DisplayMemberBinding as Binding;
+ var sortBy = columnBinding?.Path.Path ?? headerClicked.Column.Header as string;
+
+ Sort(sortBy, direction);
+
+ _lastHeaderClicked = headerClicked;
+ _lastDirection = direction;
+ }
+ }
+ }
+
+ private void Sort(string sortBy, ListSortDirection direction)
+ {
+ var dataView = CollectionViewSource.GetDefaultView(programSourceView.ItemsSource);
+
+ dataView.SortDescriptions.Clear();
+ SortDescription sd = new SortDescription(sortBy, direction);
+ dataView.SortDescriptions.Add(sd);
+ dataView.Refresh();
+ }
+
+ private bool IsSelectedRowStatusEnabledMoreOrEqualThanDisabled(List selectedItems)
+ {
+ return selectedItems.Where(x => x.Enabled).Count() >= selectedItems.Where(x => !x.Enabled).Count();
+ }
+
+ private void Row_OnClick(object sender, RoutedEventArgs e)
+ {
+ var selectedItems = programSourceView
+ .SelectedItems.Cast()
+ .ToList();
+
+ if (selectedItems
+ .Where(t1 => !_settings
+ .ProgramSources
+ .Any(x => t1.UniqueIdentifier == x.UniqueIdentifier))
+ .Count() == 0)
+ {
+ btnProgramSourceStatus.Content = context.API.GetTranslation("wox_plugin_program_delete");
+ return;
+ }
+
+ if (IsSelectedRowStatusEnabledMoreOrEqualThanDisabled(selectedItems))
+ {
+ btnProgramSourceStatus.Content = "Disable";
+ }
+ else
+ {
+ btnProgramSourceStatus.Content = "Enable";
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj b/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj
index 322a873508..58b93f8c65 100644
--- a/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj
+++ b/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj
@@ -71,13 +71,15 @@
AddProgramSource.xaml
+
+
-
+
ProgramSetting.xaml
@@ -103,6 +105,9 @@
PreserveNewest
+
+ PreserveNewest
+
MSBuild:Compile
Designer
@@ -135,7 +140,7 @@
Designer
PreserveNewest
-
+
MSBuild:Compile
Designer