This commit is contained in:
bao-qian 2015-11-07 02:23:40 +00:00
parent cae8485092
commit 7db73cbd44
8 changed files with 125 additions and 75 deletions

View file

@ -1,7 +1,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using Newtonsoft.Json; using Exceptionless.Json;
using JsonProperty = Newtonsoft.Json.JsonPropertyAttribute;
using Wox.Infrastructure.Storage; using Wox.Infrastructure.Storage;
namespace Wox.Plugin.Everything namespace Wox.Plugin.Everything

View file

@ -13,10 +13,9 @@ namespace Wox.Plugin.PluginIndicator
public List<Result> Query(Query query) public List<Result> Query(Query query)
{ {
var results = from plugin in PluginManager.NonGlobalPlugins var results = from keyword in PluginManager.NonGlobalPlugins.Keys
select plugin.Metadata into metadata
from keyword in metadata.ActionKeywords
where keyword.StartsWith(query.Terms[0]) where keyword.StartsWith(query.Terms[0])
let metadata = PluginManager.NonGlobalPlugins[keyword].Metadata
let customizedPluginConfig = let customizedPluginConfig =
UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == metadata.ID) UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == metadata.ID)
where customizedPluginConfig == null || !customizedPluginConfig.Disabled where customizedPluginConfig == null || !customizedPluginConfig.Disabled

View file

