From 8662e963ac80155313d2dc1cd601cfd26201cd84 Mon Sep 17 00:00:00 2001 From: bao-qian Date: Sat, 7 Nov 2015 03:50:15 +0000 Subject: [PATCH 01/10] Misc --- .../PluginIndicator.cs | 5 +- Wox.Core/Plugin/PluginManager.cs | 48 ++++++++----------- Wox/Properties/Resources.Designer.cs | 26 +++++----- Wox/Properties/Settings.Designer.cs | 10 ++-- 4 files changed, 39 insertions(+), 50 deletions(-) diff --git a/Plugins/Wox.Plugin.PluginIndicator/PluginIndicator.cs b/Plugins/Wox.Plugin.PluginIndicator/PluginIndicator.cs index f7b2bd0314..f7f518889c 100644 --- a/Plugins/Wox.Plugin.PluginIndicator/PluginIndicator.cs +++ b/Plugins/Wox.Plugin.PluginIndicator/PluginIndicator.cs @@ -13,10 +13,9 @@ namespace Wox.Plugin.PluginIndicator public List Query(Query query) { - var results = from plugin in PluginManager.NonGlobalPlugins - select plugin.Metadata into metadata - from keyword in metadata.ActionKeywords + var results = from keyword in PluginManager.NonGlobalPlugins.Keys where keyword.StartsWith(query.Terms[0]) + let metadata = PluginManager.NonGlobalPlugins[keyword].Metadata let customizedPluginConfig = UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == metadata.ID) where customizedPluginConfig == null || !customizedPluginConfig.Disabled diff --git a/Wox.Core/Plugin/PluginManager.cs b/Wox.Core/Plugin/PluginManager.cs index 6123508c3a..bb7a700796 100644 --- a/Wox.Core/Plugin/PluginManager.cs +++ b/Wox.Core/Plugin/PluginManager.cs @@ -29,8 +29,8 @@ namespace Wox.Core.Plugin public static IEnumerable AllPlugins { get; private set; } - public static IEnumerable GlobalPlugins { get; private set; } - public static IEnumerable NonGlobalPlugins { get; private set; } + public static List GlobalPlugins { get; } = new List(); + public static Dictionary NonGlobalPlugins { get; } = new Dictionary(); private static IEnumerable InstantQueryPlugins { get; set; } public static IPublicAPI API { private set; get; } @@ -104,8 +104,20 @@ namespace Wox.Core.Plugin { InstantQueryPlugins = GetPluginsForInterface(); contextMenuPlugins = GetPluginsForInterface(); - GlobalPlugins = AllPlugins.Where(p => IsGlobalPlugin(p.Metadata)); - NonGlobalPlugins = AllPlugins.Where(p => !IsGlobalPlugin(p.Metadata)); + foreach (var plugin in AllPlugins) + { + if (IsGlobalPlugin(plugin.Metadata)) + { + GlobalPlugins.Add(plugin); + } + else + { + foreach (string actionKeyword in plugin.Metadata.ActionKeywords) + { + NonGlobalPlugins[actionKeyword] = plugin; + } + } + } }); } @@ -123,7 +135,7 @@ namespace Wox.Core.Plugin var search = rawQuery; List actionParameters = terms.ToList(); if (terms.Length == 0) return null; - if (IsVailldActionKeyword(terms[0])) + if (NonGlobalPlugins.ContainsKey(terms[0])) { actionKeyword = terms[0]; actionParameters = terms.Skip(1).ToList(); @@ -143,8 +155,8 @@ namespace Wox.Core.Plugin public static void QueryForAllPlugins(Query query) { - var pluginPairs = GetPluginForActionKeyword(query.ActionKeyword) != null ? - new List { GetPluginForActionKeyword(query.ActionKeyword) } : GlobalPlugins; + var pluginPairs = NonGlobalPlugins.ContainsKey(query.ActionKeyword) ? + new List { NonGlobalPlugins[query.ActionKeyword] } : GlobalPlugins; foreach (var plugin in pluginPairs) { var customizedPluginConfig = UserSettingStorage.Instance. @@ -187,21 +199,6 @@ namespace Wox.Core.Plugin } } - /// - /// Check if a query contains valid action keyword - /// - /// - /// - private static bool IsVailldActionKeyword(string actionKeyword) - { - if (string.IsNullOrEmpty(actionKeyword) || actionKeyword == Query.GlobalPluginWildcardSign) return false; - PluginPair pair = AllPlugins.FirstOrDefault(o => o.Metadata.ActionKeywords.Contains(actionKeyword)); - if (pair == null) return false; - var customizedPluginConfig = UserSettingStorage.Instance. - CustomizedPluginConfigs.FirstOrDefault(o => o.ID == pair.Metadata.ID); - return customizedPluginConfig == null || !customizedPluginConfig.Disabled; - } - private static bool IsGlobalPlugin(PluginMetadata metadata) { return metadata.ActionKeywords.Contains(Query.GlobalPluginWildcardSign); @@ -225,13 +222,6 @@ namespace Wox.Core.Plugin return AllPlugins.FirstOrDefault(o => o.Metadata.ID == id); } - private static PluginPair GetPluginForActionKeyword(string actionKeyword) - { - //if a query doesn't contain a vaild action keyword, it should be a query for system plugin - if (string.IsNullOrEmpty(actionKeyword) || actionKeyword == Query.GlobalPluginWildcardSign) return null; - return NonGlobalPlugins.FirstOrDefault(o => o.Metadata.ActionKeywords.Contains(actionKeyword)); - } - public static IEnumerable GetPluginsForInterface() where T : IFeatures { return AllPlugins.Where(p => p.Plugin is T); diff --git a/Wox/Properties/Resources.Designer.cs b/Wox/Properties/Resources.Designer.cs index 7665c71436..20e0fb2257 100644 --- a/Wox/Properties/Resources.Designer.cs +++ b/Wox/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// 此代码由工具生成。 -// 运行时版本:4.0.30319.0 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// 对此文件的更改可能会导致不正确的行为,并且如果 -// 重新生成代码,这些更改将会丢失。 +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ @@ -13,12 +13,12 @@ namespace Wox.Properties { /// - /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// A strongly-typed resource class, for looking up localized strings, etc. /// - // 此类是由 StronglyTypedResourceBuilder - // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 - // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen - // (以 /str 作为命令选项),或重新生成 VS 项目。 + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] @@ -33,7 +33,7 @@ namespace Wox.Properties { } /// - /// 返回此类使用的缓存的 ResourceManager 实例。 + /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ namespace Wox.Properties { } /// - /// 使用此强类型资源类,为所有资源查找 - /// 重写当前线程的 CurrentUICulture 属性。 + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { @@ -61,7 +61,7 @@ namespace Wox.Properties { } /// - /// 查找类似于 (Icon) 的 System.Drawing.Icon 类型的本地化资源。 + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). /// internal static System.Drawing.Icon app { get { diff --git a/Wox/Properties/Settings.Designer.cs b/Wox/Properties/Settings.Designer.cs index eb3d4dc309..7a4226349e 100644 --- a/Wox/Properties/Settings.Designer.cs +++ b/Wox/Properties/Settings.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// 此代码由工具生成。 -// 运行时版本:4.0.30319.0 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// 对此文件的更改可能会导致不正确的行为,并且如果 -// 重新生成代码,这些更改将会丢失。 +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ @@ -12,7 +12,7 @@ namespace Wox.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); From 7d52b0cc962ead79e24dafab88655487009c6387 Mon Sep 17 00:00:00 2001 From: bao-qian Date: Sat, 7 Nov 2015 03:50:26 +0000 Subject: [PATCH 02/10] Fix exclusive for action keyword --- Wox/Helper/ListBoxItems.cs | 29 ++++++++++++++++++++++++ Wox/MainWindow.xaml.cs | 45 ++++++++++++++++++++++++++++---------- Wox/ResultPanel.xaml.cs | 32 +++++++++++++++++---------- Wox/Wox.csproj | 5 ++++- 4 files changed, 86 insertions(+), 25 deletions(-) create mode 100644 Wox/Helper/ListBoxItems.cs diff --git a/Wox/Helper/ListBoxItems.cs b/Wox/Helper/ListBoxItems.cs new file mode 100644 index 0000000000..2a7f880bad --- /dev/null +++ b/Wox/Helper/ListBoxItems.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Linq; +using Wox.Plugin; + +namespace Wox.Helper +{ + class ListBoxItems : ObservableCollection + { + public void RemoveAll(Predicate predicate) + { + CheckReentrancy(); + + List itemsToRemove = Items.Where(x => predicate(x)).ToList(); + if (itemsToRemove.Count > 0) + { + itemsToRemove.ForEach(item => Items.Remove(item)); + + OnPropertyChanged(new PropertyChangedEventArgs("Count")); + OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); + // fuck ms http://blogs.msdn.com/b/nathannesbit/archive/2009/04/20/addrange-and-observablecollection.aspx + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + } + } + } +} diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs index 13481cd019..61d56a032b 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -43,11 +43,11 @@ namespace Wox private readonly Storyboard progressBarStoryboard = new Storyboard(); private NotifyIcon notifyIcon; - private bool queryHasReturn; - private string lastQuery; + private bool _queryHasReturn; + private Query _lastQuery = new Query(); private ToolTip toolTip = new ToolTip(); - private bool ignoreTextChange = false; + private bool _ignoreTextChange = false; private List CurrentContextMenus = new List(); private string textBeforeEnterContextMenuMode; @@ -72,7 +72,7 @@ namespace Wox { Dispatcher.Invoke(new Action(() => { - ignoreTextChange = true; + _ignoreTextChange = true; tbQuery.Text = query; tbQuery.CaretIndex = tbQuery.Text.Length; if (selectAll) @@ -441,10 +441,10 @@ namespace Wox private void TbQuery_OnTextChanged(object sender, TextChangedEventArgs e) { - - if (ignoreTextChange) { ignoreTextChange = false; return; } - if (!string.IsNullOrEmpty(tbQuery.Text.Trim())) + if (_ignoreTextChange) { _ignoreTextChange = false; return; } + string query = tbQuery.Text.Trim(); + if (!string.IsNullOrEmpty(query)) { toolTip.IsOpen = false; if (IsInContextMenuMode) @@ -453,10 +453,10 @@ namespace Wox return; } - Query(tbQuery.Text); + Query(query); Dispatcher.DelayInvoke("ShowProgressbar", () => { - if (!string.IsNullOrEmpty(tbQuery.Text.Trim()) && tbQuery.Text != lastQuery && !queryHasReturn) + if (!string.IsNullOrEmpty(query) && query != _lastQuery.RawQuery && !_queryHasReturn) { StartProgress(); } @@ -479,7 +479,28 @@ namespace Wox var query = PluginManager.QueryInit(text); if (query != null) { - lastQuery = query.RawQuery; + // handle the exclusiveness of plugin using action keyword + string lastKeyword = _lastQuery.ActionKeyword; + string keyword = query.ActionKeyword; + if (string.IsNullOrEmpty(lastKeyword)) + { + if (!string.IsNullOrEmpty(keyword)) + { + pnlResult.RemoveResultsExcept(PluginManager.NonGlobalPlugins[keyword]); + } + } + else + { + if (string.IsNullOrEmpty(keyword)) + { + pnlResult.RemoveResultsFor(PluginManager.NonGlobalPlugins[lastKeyword]); + } + else if (lastKeyword != keyword) + { + pnlResult.RemoveResultsExcept(PluginManager.NonGlobalPlugins[keyword]); + } + } + _lastQuery = query; PluginManager.QueryForAllPlugins(query); } StopProgress(); @@ -814,7 +835,7 @@ namespace Wox private void UpdateResultView(List list) { - queryHasReturn = true; + _queryHasReturn = true; progressBar.Dispatcher.Invoke(new Action(StopProgress)); if (list == null || list.Count == 0) return; @@ -824,7 +845,7 @@ namespace Wox { o.Score += UserSelectedRecordStorage.Instance.GetSelectedCount(o) * 5; }); - List l = list.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == lastQuery).ToList(); + List l = list.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == _lastQuery.RawQuery).ToList(); UpdateResultViewInternal(l); } } diff --git a/Wox/ResultPanel.xaml.cs b/Wox/ResultPanel.xaml.cs index 3115ece6ef..f3e0148fd7 100644 --- a/Wox/ResultPanel.xaml.cs +++ b/Wox/ResultPanel.xaml.cs @@ -9,6 +9,7 @@ using System.Windows.Media; using System.Linq; using System.Runtime.Remoting.Contexts; using Wox.Core.UserSettings; +using Wox.Helper; using Wox.Plugin; using Wox.Storage; @@ -20,7 +21,7 @@ namespace Wox public event Action LeftMouseClickEvent; public event Action RightMouseClickEvent; public event Action ItemDropEvent; - private readonly ObservableCollection _results; //todo, for better performance, override the default linear search + private readonly ListBoxItems _results; //todo, for better performance, override the default linear search private readonly object _resultsUpdateLock = new object(); protected virtual void OnRightMouseClick(Result result) @@ -38,6 +39,22 @@ namespace Wox public int MaxResultsToShow { get { return UserSettingStorage.Instance.MaxResultsToShow * 50; } } + internal void RemoveResultsFor(PluginPair plugin) + { + lock (_resultsUpdateLock) + { + _results.RemoveAll(r => r.PluginID == plugin.Metadata.ID); + } + } + + internal void RemoveResultsExcept(PluginPair plugin) + { + lock (_resultsUpdateLock) + { + _results.RemoveAll(r => r.PluginID != plugin.Metadata.ID); + } + } + public void AddResults(List newResults) { if (newResults != null && newResults.Count > 0) @@ -45,16 +62,7 @@ namespace Wox lock (_resultsUpdateLock) { var pluginId = newResults[0].PluginID; - var actionKeyword = newResults[0].OriginQuery.ActionKeyword; - List oldResults; - if (string.IsNullOrEmpty(actionKeyword)) - { - oldResults = _results.Where(r => r.PluginID == pluginId).ToList(); - } - else - { - oldResults = _results.ToList(); - } + var oldResults = _results.Where(r => r.PluginID == pluginId).ToList(); // intersection of A (old results) and B (new newResults) var intersection = oldResults.Intersect(newResults).ToList(); @@ -236,7 +244,7 @@ namespace Wox public ResultPanel() { InitializeComponent(); - _results = new ObservableCollection(); + _results = new ListBoxItems(); lbResults.ItemsSource = _results; } diff --git a/Wox/Wox.csproj b/Wox/Wox.csproj index ff6ac6882c..06d0cb7946 100644 --- a/Wox/Wox.csproj +++ b/Wox/Wox.csproj @@ -106,6 +106,7 @@ + @@ -280,7 +281,9 @@ ResXFileCodeGenerator Resources.Designer.cs - + + Designer + SettingsSingleFileGenerator Settings.Designer.cs From 705354a3d6617d1ad83e2499f9c3830e6b3a16fc Mon Sep 17 00:00:00 2001 From: bao-qian Date: Sat, 7 Nov 2015 17:32:58 +0000 Subject: [PATCH 03/10] Better logger 1. Throw exception for fatal/error log when debugging 2. Write to debug output for warn/debug/info log when debugging 3. part of #355 --- .../Wox.Plugin.Program/FileChangeWatcher.cs | 4 +-- .../ProgramSources/AppPathsProgramSource.cs | 2 +- .../ProgramSources/FileSystemProgramSource.cs | 4 ++- Plugins/Wox.Plugin.Program/Programs.cs | 9 ++--- Wox.Core/Plugin/CSharpPluginLoader.cs | 12 +++---- Wox.Core/Plugin/JsonRPCPlugin.cs | 2 +- Wox.Core/Plugin/PluginConfig.cs | 33 +++++-------------- Wox.Core/Plugin/PluginManager.cs | 22 ++++++------- Wox.Core/Theme/Theme.cs | 2 +- Wox.Core/Wox.Core.csproj | 7 ---- Wox.Core/i18n/Internationalization.cs | 10 ++---- .../Exception/ExceptionFormatter.cs | 0 .../Exception/WoxException.cs | 1 - .../Exception/WoxFatalException.cs | 4 +-- .../Exception/WoxHttpException.cs | 0 .../Exception/WoxI18nException.cs | 0 .../Exception/WoxJsonRPCException.cs | 0 .../Exception/WoxPluginException.cs | 4 +-- Wox.Infrastructure/Logger/Log.cs | 21 ++++++++---- Wox.Infrastructure/Stopwatch.cs | 11 ++----- Wox.Infrastructure/Wox.Infrastructure.csproj | 8 +++++ Wox.Test/Plugins/PluginInitTest.cs | 2 +- Wox.sln | 3 ++ Wox/Helper/ErrorReporting.cs | 2 +- Wox/Helper/ListBoxItems.cs | 6 +++- Wox/MainWindow.xaml.cs | 11 +++++-- 26 files changed, 85 insertions(+), 95 deletions(-) rename {Wox.Core => Wox.Infrastructure}/Exception/ExceptionFormatter.cs (100%) rename {Wox.Core => Wox.Infrastructure}/Exception/WoxException.cs (99%) rename Wox.Core/Exception/WoxCritialException.cs => Wox.Infrastructure/Exception/WoxFatalException.cs (62%) rename {Wox.Core => Wox.Infrastructure}/Exception/WoxHttpException.cs (100%) rename {Wox.Core => Wox.Infrastructure}/Exception/WoxI18nException.cs (100%) rename {Wox.Core => Wox.Infrastructure}/Exception/WoxJsonRPCException.cs (100%) rename {Wox.Core => Wox.Infrastructure}/Exception/WoxPluginException.cs (60%) diff --git a/Plugins/Wox.Plugin.Program/FileChangeWatcher.cs b/Plugins/Wox.Plugin.Program/FileChangeWatcher.cs index 4d258e74fc..cb3b315aa6 100644 --- a/Plugins/Wox.Plugin.Program/FileChangeWatcher.cs +++ b/Plugins/Wox.Plugin.Program/FileChangeWatcher.cs @@ -2,7 +2,7 @@ using System.Diagnostics; using System.IO; using System.Threading; - +using Wox.Infrastructure.Logger; namespace Wox.Plugin.Program { internal class FileChangeWatcher @@ -15,7 +15,7 @@ namespace Wox.Plugin.Program if (watchedPath.Contains(path)) return; if (!Directory.Exists(path)) { - Debug.WriteLine(string.Format("FileChangeWatcher: {0} doesn't exist", path)); + Log.Warn($"FileChangeWatcher: {path} doesn't exist"); return; } diff --git a/Plugins/Wox.Plugin.Program/ProgramSources/AppPathsProgramSource.cs b/Plugins/Wox.Plugin.Program/ProgramSources/AppPathsProgramSource.cs index 16e0961b3d..817f1e174f 100644 --- a/Plugins/Wox.Plugin.Program/ProgramSources/AppPathsProgramSource.cs +++ b/Plugins/Wox.Plugin.Program/ProgramSources/AppPathsProgramSource.cs @@ -57,7 +57,7 @@ namespace Wox.Plugin.Program.ProgramSources } catch (Exception e) { - Log.Error(e.StackTrace); + Log.Error(e); } } } diff --git a/Plugins/Wox.Plugin.Program/ProgramSources/FileSystemProgramSource.cs b/Plugins/Wox.Plugin.Program/ProgramSources/FileSystemProgramSource.cs index cb0cf7e765..f5571a18df 100644 --- a/Plugins/Wox.Plugin.Program/ProgramSources/FileSystemProgramSource.cs +++ b/Plugins/Wox.Plugin.Program/ProgramSources/FileSystemProgramSource.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Wox.Core.Exception; using Wox.Infrastructure.Logger; namespace Wox.Plugin.Program.ProgramSources @@ -70,7 +71,8 @@ namespace Wox.Plugin.Program.ProgramSources } catch (Exception e) { - Log.Warn(string.Format("GetAppFromDirectory failed: {0} - {1}", path, e.Message)); + var woxPluginException = new WoxPluginException("Program", $"GetAppFromDirectory failed: {path}", e); + Log.Error(woxPluginException); } } diff --git a/Plugins/Wox.Plugin.Program/Programs.cs b/Plugins/Wox.Plugin.Program/Programs.cs index 7f98198644..8ec1ea9a30 100644 --- a/Plugins/Wox.Plugin.Program/Programs.cs +++ b/Plugins/Wox.Plugin.Program/Programs.cs @@ -8,6 +8,7 @@ using System.Windows; using IWshRuntimeLibrary; using Wox.Infrastructure; using Wox.Plugin.Program.ProgramSources; +using Wox.Infrastructure.Logger; using Stopwatch = Wox.Infrastructure.Stopwatch; namespace Wox.Plugin.Program @@ -17,7 +18,7 @@ namespace Wox.Plugin.Program private static object lockObject = new object(); private static List programs = new List(); private static List sources = new List(); - private static Dictionary SourceTypes = new Dictionary() { + private static Dictionary SourceTypes = new Dictionary() { {"FileSystemProgramSource", typeof(FileSystemProgramSource)}, {"CommonStartMenuProgramSource", typeof(CommonStartMenuProgramSource)}, {"UserStartMenuProgramSource", typeof(UserStartMenuProgramSource)}, @@ -27,7 +28,7 @@ namespace Wox.Plugin.Program public List Query(Query query) { - + var fuzzyMather = FuzzyMatcher.Create(query.Search); List returnList = programs.Where(o => MatchProgram(o, fuzzyMather)).ToList(); returnList.ForEach(ScoreFilter); @@ -75,7 +76,7 @@ namespace Wox.Plugin.Program { programs = ProgramCacheStorage.Instance.Programs; }); - Debug.WriteLine($"Preload {programs.Count} programs from cache"); + Log.Info($"Preload {programs.Count} programs from cache"); Stopwatch.Debug("Program Index", IndexPrograms); } @@ -98,7 +99,7 @@ namespace Wox.Plugin.Program } sources.Clear(); - foreach(var source in programSources.Where(o => o.Enabled)) + foreach (var source in programSources.Where(o => o.Enabled)) { Type sourceClass; if (SourceTypes.TryGetValue(source.Type, out sourceClass)) diff --git a/Wox.Core/Plugin/CSharpPluginLoader.cs b/Wox.Core/Plugin/CSharpPluginLoader.cs index 7041d26c21..c5d1c78edc 100644 --- a/Wox.Core/Plugin/CSharpPluginLoader.cs +++ b/Wox.Core/Plugin/CSharpPluginLoader.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using Wox.Core.Exception; using Wox.Infrastructure.Logger; using Wox.Plugin; @@ -19,10 +20,10 @@ namespace Wox.Core.Plugin try { Assembly asm = Assembly.Load(AssemblyName.GetAssemblyName(metadata.ExecuteFilePath)); - List types = asm.GetTypes().Where(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Contains(typeof(IPlugin))).ToList(); + List types = asm.GetTypes().Where(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Contains(typeof(IPlugin))).ToList(); if (types.Count == 0) { - Log.Warn(string.Format("Couldn't load plugin {0}: didn't find the class that implement IPlugin", metadata.Name)); + Log.Warn($"Couldn't load plugin {metadata.Name}: didn't find the class that implement IPlugin"); continue; } @@ -39,12 +40,7 @@ namespace Wox.Core.Plugin } catch (System.Exception e) { - Log.Error(string.Format("Couldn't load plugin {0}: {1}", metadata.Name, e.Message)); -#if (DEBUG) - { - throw; - } -#endif + Log.Error(new WoxPluginException(metadata.Name, $"Couldn't load plugin", e)); } } diff --git a/Wox.Core/Plugin/JsonRPCPlugin.cs b/Wox.Core/Plugin/JsonRPCPlugin.cs index 6f65d78c93..a7d5db8cc5 100644 --- a/Wox.Core/Plugin/JsonRPCPlugin.cs +++ b/Wox.Core/Plugin/JsonRPCPlugin.cs @@ -74,7 +74,7 @@ namespace Wox.Core.Plugin } catch (System.Exception e) { - Log.Error(e.Message); + Log.Error(e); } } return null; diff --git a/Wox.Core/Plugin/PluginConfig.cs b/Wox.Core/Plugin/PluginConfig.cs index 63abe41ff4..05f72bbe64 100644 --- a/Wox.Core/Plugin/PluginConfig.cs +++ b/Wox.Core/Plugin/PluginConfig.cs @@ -47,7 +47,7 @@ namespace Wox.Core.Plugin } catch (System.Exception e) { - Log.Error(ExceptionFormatter.FormatExcpetion(e)); + Log.Fatal(e); } } PluginMetadata metadata = GetPluginMetadata(directory); @@ -63,7 +63,7 @@ namespace Wox.Core.Plugin string configPath = Path.Combine(pluginDirectory, pluginConfigName); if (!File.Exists(configPath)) { - Log.Warn(string.Format("parse plugin {0} failed: didn't find config file.", configPath)); + Log.Warn($"parse plugin {configPath} failed: didn't find config file."); return null; } @@ -77,40 +77,25 @@ namespace Wox.Core.Plugin // for plugin still use old ActionKeyword metadata.ActionKeyword = metadata.ActionKeywords?[0]; } - catch (System.Exception) + catch (System.Exception e) { - string error = string.Format("Parse plugin config {0} failed: json format is not valid", configPath); - Log.Warn(error); -#if (DEBUG) - { - throw new WoxException(error); - } -#endif + string msg = $"Parse plugin config {configPath} failed: json format is not valid"; + Log.Error(new WoxException(msg)); return null; } if (!AllowedLanguage.IsAllowed(metadata.Language)) { - string error = string.Format("Parse plugin config {0} failed: invalid language {1}", configPath, metadata.Language); - Log.Warn(error); -#if (DEBUG) - { - throw new WoxException(error); - } -#endif + string msg = $"Parse plugin config {configPath} failed: invalid language {metadata.Language}"; + Log.Error(new WoxException(msg)); return null; } if (!File.Exists(metadata.ExecuteFilePath)) { - string error = string.Format("Parse plugin config {0} failed: ExecuteFile {1} didn't exist", configPath, metadata.ExecuteFilePath); - Log.Warn(error); -#if (DEBUG) - { - throw new WoxException(error); - } -#endif + string msg = $"Parse plugin config {configPath} failed: ExecuteFile {metadata.ExecuteFilePath} didn't exist"; + Log.Error(new WoxException(msg)); return null; } diff --git a/Wox.Core/Plugin/PluginManager.cs b/Wox.Core/Plugin/PluginManager.cs index bb7a700796..06f10f7278 100644 --- a/Wox.Core/Plugin/PluginManager.cs +++ b/Wox.Core/Plugin/PluginManager.cs @@ -58,7 +58,7 @@ namespace Wox.Core.Plugin } catch (System.Exception e) { - Log.Error(e.Message); + Log.Error(e); } } } @@ -69,7 +69,7 @@ namespace Wox.Core.Plugin /// public static void Init(IPublicAPI api) { - if (api == null) throw new WoxCritialException("api is null"); + if (api == null) throw new WoxFatalException("api is null"); SetupPluginDirectories(); API = api; @@ -164,7 +164,7 @@ namespace Wox.Core.Plugin if (customizedPluginConfig != null && customizedPluginConfig.Disabled) continue; if (IsInstantQueryPlugin(plugin)) { - Stopwatch.Debug($"Instant Query for {plugin.Metadata.Name}", () => + Stopwatch.Normal($"Instant QueryForPlugin for {plugin.Metadata.Name}", () => { QueryForPlugin(plugin, query); }); @@ -173,7 +173,10 @@ namespace Wox.Core.Plugin { ThreadPool.QueueUserWorkItem(state => { - QueryForPlugin(plugin, query); + Stopwatch.Normal($"Normal QueryForPlugin for {plugin.Metadata.Name}", () => + { + QueryForPlugin(plugin, query); + }); }); } } @@ -184,7 +187,7 @@ namespace Wox.Core.Plugin try { List results = new List(); - var milliseconds = Stopwatch.Normal($"Query for {pair.Metadata.Name}", () => + var milliseconds = Stopwatch.Normal($"Plugin.Query cost for {pair.Metadata.Name}", () => { results = pair.Plugin.Query(query) ?? results; results.ForEach(o => { o.PluginID = pair.Metadata.ID; }); @@ -195,7 +198,7 @@ namespace Wox.Core.Plugin } catch (System.Exception e) { - throw new WoxPluginException(pair.Metadata.Name, e); + throw new WoxPluginException(pair.Metadata.Name, $"QueryForPlugin failed", e); } } @@ -239,12 +242,7 @@ namespace Wox.Core.Plugin } catch (System.Exception e) { - Log.Error($"Couldn't load plugin context menus {pluginPair.Metadata.Name}: {e.Message}"); -#if (DEBUG) - { - throw; - } -#endif + Log.Error(new WoxPluginException(pluginPair.Metadata.Name, $"Couldn't load plugin context menus", e)); } } diff --git a/Wox.Core/Theme/Theme.cs b/Wox.Core/Theme/Theme.cs index 114b5742c7..9d937b51b1 100644 --- a/Wox.Core/Theme/Theme.cs +++ b/Wox.Core/Theme/Theme.cs @@ -35,7 +35,7 @@ namespace Wox.Core.Theme } catch (System.Exception e) { - Log.Error(e.Message); + Log.Error(e); } } } diff --git a/Wox.Core/Wox.Core.csproj b/Wox.Core/Wox.Core.csproj index c7e8072a24..d69ae6a8d6 100644 --- a/Wox.Core/Wox.Core.csproj +++ b/Wox.Core/Wox.Core.csproj @@ -57,13 +57,6 @@ - - - - - - - diff --git a/Wox.Core/i18n/Internationalization.cs b/Wox.Core/i18n/Internationalization.cs index cc0d80e837..d94044a821 100644 --- a/Wox.Core/i18n/Internationalization.cs +++ b/Wox.Core/i18n/Internationalization.cs @@ -32,7 +32,7 @@ namespace Wox.Core.i18n } catch (System.Exception e) { - Log.Error(e.Message); + Log.Error(e); } } } @@ -122,12 +122,8 @@ namespace Wox.Core.i18n } catch (System.Exception e) { - Log.Warn("Update Plugin metadata translation failed:" + e.Message); -#if (DEBUG) - { - throw; - } -#endif + var woxPluginException = new WoxPluginException(pluginPair.Metadata.Name, "Update Plugin metadata translation failed:", e); + Log.Error(woxPluginException); } } diff --git a/Wox.Core/Exception/ExceptionFormatter.cs b/Wox.Infrastructure/Exception/ExceptionFormatter.cs similarity index 100% rename from Wox.Core/Exception/ExceptionFormatter.cs rename to Wox.Infrastructure/Exception/ExceptionFormatter.cs diff --git a/Wox.Core/Exception/WoxException.cs b/Wox.Infrastructure/Exception/WoxException.cs similarity index 99% rename from Wox.Core/Exception/WoxException.cs rename to Wox.Infrastructure/Exception/WoxException.cs index 2840e34aaa..bd23429ab6 100644 --- a/Wox.Core/Exception/WoxException.cs +++ b/Wox.Infrastructure/Exception/WoxException.cs @@ -14,7 +14,6 @@ public WoxException(string msg, System.Exception innerException) : base(msg, innerException) { - } } } diff --git a/Wox.Core/Exception/WoxCritialException.cs b/Wox.Infrastructure/Exception/WoxFatalException.cs similarity index 62% rename from Wox.Core/Exception/WoxCritialException.cs rename to Wox.Infrastructure/Exception/WoxFatalException.cs index cf840f9b19..21984f18d4 100644 --- a/Wox.Core/Exception/WoxCritialException.cs +++ b/Wox.Infrastructure/Exception/WoxFatalException.cs @@ -3,9 +3,9 @@ /// /// Represent exceptions that wox can't handle and MUST close running Wox. /// - public class WoxCritialException : WoxException + public class WoxFatalException : WoxException { - public WoxCritialException(string msg) : base(msg) + public WoxFatalException(string msg) : base(msg) { } } diff --git a/Wox.Core/Exception/WoxHttpException.cs b/Wox.Infrastructure/Exception/WoxHttpException.cs similarity index 100% rename from Wox.Core/Exception/WoxHttpException.cs rename to Wox.Infrastructure/Exception/WoxHttpException.cs diff --git a/Wox.Core/Exception/WoxI18nException.cs b/Wox.Infrastructure/Exception/WoxI18nException.cs similarity index 100% rename from Wox.Core/Exception/WoxI18nException.cs rename to Wox.Infrastructure/Exception/WoxI18nException.cs diff --git a/Wox.Core/Exception/WoxJsonRPCException.cs b/Wox.Infrastructure/Exception/WoxJsonRPCException.cs similarity index 100% rename from Wox.Core/Exception/WoxJsonRPCException.cs rename to Wox.Infrastructure/Exception/WoxJsonRPCException.cs diff --git a/Wox.Core/Exception/WoxPluginException.cs b/Wox.Infrastructure/Exception/WoxPluginException.cs similarity index 60% rename from Wox.Core/Exception/WoxPluginException.cs rename to Wox.Infrastructure/Exception/WoxPluginException.cs index e435be5cdd..bc1854f564 100644 --- a/Wox.Core/Exception/WoxPluginException.cs +++ b/Wox.Infrastructure/Exception/WoxPluginException.cs @@ -4,8 +4,8 @@ { public string PluginName { get; set; } - public WoxPluginException(string pluginName,System.Exception e) - : base(e.Message,e) + public WoxPluginException(string pluginName, string msg, System.Exception e) + : base($"{msg}: {pluginName}", e) { PluginName = pluginName; } diff --git a/Wox.Infrastructure/Logger/Log.cs b/Wox.Infrastructure/Logger/Log.cs index 8abaf16a4f..e03c7045bc 100644 --- a/Wox.Infrastructure/Logger/Log.cs +++ b/Wox.Infrastructure/Logger/Log.cs @@ -1,5 +1,6 @@ using System; using NLog; +using Wox.Core.Exception; namespace Wox.Infrastructure.Logger { @@ -7,34 +8,40 @@ namespace Wox.Infrastructure.Logger { private static NLog.Logger logger = LogManager.GetCurrentClassLogger(); - public static void Error(string msg) - { - logger.Error(msg); - } - public static void Error(Exception e) { +#if DEBUG + throw e; +#else logger.Error(e.Message + "\r\n" + e.StackTrace); +#endif } public static void Debug(string msg) { + System.Diagnostics.Debug.WriteLine($"DEBUG: {msg}"); logger.Debug(msg); } public static void Info(string msg) { + System.Diagnostics.Debug.WriteLine($"INFO: {msg}"); logger.Info(msg); } public static void Warn(string msg) { + System.Diagnostics.Debug.WriteLine($"WARN: {msg}"); logger.Warn(msg); } - public static void Fatal(string msg) + public static void Fatal(Exception e) { - logger.Fatal(msg); +#if DEBUG + throw e; +#else + logger.Fatal(ExceptionFormatter.FormatExcpetion(e)); +#endif } } } diff --git a/Wox.Infrastructure/Stopwatch.cs b/Wox.Infrastructure/Stopwatch.cs index c0d8288540..7387734d5b 100644 --- a/Wox.Infrastructure/Stopwatch.cs +++ b/Wox.Infrastructure/Stopwatch.cs @@ -18,14 +18,6 @@ namespace Wox.Infrastructure #endif } - [Conditional("DEBUG")] - private static void WriteTimeInfo(string name, long milliseconds) - { - string info = $"{name} : {milliseconds}ms"; - System.Diagnostics.Debug.WriteLine(info); - Log.Info(info); - } - /// /// This stopwatch will also appear only in Debug mode /// @@ -36,7 +28,8 @@ namespace Wox.Infrastructure action(); stopWatch.Stop(); var milliseconds = stopWatch.ElapsedMilliseconds; - WriteTimeInfo(name, milliseconds); + string info = $"{name} : {milliseconds}ms"; + Log.Debug(info); return milliseconds; } diff --git a/Wox.Infrastructure/Wox.Infrastructure.csproj b/Wox.Infrastructure/Wox.Infrastructure.csproj index e3740ee2cc..31100d3ae4 100644 --- a/Wox.Infrastructure/Wox.Infrastructure.csproj +++ b/Wox.Infrastructure/Wox.Infrastructure.csproj @@ -46,9 +46,17 @@ + + + + + + + + diff --git a/Wox.Test/Plugins/PluginInitTest.cs b/Wox.Test/Plugins/PluginInitTest.cs index 3bb5658c5e..e23fa54322 100644 --- a/Wox.Test/Plugins/PluginInitTest.cs +++ b/Wox.Test/Plugins/PluginInitTest.cs @@ -11,7 +11,7 @@ namespace Wox.Test.Plugins [Test] public void PublicAPIIsNullTest() { - Assert.Throws(typeof(WoxCritialException), () => PluginManager.Init(null)); + Assert.Throws(typeof(WoxFatalException), () => PluginManager.Init(null)); } } } diff --git a/Wox.sln b/Wox.sln index d50b7e3b37..efad41543f 100644 --- a/Wox.sln +++ b/Wox.sln @@ -62,6 +62,9 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin.Everything", "Plugins\Wox.Plugin.Everything\Wox.Plugin.Everything.csproj", "{230AE83F-E92E-4E69-8355-426B305DA9C0}" EndProject Global + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU diff --git a/Wox/Helper/ErrorReporting.cs b/Wox/Helper/ErrorReporting.cs index e7b5a81fb9..63c6f80dc8 100644 --- a/Wox/Helper/ErrorReporting.cs +++ b/Wox/Helper/ErrorReporting.cs @@ -9,7 +9,7 @@ namespace Wox.Helper { public static void Report(Exception e) { - Log.Error(ExceptionFormatter.FormatExcpetion(e)); + Log.Fatal(e); new CrashReporter.CrashReporter(e).Show(); } diff --git a/Wox/Helper/ListBoxItems.cs b/Wox/Helper/ListBoxItems.cs index 2a7f880bad..103630d6e4 100644 --- a/Wox/Helper/ListBoxItems.cs +++ b/Wox/Helper/ListBoxItems.cs @@ -9,6 +9,7 @@ using Wox.Plugin; namespace Wox.Helper { class ListBoxItems : ObservableCollection + // todo implement custom moveItem,removeItem,insertItem { public void RemoveAll(Predicate predicate) { @@ -21,7 +22,10 @@ namespace Wox.Helper OnPropertyChanged(new PropertyChangedEventArgs("Count")); OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); - // fuck ms http://blogs.msdn.com/b/nathannesbit/archive/2009/04/20/addrange-and-observablecollection.aspx + // fuck ms + // http://blogs.msdn.com/b/nathannesbit/archive/2009/04/20/addrange-and-observablecollection.aspx + // http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/listcollectionviewcollectionview-doesnt-support-notifycollectionchanged-with-multiple-items.aspx + // PS: don't use Reset for other data updates, it will cause UI flickering OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } } diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs index 61d56a032b..71204acde8 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -32,6 +32,7 @@ using IDataObject = System.Windows.IDataObject; using KeyEventArgs = System.Windows.Input.KeyEventArgs; using MenuItem = System.Windows.Forms.MenuItem; using MessageBox = System.Windows.MessageBox; +using Stopwatch = Wox.Infrastructure.Stopwatch; using ToolTip = System.Windows.Controls.ToolTip; namespace Wox @@ -852,10 +853,14 @@ namespace Wox private void UpdateResultViewInternal(List list) { - Dispatcher.Invoke(new Action(() => + if (list != null && list.Count > 0) { - pnlResult.AddResults(list); - })); + Dispatcher.Invoke(new Action(() => + { + Stopwatch.Normal($"UI update cost for {list[0].PluginDirectory.Split('\\').Last()}", + () =>{pnlResult.AddResults(list);}); + })); + } } private Result GetTopMostContextMenu(Result result) From 9627272b57d1ce0a66cdfed6d56f79c4fcfb570a Mon Sep 17 00:00:00 2001 From: bao-qian Date: Sat, 7 Nov 2015 20:48:18 +0000 Subject: [PATCH 04/10] Fix clearance of old results part of #350 --- Wox/MainWindow.xaml.cs | 60 ++++++++++++++++---------------- Wox/ResultPanel.xaml.cs | 73 ++++++++++++++++++--------------------- Wox/SettingWindow.xaml.cs | 2 +- 3 files changed, 65 insertions(+), 70 deletions(-) diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs index 71204acde8..d842aa2fdb 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -163,7 +163,7 @@ namespace Wox o.PluginID = plugin.ID; o.OriginQuery = query; }); - UpdateResultView(results); + UpdateResultView(results, plugin, query); } public void ShowContextMenu(PluginMetadata plugin, List results) @@ -177,7 +177,7 @@ namespace Wox o.ContextMenu = null; }); pnlContextMenu.Clear(); - pnlContextMenu.AddResults(results); + pnlContextMenu.AddResults(results, plugin.ID); pnlContextMenu.Visibility = Visibility.Visible; pnlResult.Visibility = Visibility.Collapsed; } @@ -419,11 +419,12 @@ namespace Wox private void QueryContextMenu() { + var contextMenuId = "Context Menu Id"; pnlContextMenu.Clear(); var query = tbQuery.Text.ToLower(); if (string.IsNullOrEmpty(query)) { - pnlContextMenu.AddResults(CurrentContextMenus); + pnlContextMenu.AddResults(CurrentContextMenus, contextMenuId); } else { @@ -436,7 +437,7 @@ namespace Wox filterResults.Add(contextMenu); } } - pnlContextMenu.AddResults(filterResults); + pnlContextMenu.AddResults(filterResults, contextMenuId); } } @@ -445,15 +446,14 @@ namespace Wox if (_ignoreTextChange) { _ignoreTextChange = false; return; } string query = tbQuery.Text.Trim(); + toolTip.IsOpen = false; + if (IsInContextMenuMode) + { + QueryContextMenu(); + return; + } if (!string.IsNullOrEmpty(query)) { - toolTip.IsOpen = false; - if (IsInContextMenuMode) - { - QueryContextMenu(); - return; - } - Query(query); Dispatcher.DelayInvoke("ShowProgressbar", () => { @@ -738,6 +738,11 @@ namespace Wox { if (history != null) { + var historyMetadata = new PluginMetadata + { + ID = "Query history", + Name = "Query history" + }; ChangeQueryText(history.Query, true); var executeQueryHistoryTitle = GetTranslation("executeQuery"); var lastExecuteTime = GetTranslation("lastExecuteTime"); @@ -753,7 +758,7 @@ namespace Wox return false; } } - }); + }, historyMetadata); } } @@ -834,33 +839,28 @@ namespace Wox } } - private void UpdateResultView(List list) + private void UpdateResultView(List list, PluginMetadata metadata, Query originQuery) { _queryHasReturn = true; progressBar.Dispatcher.Invoke(new Action(StopProgress)); - if (list == null || list.Count == 0) return; - if (list.Count > 0) + list.ForEach(o => { - list.ForEach(o => - { - o.Score += UserSelectedRecordStorage.Instance.GetSelectedCount(o) * 5; - }); - List l = list.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == _lastQuery.RawQuery).ToList(); - UpdateResultViewInternal(l); + o.Score += UserSelectedRecordStorage.Instance.GetSelectedCount(o) * 5; + }); + if (originQuery.RawQuery == _lastQuery.RawQuery) + { + UpdateResultViewInternal(list, metadata); } } - private void UpdateResultViewInternal(List list) + private void UpdateResultViewInternal(List list, PluginMetadata metadata) { - if (list != null && list.Count > 0) + Dispatcher.Invoke(new Action(() => { - Dispatcher.Invoke(new Action(() => - { - Stopwatch.Normal($"UI update cost for {list[0].PluginDirectory.Split('\\').Last()}", - () =>{pnlResult.AddResults(list);}); - })); - } + Stopwatch.Normal($"UI update cost for {metadata.Name}", + () => { pnlResult.AddResults(list, metadata.ID); }); + })); } private Result GetTopMostContextMenu(Result result) @@ -908,7 +908,7 @@ namespace Wox textBeforeEnterContextMenuMode = tbQuery.Text; ChangeQueryText(""); pnlContextMenu.Clear(); - pnlContextMenu.AddResults(results); + pnlContextMenu.AddResults(results, result.PluginID); CurrentContextMenus = results; pnlContextMenu.Visibility = Visibility.Visible; pnlResult.Visibility = Visibility.Collapsed; diff --git a/Wox/ResultPanel.xaml.cs b/Wox/ResultPanel.xaml.cs index f3e0148fd7..66f9a9fea9 100644 --- a/Wox/ResultPanel.xaml.cs +++ b/Wox/ResultPanel.xaml.cs @@ -55,56 +55,51 @@ namespace Wox } } - public void AddResults(List newResults) + public void AddResults(List newResults, string resultId) { - if (newResults != null && newResults.Count > 0) + var oldResults = _results.Where(r => r.PluginID == resultId).ToList(); + // intersection of A (old results) and B (new newResults) + var intersection = oldResults.Intersect(newResults).ToList(); + lock (_resultsUpdateLock) { - lock (_resultsUpdateLock) + // remove result of relative complement of B in A + foreach (var result in oldResults.Except(intersection)) { - var pluginId = newResults[0].PluginID; - var oldResults = _results.Where(r => r.PluginID == pluginId).ToList(); - // intersection of A (old results) and B (new newResults) - var intersection = oldResults.Intersect(newResults).ToList(); + _results.Remove(result); + } - // remove result of relative complement of B in A - foreach (var result in oldResults.Except(intersection)) + // update scores + foreach (var result in newResults) + { + if (IsTopMostResult(result)) { - _results.Remove(result); + result.Score = int.MaxValue; } + } - // update scores - foreach (var result in newResults) - { - if (IsTopMostResult(result)) - { - result.Score = int.MaxValue; - } - } - - // update index for result in intersection of A and B - foreach (var result in intersection) - { - int oldIndex = _results.IndexOf(result); - int oldScore = _results[oldIndex].Score; - if (result.Score != oldScore) - { - int newIndex = InsertIndexOf(result.Score); - if (newIndex != oldIndex) - { - _results.Move(oldIndex, newIndex); - } - } - } - - // insert result in relative complement of A in B - foreach (var result in newResults.Except(intersection)) + // update index for result in intersection of A and B + foreach (var result in intersection) + { + int oldIndex = _results.IndexOf(result); + int oldScore = _results[oldIndex].Score; + if (result.Score != oldScore) { int newIndex = InsertIndexOf(result.Score); - _results.Insert(newIndex, result); + if (newIndex != oldIndex) + { + _results.Move(oldIndex, newIndex); + } } - lbResults.Margin = lbResults.Items.Count > 0 ? new Thickness { Top = 8 } : new Thickness { Top = 0 }; - SelectFirst(); } + + // insert result in relative complement of A in B + foreach (var result in newResults.Except(intersection)) + { + int newIndex = InsertIndexOf(result.Score); + _results.Insert(newIndex, result); + } + lbResults.Margin = lbResults.Items.Count > 0 ? new Thickness { Top = 8 } : new Thickness { Top = 0 }; + SelectFirst(); } } diff --git a/Wox/SettingWindow.xaml.cs b/Wox/SettingWindow.xaml.cs index 09e269d56c..5b57bb8d85 100644 --- a/Wox/SettingWindow.xaml.cs +++ b/Wox/SettingWindow.xaml.cs @@ -429,7 +429,7 @@ namespace Wox IcoPath = "Images/app.png", PluginDirectory = Path.GetDirectoryName(Application.ExecutablePath) } - }); + }, "test id"); foreach (string theme in ThemeManager.Theme.LoadAvailableThemes()) { From 2b27e84956173fc33f2f0c2ebe510fd9feb20e2e Mon Sep 17 00:00:00 2001 From: bao-qian Date: Sun, 8 Nov 2015 01:44:28 +0000 Subject: [PATCH 05/10] Enhance result panel update The last commit f132cb54baa000a245feb5da87149960f6dbd9f5 only fix UI flickering for different icon. This commit also fix the commit for same icon. e.g. in web search plugin, although the title is different, but the icon is not changes. part of #350 --- Wox/Helper/ListBoxItems.cs | 36 +++++++++++++++++++++++++++++++++++- Wox/ResultPanel.xaml.cs | 38 +++++++++++++++++++++++--------------- 2 files changed, 58 insertions(+), 16 deletions(-) diff --git a/Wox/Helper/ListBoxItems.cs b/Wox/Helper/ListBoxItems.cs index 103630d6e4..5d62edf11d 100644 --- a/Wox/Helper/ListBoxItems.cs +++ b/Wox/Helper/ListBoxItems.cs @@ -9,7 +9,7 @@ using Wox.Plugin; namespace Wox.Helper { class ListBoxItems : ObservableCollection - // todo implement custom moveItem,removeItem,insertItem + // todo implement custom moveItem,removeItem,insertItem for better performance { public void RemoveAll(Predicate predicate) { @@ -18,6 +18,7 @@ namespace Wox.Helper List itemsToRemove = Items.Where(x => predicate(x)).ToList(); if (itemsToRemove.Count > 0) { + itemsToRemove.ForEach(item => Items.Remove(item)); OnPropertyChanged(new PropertyChangedEventArgs("Count")); @@ -29,5 +30,38 @@ namespace Wox.Helper OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } } + + public void Update(List newItems) + { + int newCount = newItems.Count; + int oldCount = Items.Count; + int location = newCount > oldCount ? oldCount : newCount; + for (int i = 0; i < location; i++) + { + Result oldItem = Items[i]; + Result newItem = newItems[i]; + if (!Equals(oldItem, newItem)) + { + this[i] = newItem; + } + } + + if (newCount > oldCount) + { + for (int i = oldCount; i < newCount; i++) + { + Add(newItems[i]); + } + } + else + { + int removeIndex = newCount; + for (int i = newCount; i < oldCount; i++) + { + RemoveAt(removeIndex); + } + } + + } } } diff --git a/Wox/ResultPanel.xaml.cs b/Wox/ResultPanel.xaml.cs index 66f9a9fea9..24d5385c3b 100644 --- a/Wox/ResultPanel.xaml.cs +++ b/Wox/ResultPanel.xaml.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; @@ -21,7 +22,7 @@ namespace Wox public event Action LeftMouseClickEvent; public event Action RightMouseClickEvent; public event Action ItemDropEvent; - private readonly ListBoxItems _results; //todo, for better performance, override the default linear search + private readonly ListBoxItems _results; private readonly object _resultsUpdateLock = new object(); protected virtual void OnRightMouseClick(Result result) @@ -57,15 +58,16 @@ namespace Wox public void AddResults(List newResults, string resultId) { - var oldResults = _results.Where(r => r.PluginID == resultId).ToList(); - // intersection of A (old results) and B (new newResults) - var intersection = oldResults.Intersect(newResults).ToList(); lock (_resultsUpdateLock) { + var resultCopy = _results.ToList(); + var oldResults = resultCopy.Where(r => r.PluginID == resultId).ToList(); + // intersection of A (old results) and B (new newResults) + var intersection = oldResults.Intersect(newResults).ToList(); // remove result of relative complement of B in A foreach (var result in oldResults.Except(intersection)) { - _results.Remove(result); + resultCopy.Remove(result); } // update scores @@ -80,14 +82,16 @@ namespace Wox // update index for result in intersection of A and B foreach (var result in intersection) { - int oldIndex = _results.IndexOf(result); - int oldScore = _results[oldIndex].Score; + int oldIndex = resultCopy.IndexOf(result); + int oldScore = resultCopy[oldIndex].Score; if (result.Score != oldScore) { - int newIndex = InsertIndexOf(result.Score); + int newIndex = InsertIndexOf(result.Score, resultCopy); if (newIndex != oldIndex) { - _results.Move(oldIndex, newIndex); + var item = resultCopy[oldIndex]; + resultCopy.RemoveAt(oldIndex); + resultCopy.Insert(newIndex, item); } } } @@ -95,9 +99,13 @@ namespace Wox // insert result in relative complement of A in B foreach (var result in newResults.Except(intersection)) { - int newIndex = InsertIndexOf(result.Score); - _results.Insert(newIndex, result); + int newIndex = InsertIndexOf(result.Score, resultCopy); + resultCopy.Insert(newIndex, result); } + + // update UI in one run, so it can avoid UI flickering + _results.Update(resultCopy); + lbResults.Margin = lbResults.Items.Count > 0 ? new Thickness { Top = 8 } : new Thickness { Top = 0 }; SelectFirst(); } @@ -108,13 +116,13 @@ namespace Wox return TopMostRecordStorage.Instance.IsTopMost(result); } - private int InsertIndexOf(int newScore) + private int InsertIndexOf(int newScore, IList list) { int index = 0; - for (; index < lbResults.Items.Count; index++) + for (; index < list.Count; index++) { - Result result = lbResults.Items[index] as Result; - if (newScore > result?.Score) + var result = list[index]; + if (newScore > result.Score) { break; } From e928b4c9e080d0eee32bfc7cf72daea310c2861b Mon Sep 17 00:00:00 2001 From: bao-qian Date: Sun, 8 Nov 2015 02:27:08 +0000 Subject: [PATCH 06/10] Fix web search plugin for new result panel --- Plugins/Wox.Plugin.WebSearch/EasyTimer.cs | 40 --------- .../Wox.Plugin.WebSearch/WebSearchPlugin.cs | 86 +++++++++---------- .../Wox.Plugin.WebSearch.csproj | 4 - 3 files changed, 39 insertions(+), 91 deletions(-) delete mode 100644 Plugins/Wox.Plugin.WebSearch/EasyTimer.cs diff --git a/Plugins/Wox.Plugin.WebSearch/EasyTimer.cs b/Plugins/Wox.Plugin.WebSearch/EasyTimer.cs deleted file mode 100644 index 49c31e63d3..0000000000 --- a/Plugins/Wox.Plugin.WebSearch/EasyTimer.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; - -namespace Wox.Plugin.WebSearch -{ - public static class EasyTimer - { - public static IDisposable SetInterval(Action method, int delayInMilliseconds) - { - System.Timers.Timer timer = new System.Timers.Timer(delayInMilliseconds); - timer.Elapsed += (source, e) => - { - method(); - }; - - timer.Enabled = true; - timer.Start(); - - // Returns a stop handle which can be used for stopping - // the timer, if required - return timer as IDisposable; - } - - public static IDisposable SetTimeout(Action method, int delayInMilliseconds) - { - System.Timers.Timer timer = new System.Timers.Timer(delayInMilliseconds); - timer.Elapsed += (source, e) => - { - method(); - }; - - timer.AutoReset = false; - timer.Enabled = true; - timer.Start(); - - // Returns a stop handle which can be used for stopping - // the timer, if required - return timer as IDisposable; - } - } -} diff --git a/Plugins/Wox.Plugin.WebSearch/WebSearchPlugin.cs b/Plugins/Wox.Plugin.WebSearch/WebSearchPlugin.cs index d4ee840df0..f2dba4a35f 100644 --- a/Plugins/Wox.Plugin.WebSearch/WebSearchPlugin.cs +++ b/Plugins/Wox.Plugin.WebSearch/WebSearchPlugin.cs @@ -4,14 +4,14 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; +using System.Windows.Controls; using Wox.Plugin.WebSearch.SuggestionSources; namespace Wox.Plugin.WebSearch { public class WebSearchPlugin : IPlugin, ISettingProvider, IPluginI18n, IInstantQuery { - private PluginInitContext context; - private IDisposable suggestionTimer; + private PluginInitContext _context; public List Query(Query query) { @@ -21,71 +21,63 @@ namespace Wox.Plugin.WebSearch if (webSearch != null) { - string keyword = query.ActionKeyword; + string keyword = query.Search; string title = keyword; - string subtitle = context.API.GetTranslation("wox_plugin_websearch_search") + " " + webSearch.Title; + string subtitle = _context.API.GetTranslation("wox_plugin_websearch_search") + " " + webSearch.Title; if (string.IsNullOrEmpty(keyword)) { title = subtitle; - subtitle = null; + subtitle = string.Empty; } - context.API.PushResults(query, context.CurrentPluginMetadata, new List() + var result = new Result { - new Result() + Title = title, + SubTitle = subtitle, + Score = 6, + IcoPath = webSearch.IconPath, + Action = c => { - Title = title, - SubTitle = subtitle, - Score = 6, - IcoPath = webSearch.IconPath, - Action = (c) => - { - Process.Start(webSearch.Url.Replace("{q}", Uri.EscapeDataString(keyword))); - return true; - } + Process.Start(webSearch.Url.Replace("{q}", Uri.EscapeDataString(keyword ?? string.Empty))); + return true; } - }); + }; + results.Add(result); if (WebSearchStorage.Instance.EnableWebSearchSuggestion && !string.IsNullOrEmpty(keyword)) { - if (suggestionTimer != null) - { - suggestionTimer.Dispose(); - } - suggestionTimer = EasyTimer.SetTimeout(() => { QuerySuggestions(keyword, query, subtitle, webSearch); }, 350); + // todo use Task.Wait when .net upgraded + results.AddRange(ResultsFromSuggestions(keyword, subtitle, webSearch)); } } - return results; } - private void QuerySuggestions(string keyword, Query query, string subtitle, WebSearch webSearch) + private IEnumerable ResultsFromSuggestions(string keyword, string subtitle, WebSearch webSearch) { - ISuggestionSource sugg = SuggestionSourceFactory.GetSuggestionSource(WebSearchStorage.Instance.WebSearchSuggestionSource, context); - if (sugg != null) + ISuggestionSource sugg = SuggestionSourceFactory.GetSuggestionSource(WebSearchStorage.Instance.WebSearchSuggestionSource, _context); + var suggestions = sugg?.GetSuggestions(keyword); + if (suggestions != null) { - var result = sugg.GetSuggestions(keyword); - if (result != null) + var resultsFromSuggestion = suggestions.Select(o => new Result { - context.API.PushResults(query, context.CurrentPluginMetadata, - result.Select(o => new Result() - { - Title = o, - SubTitle = subtitle, - Score = 5, - IcoPath = webSearch.IconPath, - Action = (c) => - { - Process.Start(webSearch.Url.Replace("{q}", Uri.EscapeDataString(o))); - return true; - } - }).ToList()); - } + Title = o, + SubTitle = subtitle, + Score = 5, + IcoPath = webSearch.IconPath, + Action = c => + { + Process.Start(webSearch.Url.Replace("{q}", Uri.EscapeDataString(o))); + return true; + } + }); + return resultsFromSuggestion; } + return new List(); } public void Init(PluginInitContext context) { - this.context = context; + _context = context; if (WebSearchStorage.Instance.WebSearches == null) WebSearchStorage.Instance.WebSearches = WebSearchStorage.Instance.LoadDefaultWebSearches(); @@ -93,9 +85,9 @@ namespace Wox.Plugin.WebSearch #region ISettingProvider Members - public System.Windows.Controls.Control CreateSettingPanel() + public Control CreateSettingPanel() { - return new WebSearchesSetting(context); + return new WebSearchesSetting(_context); } #endregion @@ -107,12 +99,12 @@ namespace Wox.Plugin.WebSearch public string GetTranslatedPluginTitle() { - return context.API.GetTranslation("wox_plugin_websearch_plugin_name"); + return _context.API.GetTranslation("wox_plugin_websearch_plugin_name"); } public string GetTranslatedPluginDescription() { - return context.API.GetTranslation("wox_plugin_websearch_plugin_description"); + return _context.API.GetTranslation("wox_plugin_websearch_plugin_description"); } public bool IsInstantQuery(string query) => false; diff --git a/Plugins/Wox.Plugin.WebSearch/Wox.Plugin.WebSearch.csproj b/Plugins/Wox.Plugin.WebSearch/Wox.Plugin.WebSearch.csproj index 32a1b26e4a..a407ad508e 100644 --- a/Plugins/Wox.Plugin.WebSearch/Wox.Plugin.WebSearch.csproj +++ b/Plugins/Wox.Plugin.WebSearch/Wox.Plugin.WebSearch.csproj @@ -49,7 +49,6 @@ - @@ -93,9 +92,6 @@ Designer - - - {4fd29318-a8ab-4d8f-aa47-60bc241b8da3} From b33b696336c6ae7e7558be68a27a55d5198b7772 Mon Sep 17 00:00:00 2001 From: bao-qian Date: Sun, 8 Nov 2015 02:27:13 +0000 Subject: [PATCH 07/10] Misc --- Wox/Wox.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/Wox/Wox.csproj b/Wox/Wox.csproj index 06d0cb7946..7d46e6109a 100644 --- a/Wox/Wox.csproj +++ b/Wox/Wox.csproj @@ -308,9 +308,6 @@ Wox.Plugin - - - From d946e18fa2d327d96889ffb1918a70eaf8fcba16 Mon Sep 17 00:00:00 2001 From: bao-qian Date: Sun, 8 Nov 2015 02:27:37 +0000 Subject: [PATCH 08/10] Fix CMD plugin for new result panel --- Plugins/Wox.Plugin.CMD/CMD.cs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/Plugins/Wox.Plugin.CMD/CMD.cs b/Plugins/Wox.Plugin.CMD/CMD.cs index 0cd255bc37..7b100dc6bb 100644 --- a/Plugins/Wox.Plugin.CMD/CMD.cs +++ b/Plugins/Wox.Plugin.CMD/CMD.cs @@ -21,22 +21,17 @@ namespace Wox.Plugin.CMD public List Query(Query query) { List results = new List(); - List pushedResults = new List(); string cmd = query.Search; if (string.IsNullOrEmpty(cmd)) { - return GetAllHistoryCmds(); + return ResultsFromlHistory(); } else { var queryCmd = GetCurrentCmd(cmd); - context.API.PushResults(query, context.CurrentPluginMetadata, new List() { queryCmd }); - pushedResults.Add(queryCmd); - + results.Add(queryCmd); var history = GetHistoryCmds(cmd, queryCmd); - context.API.PushResults(query, context.CurrentPluginMetadata, history); - pushedResults.AddRange(history); - + results.AddRange(history); try { @@ -57,7 +52,11 @@ namespace Wox.Plugin.CMD if (basedir != null) { - List autocomplete = Directory.GetFileSystemEntries(basedir).Select(o => dir + Path.GetFileName(o)).Where(o => o.StartsWith(cmd, StringComparison.OrdinalIgnoreCase) && !results.Any(p => o.Equals(p.Title, StringComparison.OrdinalIgnoreCase)) && !pushedResults.Any(p => o.Equals(p.Title, StringComparison.OrdinalIgnoreCase))).ToList(); + var autocomplete = Directory.GetFileSystemEntries(basedir). + Select(o => dir + Path.GetFileName(o)). + Where(o => o.StartsWith(cmd, StringComparison.OrdinalIgnoreCase) && + !results.Any(p => o.Equals(p.Title, StringComparison.OrdinalIgnoreCase)) && + !results.Any(p => o.Equals(p.Title, StringComparison.OrdinalIgnoreCase))).ToList(); autocomplete.Sort(); results.AddRange(autocomplete.ConvertAll(m => new Result() { @@ -94,7 +93,7 @@ namespace Wox.Plugin.CMD var ret = new Result { Title = m.Key, - SubTitle = string.Format(context.API.GetTranslation("wox_plugin_cmd_cmd_has_been_executed_times"), m.Value), + SubTitle = string.Format(context.API.GetTranslation("wox_plugin_cmd_cmd_has_been_executed_times"), m.Value), IcoPath = "Images/cmd.png", Action = (c) => { @@ -125,13 +124,13 @@ namespace Wox.Plugin.CMD return result; } - private List GetAllHistoryCmds() + private List ResultsFromlHistory() { IEnumerable history = CMDStorage.Instance.CMDHistory.OrderByDescending(o => o.Value) .Select(m => new Result { Title = m.Key, - SubTitle = string.Format(context.API.GetTranslation("wox_plugin_cmd_cmd_has_been_executed_times"), m.Value), + SubTitle = string.Format(context.API.GetTranslation("wox_plugin_cmd_cmd_has_been_executed_times"), m.Value), IcoPath = "Images/cmd.png", Action = (c) => { From e3cdfe27d18a82ab5195f3e5b11344f27afa59f1 Mon Sep 17 00:00:00 2001 From: bao-qian Date: Sun, 8 Nov 2015 02:50:33 +0000 Subject: [PATCH 09/10] Fix query history for the new result panel --- Wox/MainWindow.xaml.cs | 14 ++++++-------- Wox/ResultPanel.xaml.cs | 8 ++++---- Wox/Storage/QueryHistoryStorage.cs | 6 +++++- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs index d842aa2fdb..97cb97d162 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -473,6 +473,7 @@ namespace Wox private void ResetQueryHistoryIndex() { + pnlResult.RemoveResultsFor(QueryHistoryStorage.MetaData); QueryHistoryStorage.Instance.Reset(); } private void Query(string text) @@ -487,18 +488,18 @@ namespace Wox { if (!string.IsNullOrEmpty(keyword)) { - pnlResult.RemoveResultsExcept(PluginManager.NonGlobalPlugins[keyword]); + pnlResult.RemoveResultsExcept(PluginManager.NonGlobalPlugins[keyword].Metadata); } } else { if (string.IsNullOrEmpty(keyword)) { - pnlResult.RemoveResultsFor(PluginManager.NonGlobalPlugins[lastKeyword]); + pnlResult.RemoveResultsFor(PluginManager.NonGlobalPlugins[lastKeyword].Metadata); } else if (lastKeyword != keyword) { - pnlResult.RemoveResultsExcept(PluginManager.NonGlobalPlugins[keyword]); + pnlResult.RemoveResultsExcept(PluginManager.NonGlobalPlugins[keyword].Metadata); } } _lastQuery = query; @@ -738,14 +739,11 @@ namespace Wox { if (history != null) { - var historyMetadata = new PluginMetadata - { - ID = "Query history", - Name = "Query history" - }; + var historyMetadata = QueryHistoryStorage.MetaData; ChangeQueryText(history.Query, true); var executeQueryHistoryTitle = GetTranslation("executeQuery"); var lastExecuteTime = GetTranslation("lastExecuteTime"); + pnlResult.RemoveResultsExcept(historyMetadata); UpdateResultViewInternal(new List() { new Result(){ diff --git a/Wox/ResultPanel.xaml.cs b/Wox/ResultPanel.xaml.cs index 24d5385c3b..121ee9b852 100644 --- a/Wox/ResultPanel.xaml.cs +++ b/Wox/ResultPanel.xaml.cs @@ -40,19 +40,19 @@ namespace Wox public int MaxResultsToShow { get { return UserSettingStorage.Instance.MaxResultsToShow * 50; } } - internal void RemoveResultsFor(PluginPair plugin) + internal void RemoveResultsFor(PluginMetadata metadata) { lock (_resultsUpdateLock) { - _results.RemoveAll(r => r.PluginID == plugin.Metadata.ID); + _results.RemoveAll(r => r.PluginID == metadata.ID); } } - internal void RemoveResultsExcept(PluginPair plugin) + internal void RemoveResultsExcept(PluginMetadata metadata) { lock (_resultsUpdateLock) { - _results.RemoveAll(r => r.PluginID != plugin.Metadata.ID); + _results.RemoveAll(r => r.PluginID != metadata.ID); } } diff --git a/Wox/Storage/QueryHistoryStorage.cs b/Wox/Storage/QueryHistoryStorage.cs index d39ebaad14..81ccc353ae 100644 --- a/Wox/Storage/QueryHistoryStorage.cs +++ b/Wox/Storage/QueryHistoryStorage.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Reflection; using Newtonsoft.Json; using Wox.Infrastructure.Storage; +using Wox.Plugin; namespace Wox.Storage { @@ -16,6 +17,9 @@ namespace Wox.Storage private int MaxHistory = 300; private int cursor = 0; + public static PluginMetadata MetaData { get; } = new PluginMetadata + { ID = "Query history", Name = "Query history" }; + protected override string ConfigFolder { get { return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Config"); } @@ -77,7 +81,7 @@ namespace Wox.Storage return History.OrderByDescending(o => o.ExecutedDateTime).ToList(); } } - + public class HistoryItem { public string Query { get; set; } From 543cd5af802c17e9728f3123d72eb13ce797df86 Mon Sep 17 00:00:00 2001 From: bao-qian Date: Sun, 8 Nov 2015 03:06:34 +0000 Subject: [PATCH 10/10] Fix progress bar Bug introduced in 9962ddf2ed80a00036ebdb2965429675c4355472 --- Wox/MainWindow.xaml.cs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs index 97cb97d162..5a289131ed 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -443,25 +443,19 @@ namespace Wox private void TbQuery_OnTextChanged(object sender, TextChangedEventArgs e) { - if (_ignoreTextChange) { _ignoreTextChange = false; return; } - string query = tbQuery.Text.Trim(); + toolTip.IsOpen = false; if (IsInContextMenuMode) { QueryContextMenu(); return; } + + string query = tbQuery.Text.Trim(); if (!string.IsNullOrEmpty(query)) { Query(query); - Dispatcher.DelayInvoke("ShowProgressbar", () => - { - if (!string.IsNullOrEmpty(query) && query != _lastQuery.RawQuery && !_queryHasReturn) - { - StartProgress(); - } - }, TimeSpan.FromMilliseconds(150)); //reset query history index after user start new query ResetQueryHistoryIndex(); } @@ -478,6 +472,7 @@ namespace Wox } private void Query(string text) { + _queryHasReturn = false; var query = PluginManager.QueryInit(text); if (query != null) { @@ -503,6 +498,13 @@ namespace Wox } } _lastQuery = query; + Dispatcher.DelayInvoke("ShowProgressbar", () => + { + if (!string.IsNullOrEmpty(query.RawQuery) && query.RawQuery == _lastQuery.RawQuery && !_queryHasReturn) + { + StartProgress(); + } + }, TimeSpan.FromMilliseconds(150)); PluginManager.QueryForAllPlugins(query); } StopProgress();