@ -29,8 +29,8 @@ namespace Wox.Core.Plugin
public static IEnumerable<PluginPair> AllPlugins { get; private set; } public static IEnumerable<PluginPair> AllPlugins { get; private set; }
public static IEnumerable<PluginPair> GlobalPlugins { get; private set; } public static List<PluginPair> GlobalPlugins { get; } = new List<PluginPair>();
public static IEnumerable<PluginPair> NonGlobalPlugins { get; private set; } public static Dictionary<string, PluginPair> NonGlobalPlugins { get; } = new Dictionary<string, PluginPair>();
private static IEnumerable<PluginPair> InstantQueryPlugins { get; set; } private static IEnumerable<PluginPair> InstantQueryPlugins { get; set; }
public static IPublicAPI API { private set; get; } public static IPublicAPI API { private set; get; }
@ -104,8 +104,20 @@ namespace Wox.Core.Plugin
{ {
InstantQueryPlugins = GetPluginsForInterface<IInstantQuery>(); InstantQueryPlugins = GetPluginsForInterface<IInstantQuery>();
contextMenuPlugins = GetPluginsForInterface<IContextMenu>(); contextMenuPlugins = GetPluginsForInterface<IContextMenu>();
GlobalPlugins = AllPlugins.Where(p => IsGlobalPlugin(p.Metadata)); foreach (var plugin in AllPlugins)
NonGlobalPlugins = AllPlugins.Where(p => !IsGlobalPlugin(p.Metadata)); {
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; var search = rawQuery;
List<string> actionParameters = terms.ToList(); List<string> actionParameters = terms.ToList();
if (terms.Length == 0) return null; if (terms.Length == 0) return null;
if (IsVailldActionKeyword(terms[0])) if (NonGlobalPlugins.ContainsKey(terms[0]))
{ {
actionKeyword = terms[0]; actionKeyword = terms[0];
actionParameters = terms.Skip(1).ToList(); actionParameters = terms.Skip(1).ToList();
@ -143,8 +155,8 @@ namespace Wox.Core.Plugin
public static void QueryForAllPlugins(Query query) public static void QueryForAllPlugins(Query query)
{ {
var pluginPairs = GetPluginForActionKeyword(query.ActionKeyword) != null ? var pluginPairs = NonGlobalPlugins.ContainsKey(query.ActionKeyword) ?
new List<PluginPair> { GetPluginForActionKeyword(query.ActionKeyword) } : GlobalPlugins; new List<PluginPair> { NonGlobalPlugins[query.ActionKeyword] } : GlobalPlugins;
foreach (var plugin in pluginPairs) foreach (var plugin in pluginPairs)
{ {
var customizedPluginConfig = UserSettingStorage.Instance. var customizedPluginConfig = UserSettingStorage.Instance.
@ -187,21 +199,6 @@ namespace Wox.Core.Plugin
} }
} }
/// <summary>
/// Check if a query contains valid action keyword
/// </summary>
/// <param name="actionKeyword"></param>
/// <returns></returns>
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) private static bool IsGlobalPlugin(PluginMetadata metadata)
{ {
return metadata.ActionKeywords.Contains(Query.GlobalPluginWildcardSign); return metadata.ActionKeywords.Contains(Query.GlobalPluginWildcardSign);
@ -225,13 +222,6 @@ namespace Wox.Core.Plugin
return AllPlugins.FirstOrDefault(o => o.Metadata.ID == id); 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<PluginPair> GetPluginsForInterface<T>() where T : IFeatures public static IEnumerable<PluginPair> GetPluginsForInterface<T>() where T : IFeatures
{ {
return AllPlugins.Where(p => p.Plugin is T); return AllPlugins.Where(p => p.Plugin is T);

View file

@ -0,0 +1,28 @@
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<Result>
{
public void RemoveAll(Predicate<Result> predicate)
{
CheckReentrancy();
List<Result> 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[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, itemsToRemove));
}
}
}
}

View file

@ -43,11 +43,11 @@ namespace Wox
private readonly Storyboard progressBarStoryboard = new Storyboard(); private readonly Storyboard progressBarStoryboard = new Storyboard();
private NotifyIcon notifyIcon; private NotifyIcon notifyIcon;
private bool queryHasReturn; private bool _queryHasReturn;
private string lastQuery; private Query _lastQuery = new Query();
private ToolTip toolTip = new ToolTip(); private ToolTip toolTip = new ToolTip();
private bool ignoreTextChange = false; private bool _ignoreTextChange = false;
private List<Result> CurrentContextMenus = new List<Result>(); private List<Result> CurrentContextMenus = new List<Result>();
private string textBeforeEnterContextMenuMode; private string textBeforeEnterContextMenuMode;
@ -72,7 +72,7 @@ namespace Wox
{ {
Dispatcher.Invoke(new Action(() => Dispatcher.Invoke(new Action(() =>
{ {
ignoreTextChange = true; _ignoreTextChange = true;
tbQuery.Text = query; tbQuery.Text = query;
tbQuery.CaretIndex = tbQuery.Text.Length; tbQuery.CaretIndex = tbQuery.Text.Length;
if (selectAll) if (selectAll)
@ -442,9 +442,9 @@ namespace Wox
private void TbQuery_OnTextChanged(object sender, TextChangedEventArgs e) private void TbQuery_OnTextChanged(object sender, TextChangedEventArgs e)
{ {
if (ignoreTextChange) { ignoreTextChange = false; return; } if (_ignoreTextChange) { _ignoreTextChange = false; return; }
string query = tbQuery.Text.Trim();
if (!string.IsNullOrEmpty(tbQuery.Text.Trim())) if (!string.IsNullOrEmpty(query))
{ {
toolTip.IsOpen = false; toolTip.IsOpen = false;
if (IsInContextMenuMode) if (IsInContextMenuMode)
@ -453,10 +453,10 @@ namespace Wox
return; return;
} }
Query(tbQuery.Text); Query(query);
Dispatcher.DelayInvoke("ShowProgressbar", () => Dispatcher.DelayInvoke("ShowProgressbar", () =>
{ {
if (!string.IsNullOrEmpty(tbQuery.Text.Trim()) && tbQuery.Text != lastQuery && !queryHasReturn) if (!string.IsNullOrEmpty(query) && query != _lastQuery.RawQuery && !_queryHasReturn)
{ {
StartProgress(); StartProgress();
} }
@ -479,7 +479,28 @@ namespace Wox
var query = PluginManager.QueryInit(text); var query = PluginManager.QueryInit(text);
if (query != null) 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); PluginManager.QueryForAllPlugins(query);
} }
StopProgress(); StopProgress();
@ -814,7 +835,7 @@ namespace Wox
private void UpdateResultView(List<Result> list) private void UpdateResultView(List<Result> list)
{ {
queryHasReturn = true; _queryHasReturn = true;
progressBar.Dispatcher.Invoke(new Action(StopProgress)); progressBar.Dispatcher.Invoke(new Action(StopProgress));
if (list == null || list.Count == 0) return; if (list == null || list.Count == 0) return;
@ -824,7 +845,7 @@ namespace Wox
{ {
o.Score += UserSelectedRecordStorage.Instance.GetSelectedCount(o) * 5; o.Score += UserSelectedRecordStorage.Instance.GetSelectedCount(o) * 5;
}); });
List<Result> l = list.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == lastQuery).ToList(); List<Result> l = list.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == _lastQuery.RawQuery).ToList();
UpdateResultViewInternal(l); UpdateResultViewInternal(l);
} }
} }

View file

@ -1,10 +1,10 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// 此代码由工具生成。 // This code was generated by a tool.
// 运行时版本:4.0.30319.0 // Runtime Version:4.0.30319.42000
// //
// 对此文件的更改可能会导致不正确的行为,并且如果 // Changes to this file may cause incorrect behavior and will be lost if
// 重新生成代码,这些更改将会丢失。 // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -13,12 +13,12 @@ namespace Wox.Properties {
/// <summary> /// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。 /// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary> /// </summary>
// 此类是由 StronglyTypedResourceBuilder // This class was auto-generated by the StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 // class via a tool like ResGen or Visual Studio.
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen // To add or remove a member, edit your .ResX file then rerun ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。 // with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
@ -33,7 +33,7 @@ namespace Wox.Properties {
} }
/// <summary> /// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。 /// Returns the cached ResourceManager instance used by this class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager { internal static global::System.Resources.ResourceManager ResourceManager {
@ -47,8 +47,8 @@ namespace Wox.Properties {
} }
/// <summary> /// <summary>
/// 使用此强类型资源类,为所有资源查找 /// Overrides the current thread's CurrentUICulture property for all
/// 重写当前线程的 CurrentUICulture 属性。 /// resource lookups using this strongly typed resource class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture { internal static global::System.Globalization.CultureInfo Culture {
@ -61,7 +61,7 @@ namespace Wox.Properties {
} }
/// <summary> /// <summary>
/// 查找类似于 (Icon) 的 System.Drawing.Icon 类型的本地化资源。 /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary> /// </summary>
internal static System.Drawing.Icon app { internal static System.Drawing.Icon app {
get { get {

View file

@ -1,10 +1,10 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// 此代码由工具生成。 // This code was generated by a tool.
// 运行时版本:4.0.30319.0 // Runtime Version:4.0.30319.42000
// //
// 对此文件的更改可能会导致不正确的行为,并且如果 // Changes to this file may cause incorrect behavior and will be lost if
// 重新生成代码,这些更改将会丢失。 // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -12,7 +12,7 @@ namespace Wox.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [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 { internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

View file

@ -9,6 +9,7 @@ using System.Windows.Media;
using System.Linq; using System.Linq;
using System.Runtime.Remoting.Contexts; using System.Runtime.Remoting.Contexts;
using Wox.Core.UserSettings; using Wox.Core.UserSettings;
using Wox.Helper;
using Wox.Plugin; using Wox.Plugin;
using Wox.Storage; using Wox.Storage;
@ -20,7 +21,7 @@ namespace Wox
public event Action<Result> LeftMouseClickEvent; public event Action<Result> LeftMouseClickEvent;
public event Action<Result> RightMouseClickEvent; public event Action<Result> RightMouseClickEvent;
public event Action<Result, IDataObject, DragEventArgs> ItemDropEvent; public event Action<Result, IDataObject, DragEventArgs> ItemDropEvent;
private readonly ObservableCollection<Result> _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(); private readonly object _resultsUpdateLock = new object();
protected virtual void OnRightMouseClick(Result result) protected virtual void OnRightMouseClick(Result result)
@ -38,6 +39,25 @@ namespace Wox
public int MaxResultsToShow { get { return UserSettingStorage.Instance.MaxResultsToShow * 50; } } 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<Result> newResults) public void AddResults(List<Result> newResults)
{ {
if (newResults != null && newResults.Count > 0) if (newResults != null && newResults.Count > 0)
@ -45,16 +65,7 @@ namespace Wox
lock (_resultsUpdateLock) lock (_resultsUpdateLock)
{ {
var pluginId = newResults[0].PluginID; var pluginId = newResults[0].PluginID;
var actionKeyword = newResults[0].OriginQuery.ActionKeyword; var oldResults = _results.Where(r => r.PluginID == pluginId).ToList();
List<Result> oldResults;
if (string.IsNullOrEmpty(actionKeyword))
{
oldResults = _results.Where(r => r.PluginID == pluginId).ToList();
}
else
{
oldResults = _results.ToList();
}
// intersection of A (old results) and B (new newResults) // intersection of A (old results) and B (new newResults)
var intersection = oldResults.Intersect(newResults).ToList(); var intersection = oldResults.Intersect(newResults).ToList();
@ -236,7 +247,7 @@ namespace Wox
public ResultPanel() public ResultPanel()
{ {
InitializeComponent(); InitializeComponent();
_results = new ObservableCollection<Result>(); _results = new ListBoxItems();
lbResults.ItemsSource = _results; lbResults.ItemsSource = _results;
} }