Merge branch 'V1.2.0' of https://github.com/qianlifeng/Wox into V1.2.0

This commit is contained in:
qianlifeng
2014-12-31 12:43:02 +08:00
54 changed files with 712 additions and 532 deletions

View File

@@ -29,11 +29,13 @@ Name: english; MessagesFile: compiler:Default.isl
Type: files; Name: "{commonstartup}\{#MyAppName}.lnk" Type: files; Name: "{commonstartup}\{#MyAppName}.lnk"
[Tasks] [Tasks]
Name: desktopicon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons}; Flags: unchecked Name: desktopicon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons};
Name: startupfolder; Description: Startup with Windows; Name: startupfolder; Description: Startup with Windows;
[Files] [Files]
Source: {#MyAppPath}\*; DestDir: {app}; Flags: ignoreversion recursesubdirs Source: {#MyAppPath}\*; Excludes: Plugins\*,Themes\*; DestDir: {app}; Flags: ignoreversion recursesubdirs
Source: {#MyAppPath}\Plugins\*; DestDir: {%USERPROFILE}\.Wox\Plugins; Flags: ignoreversion recursesubdirs
Source: {#MyAppPath}\Themes\*; DestDir: {%USERPROFILE}\.Wox\Themes; Flags: ignoreversion recursesubdirs
[Icons] [Icons]
Name: {group}\{#MyAppName}; Filename: {app}\{#MyAppExeName} Name: {group}\{#MyAppName}; Filename: {app}\{#MyAppExeName}
@@ -42,4 +44,10 @@ Name: {userdesktop}\{#MyAppName}; Filename: {app}\{#MyAppExeName}; Tasks: deskto
Name: {userstartup}\{#MyAppName}; Filename: {app}\{#MyAppExeName}; Tasks: startupfolder Name: {userstartup}\{#MyAppName}; Filename: {app}\{#MyAppExeName}; Tasks: startupfolder
[Run] [Run]
Filename: {app}\{#MyAppExeName}; Description: {cm:LaunchProgram,{#MyAppName}}; Flags: nowait postinstall skipifsilent Filename: {app}\{#MyAppExeName}; Description: {cm:LaunchProgram,{#MyAppName}}; Flags: nowait postinstall skipifsilent unchecked
[UninstallDelete]
Type: filesandordirs; Name: "{%USERPROFILE}\.Wox"
[UninstallRun]
Filename: {sys}\taskkill.exe; Parameters: "/f /im Wox.exe"; Flags: skipifdoesntexist runhidden

View File

@@ -197,7 +197,7 @@ namespace Wox.Plugin.PluginManagement
private List<Result> ListUnInstalledPlugins(Query query) private List<Result> ListUnInstalledPlugins(Query query)
{ {
List<Result> results = new List<Result>(); List<Result> results = new List<Result>();
List<PluginMetadata> allInstalledPlugins = ParseThirdPartyPlugins(); List<PluginMetadata> allInstalledPlugins = ParseUserPlugins();
if (query.ActionParameters.Count > 1) if (query.ActionParameters.Count > 1)
{ {
string pluginName = query.ActionParameters[1]; string pluginName = query.ActionParameters[1];
@@ -235,7 +235,7 @@ namespace Wox.Plugin.PluginManagement
private List<Result> ListInstalledPlugins() private List<Result> ListInstalledPlugins()
{ {
List<Result> results = new List<Result>(); List<Result> results = new List<Result>();
foreach (PluginMetadata plugin in ParseThirdPartyPlugins()) foreach (PluginMetadata plugin in ParseUserPlugins())
{ {
results.Add(new Result() results.Add(new Result()
{ {
@@ -247,7 +247,7 @@ namespace Wox.Plugin.PluginManagement
return results; return results;
} }
private static List<PluginMetadata> ParseThirdPartyPlugins() private static List<PluginMetadata> ParseUserPlugins()
{ {
List<PluginMetadata> pluginMetadatas = new List<PluginMetadata>(); List<PluginMetadata> pluginMetadatas = new List<PluginMetadata>();
if (!Directory.Exists(PluginPath)) if (!Directory.Exists(PluginPath))
@@ -276,7 +276,7 @@ namespace Wox.Plugin.PluginManagement
try try
{ {
metadata = JsonConvert.DeserializeObject<PluginMetadata>(File.ReadAllText(configPath)); metadata = JsonConvert.DeserializeObject<PluginMetadata>(File.ReadAllText(configPath));
metadata.PluginType = PluginType.ThirdParty; metadata.PluginType = PluginType.User;
metadata.PluginDirectory = pluginDirectory; metadata.PluginDirectory = pluginDirectory;
} }
catch (Exception) catch (Exception)

View File

@@ -0,0 +1,206 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Xml;
using Microsoft.Win32;
namespace Wox.Core.Exception
{
public class ExceptionFormatter
{
public static string FormatExcpetion(object exception)
{
return CreateExceptionReport(exception);
}
private static string CreateExceptionReport(object exceptionObject)
{
var sb = new StringBuilder();
sb.AppendLine("## Exception");
sb.AppendLine();
sb.AppendLine("```");
var ex = exceptionObject as System.Exception;
if (ex != null)
{
var exlist = new List<StringBuilder>();
while (ex != null)
{
var exsb = new StringBuilder();
exsb.Append(ex.GetType().FullName);
exsb.Append(": ");
exsb.AppendLine(ex.Message);
if (ex.Source != null)
{
exsb.Append(" Source: ");
exsb.AppendLine(ex.Source);
}
if (ex.TargetSite != null)
{
exsb.Append(" TargetAssembly: ");
exsb.AppendLine(ex.TargetSite.Module.Assembly.ToString());
exsb.Append(" TargetModule: ");
exsb.AppendLine(ex.TargetSite.Module.ToString());
exsb.Append(" TargetSite: ");
exsb.AppendLine(ex.TargetSite.ToString());
}
exsb.AppendLine(ex.StackTrace);
exlist.Add(exsb);
ex = ex.InnerException;
}
foreach (var result in exlist.Select(o => o.ToString()).Reverse())
{
sb.AppendLine(result);
}
sb.AppendLine("```");
sb.AppendLine();
}
else
{
sb.AppendLine(exceptionObject.GetType().FullName);
sb.AppendLine(new StackTrace().ToString());
sb.AppendLine("```");
sb.AppendLine();
}
sb.AppendLine("## Environment");
sb.AppendLine();
sb.Append("* Command Line: ");
sb.AppendLine(Environment.CommandLine);
sb.Append("* Timestamp: ");
sb.AppendLine(XmlConvert.ToString(DateTime.Now));
sb.Append("* IntPtr Length: ");
sb.AppendLine(IntPtr.Size.ToString());
sb.Append("* System Version: ");
sb.AppendLine(Environment.OSVersion.VersionString);
sb.Append("* CLR Version: ");
sb.AppendLine(Environment.Version.ToString());
sb.AppendLine("* Installed .NET Framework: ");
foreach (var result in GetFrameworkVersionFromRegistry())
{
sb.Append(" * ");
sb.AppendLine(result);
}
sb.AppendLine();
sb.AppendLine("## Assemblies - " + System.AppDomain.CurrentDomain.FriendlyName);
sb.AppendLine();
foreach (var ass in System.AppDomain.CurrentDomain.GetAssemblies().OrderBy(o => o.GlobalAssemblyCache ? 100 : 0))
{
sb.Append("* ");
sb.Append(ass.FullName);
sb.Append(" (");
sb.Append(string.IsNullOrEmpty(ass.Location) ? "not supported" : ass.Location);
sb.AppendLine(")");
}
var process = System.Diagnostics.Process.GetCurrentProcess();
sb.AppendLine();
sb.AppendLine("## Modules - " + process.ProcessName);
sb.AppendLine();
foreach (ProcessModule mod in process.Modules)
{
sb.Append("* ");
sb.Append(mod.FileName);
sb.Append(" (");
sb.Append(mod.FileVersionInfo.FileDescription);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.FileVersion);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.ProductName);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.ProductVersion);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.CompanyName);
sb.Append("), ");
sb.Append(string.Format("0x{0:X16}", mod.BaseAddress.ToInt64()));
sb.AppendLine();
}
sb.AppendLine();
sb.AppendLine("## Threads - " + process.Threads.Count);
sb.AppendLine();
foreach (ProcessThread th in process.Threads)
{
sb.Append("* ");
sb.AppendLine(string.Format("{0}, {1} {2}, Started: {3}, StartAddress: 0x{4:X16}", th.Id, th.ThreadState, th.PriorityLevel, th.StartTime, th.StartAddress.ToInt64()));
}
return sb.ToString();
}
// http://msdn.microsoft.com/en-us/library/hh925568%28v=vs.110%29.aspx
private static List<string> GetFrameworkVersionFromRegistry()
{
try
{
var result = new List<string>();
using (RegistryKey ndpKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\"))
{
foreach (string versionKeyName in ndpKey.GetSubKeyNames())
{
if (versionKeyName.StartsWith("v"))
{
RegistryKey versionKey = ndpKey.OpenSubKey(versionKeyName);
string name = (string)versionKey.GetValue("Version", "");
string sp = versionKey.GetValue("SP", "").ToString();
string install = versionKey.GetValue("Install", "").ToString();
if (install != "")
if (sp != "" && install == "1")
result.Add(string.Format("{0} {1} SP{2}", versionKeyName, name, sp));
else
result.Add(string.Format("{0} {1}", versionKeyName, name));
if (name != "")
{
continue;
}
foreach (string subKeyName in versionKey.GetSubKeyNames())
{
RegistryKey subKey = versionKey.OpenSubKey(subKeyName);
name = (string)subKey.GetValue("Version", "");
if (name != "")
sp = subKey.GetValue("SP", "").ToString();
install = subKey.GetValue("Install", "").ToString();
if (install != "")
{
if (sp != "" && install == "1")
result.Add(string.Format("{0} {1} {2} SP{3}", versionKeyName, subKeyName, name, sp));
else if (install == "1")
result.Add(string.Format("{0} {1} {2}", versionKeyName, subKeyName, name));
}
}
}
}
}
using (RegistryKey ndpKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\"))
{
int releaseKey = (int)ndpKey.GetValue("Release");
{
if (releaseKey == 378389)
result.Add("v4.5");
if (releaseKey == 378675)
result.Add("v4.5.1 installed with Windows 8.1");
if (releaseKey == 378758)
result.Add("4.5.1 installed on Windows 8, Windows 7 SP1, or Windows Vista SP2");
}
}
return result;
}
catch (System.Exception e)
{
return new List<string>();
}
}
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Wox.Core.Exception
{
/// <summary>
/// Represent exceptions that wox can't handle and MUST close running Wox.
/// </summary>
public class WoxCritialException : WoxException
{
public WoxCritialException(string msg) : base(msg)
{
}
}
}

View File

@@ -0,0 +1,14 @@
namespace Wox.Core.Exception
{
/// <summary>
/// Base Wox Exceptions
/// </summary>
public class WoxException : System.Exception
{
public WoxException(string msg)
: base(msg)
{
}
}
}

View File

@@ -1,9 +1,4 @@
using System; namespace Wox.Core.Exception
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Wox.Infrastructure.Exceptions
{ {
public class WoxHttpException :WoxException public class WoxHttpException :WoxException
{ {

View File

@@ -1,4 +1,4 @@
namespace Wox.Infrastructure.Exceptions namespace Wox.Core.Exception
{ {
public class WoxJsonRPCException : WoxException public class WoxJsonRPCException : WoxException
{ {

View File

@@ -44,7 +44,7 @@ namespace Wox.Core.Plugin
plugins.Add(pair); plugins.Add(pair);
} }
} }
catch (Exception e) catch (System.Exception e)
{ {
Log.Error(string.Format("Couldn't load plugin {0}: {1}", metadata.Name, e.Message)); Log.Error(string.Format("Couldn't load plugin {0}: {1}", metadata.Name, e.Message));
#if (DEBUG) #if (DEBUG)

View File

@@ -4,8 +4,8 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using System.Windows.Forms;
using Newtonsoft.Json; using Newtonsoft.Json;
using Wox.Infrastructure.Exceptions;
using Wox.Infrastructure.Logger; using Wox.Infrastructure.Logger;
using Wox.Plugin; using Wox.Plugin;
@@ -72,9 +72,8 @@ namespace Wox.Core.Plugin
} }
return results; return results;
} }
catch (Exception e) catch (System.Exception e)
{ {
ErrorReporting.TryShowErrorMessageBox(e.Message, e);
Log.Error(e.Message); Log.Error(e.Message);
} }
} }
@@ -83,14 +82,14 @@ namespace Wox.Core.Plugin
private void ExecuteWoxAPI(string method, object[] parameters) private void ExecuteWoxAPI(string method, object[] parameters)
{ {
MethodInfo methodInfo = App.Window.GetType().GetMethod(method); MethodInfo methodInfo = PluginManager.API.GetType().GetMethod(method);
if (methodInfo != null) if (methodInfo != null)
{ {
try try
{ {
methodInfo.Invoke(App.Window, parameters); methodInfo.Invoke(PluginManager.API, parameters);
} }
catch (Exception) catch (System.Exception)
{ {
#if (DEBUG) #if (DEBUG)
{ {
@@ -132,7 +131,7 @@ namespace Wox.Core.Plugin
string result = reader.ReadToEnd(); string result = reader.ReadToEnd();
if (result.StartsWith("DEBUG:")) if (result.StartsWith("DEBUG:"))
{ {
System.Windows.Forms.MessageBox.Show(new Form { TopMost = true }, result.Substring(6)); MessageBox.Show(new Form { TopMost = true }, result.Substring(6));
return ""; return "";
} }
if (string.IsNullOrEmpty(result)) if (string.IsNullOrEmpty(result))
@@ -142,7 +141,8 @@ namespace Wox.Core.Plugin
string error = errorReader.ReadToEnd(); string error = errorReader.ReadToEnd();
if (!string.IsNullOrEmpty(error)) if (!string.IsNullOrEmpty(error))
{ {
ErrorReporting.TryShowErrorMessageBox(error, new WoxJsonRPCException(error)); //todo:
// ErrorReporting.TryShowErrorMessageBox(error, new WoxJsonRPCException(error));
} }
} }
} }

View File

@@ -13,7 +13,7 @@ namespace Wox.Core.Plugin
return jsonRPCPluginMetadatas.Select(metadata => new PluginPair() return jsonRPCPluginMetadatas.Select(metadata => new PluginPair()
{ {
Plugin = jsonRPCPlugin, Plugin = new T(), //every JsonRPC plugin should has its own plugin instance
Metadata = metadata Metadata = metadata
}).ToList(); }).ToList();
} }

View File

@@ -4,7 +4,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Newtonsoft.Json; using Newtonsoft.Json;
using Wox.Infrastructure.Exceptions; using Wox.Core.Exception;
using Wox.Infrastructure.Logger; using Wox.Infrastructure.Logger;
using Wox.Infrastructure.Storage.UserSettings; using Wox.Infrastructure.Storage.UserSettings;
using Wox.Plugin; using Wox.Plugin;
@@ -28,7 +28,7 @@ namespace Wox.Core.Plugin
ParseSystemPlugins(); ParseSystemPlugins();
foreach (string pluginDirectory in pluginDirectories) foreach (string pluginDirectory in pluginDirectories)
{ {
ParseThirdPartyPlugins(pluginDirectory); ParseUserPlugins(pluginDirectory);
} }
if (PluginManager.DebuggerMode != null) if (PluginManager.DebuggerMode != null)
@@ -41,6 +41,13 @@ namespace Wox.Core.Plugin
private static void ParseSystemPlugins() private static void ParseSystemPlugins()
{ {
string systemPluginPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
"Wox.Plugin.SystemPlugins.dll");
if (!File.Exists(systemPluginPath))
{
throw new WoxCritialException("System Plugin DLL is missing.");
}
pluginMetadatas.Add(new PluginMetadata() pluginMetadatas.Add(new PluginMetadata()
{ {
Name = "System Plugins", Name = "System Plugins",
@@ -56,17 +63,25 @@ namespace Wox.Core.Plugin
}); });
} }
private static void ParseThirdPartyPlugins(string pluginDirectory) private static void ParseUserPlugins(string pluginDirectory)
{ {
if (!Directory.Exists(pluginDirectory)) return;
string[] directories = Directory.GetDirectories(pluginDirectory); string[] directories = Directory.GetDirectories(pluginDirectory);
foreach (string directory in directories) foreach (string directory in directories)
{ {
if (File.Exists((Path.Combine(directory, "NeedDelete.txt")))) if (File.Exists((Path.Combine(directory, "NeedDelete.txt"))))
{
try
{ {
Directory.Delete(directory, true); Directory.Delete(directory, true);
continue; continue;
} }
catch (System.Exception e)
{
Log.Error(ExceptionFormatter.FormatExcpetion(e));
}
}
PluginMetadata metadata = GetPluginMetadata(directory); PluginMetadata metadata = GetPluginMetadata(directory);
if (metadata != null) if (metadata != null)
{ {
@@ -88,10 +103,10 @@ namespace Wox.Core.Plugin
try try
{ {
metadata = JsonConvert.DeserializeObject<PluginMetadata>(File.ReadAllText(configPath)); metadata = JsonConvert.DeserializeObject<PluginMetadata>(File.ReadAllText(configPath));
metadata.PluginType = PluginType.ThirdParty; metadata.PluginType = PluginType.User;
metadata.PluginDirectory = pluginDirectory; metadata.PluginDirectory = pluginDirectory;
} }
catch (Exception) catch (System.Exception)
{ {
string error = string.Format("Parse plugin config {0} failed: json format is not valid", configPath); string error = string.Format("Parse plugin config {0} failed: json format is not valid", configPath);
Log.Warn(error); Log.Warn(error);

View File

@@ -1,18 +1,17 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Forms;
using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip;
using Newtonsoft.Json; using Newtonsoft.Json;
using Wox.Core.Plugin;
using Wox.Plugin; using Wox.Plugin;
namespace Wox.Helper namespace Wox.Core.Plugin
{ {
public class PluginInstaller internal class PluginInstaller
{ {
public static void Install(string path) internal static void Install(string path)
{ {
if (File.Exists(path)) if (File.Exists(path))
{ {
@@ -37,11 +36,7 @@ namespace Wox.Helper
return; return;
} }
string pluginFolerPath = Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), "Plugins"); string pluginFolerPath = PluginManager.DefaultPluginDirectory;
if (!Directory.Exists(pluginFolerPath))
{
Directory.CreateDirectory(pluginFolerPath);
}
string newPluginName = plugin.Name string newPluginName = plugin.Name
.Replace("/", "_") .Replace("/", "_")
@@ -66,9 +61,9 @@ namespace Wox.Helper
plugin.Name, existingPlugin.Metadata.Version, plugin.Version, plugin.Author); plugin.Name, existingPlugin.Metadata.Version, plugin.Version, plugin.Author);
} }
MessageBoxResult result = MessageBox.Show(content, "Install plugin", DialogResult result = MessageBox.Show(content, "Install plugin", MessageBoxButtons.YesNo,
MessageBoxButton.YesNo, MessageBoxImage.Question); MessageBoxIcon.Question);
if (result == MessageBoxResult.Yes) if (result == DialogResult.Yes)
{ {
if (existingPlugin != null && Directory.Exists(existingPlugin.Metadata.PluginDirectory)) if (existingPlugin != null && Directory.Exists(existingPlugin.Metadata.PluginDirectory))
{ {
@@ -88,7 +83,7 @@ namespace Wox.Helper
// Plugins.Init(); // Plugins.Init();
//} //}
if (MessageBox.Show("You have installed plugin " + plugin.Name + " successfully.\r\n Restart Wox to take effect?", "Install plugin", if (MessageBox.Show("You have installed plugin " + plugin.Name + " successfully.\r\n Restart Wox to take effect?", "Install plugin",
MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{ {
ProcessStartInfo Info = new ProcessStartInfo(); ProcessStartInfo Info = new ProcessStartInfo();
Info.Arguments = "/C ping 127.0.0.1 -n 1 && \"" + Info.Arguments = "/C ping 127.0.0.1 -n 1 && \"" +
@@ -97,7 +92,7 @@ namespace Wox.Helper
Info.CreateNoWindow = true; Info.CreateNoWindow = true;
Info.FileName = "cmd.exe"; Info.FileName = "cmd.exe";
Process.Start(Info); Process.Start(Info);
App.Window.CloseApp(); PluginManager.API.CloseApp();
} }
} }
} }
@@ -116,15 +111,15 @@ namespace Wox.Helper
try try
{ {
metadata = JsonConvert.DeserializeObject<PluginMetadata>(File.ReadAllText(configPath)); metadata = JsonConvert.DeserializeObject<PluginMetadata>(File.ReadAllText(configPath));
metadata.PluginType = PluginType.ThirdParty; metadata.PluginType = PluginType.User;
metadata.PluginDirectory = pluginDirectory; metadata.PluginDirectory = pluginDirectory;
} }
catch (Exception) catch (System.Exception)
{ {
string error = string.Format("Parse plugin config {0} failed: json format is not valid", configPath); string error = string.Format("Parse plugin config {0} failed: json format is not valid", configPath);
#if (DEBUG) #if (DEBUG)
{ {
throw new Exception(error); throw new System.Exception(error);
} }
#endif #endif
return null; return null;
@@ -137,7 +132,7 @@ namespace Wox.Helper
metadata.Language); metadata.Language);
#if (DEBUG) #if (DEBUG)
{ {
throw new Exception(error); throw new System.Exception(error);
} }
#endif #endif
return null; return null;
@@ -148,7 +143,7 @@ namespace Wox.Helper
metadata.ExecuteFilePath); metadata.ExecuteFilePath);
#if (DEBUG) #if (DEBUG)
{ {
throw new Exception(error); throw new System.Exception(error);
} }
#endif #endif
return null; return null;

View File

@@ -4,7 +4,9 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using Wox.Core.Exception;
using Wox.Infrastructure.Http; using Wox.Infrastructure.Http;
using Wox.Infrastructure.Logger;
using Wox.Plugin; using Wox.Plugin;
namespace Wox.Core.Plugin namespace Wox.Core.Plugin
@@ -15,6 +17,8 @@ namespace Wox.Core.Plugin
public static class PluginManager public static class PluginManager
{ {
public static String DebuggerMode { get; private set; } public static String DebuggerMode { get; private set; }
public static IPublicAPI API { get; private set; }
private static List<PluginPair> plugins = new List<PluginPair>(); private static List<PluginPair> plugins = new List<PluginPair>();
/// <summary> /// <summary>
@@ -22,12 +26,32 @@ namespace Wox.Core.Plugin
/// </summary> /// </summary>
private static List<string> pluginDirectories = new List<string>(); private static List<string> pluginDirectories = new List<string>();
static PluginManager()
/// <summary>
/// Default plugin directory
/// new plugin will be installed to this directory
/// </summary>
public static string DefaultPluginDirectory
{ {
get
{
string userProfilePath = Environment.GetEnvironmentVariable("USERPROFILE");
if (string.IsNullOrEmpty(userProfilePath))
{
throw new WoxCritialException("Wox Can't Find Environment Variable UserProfile");
}
return Path.Combine(Path.Combine(userProfilePath, ".Wox"), "Plugins");
}
}
private static void SetupPluginDirectories()
{
pluginDirectories.Clear();
pluginDirectories.Add(DefaultPluginDirectory);
pluginDirectories.Add( pluginDirectories.Add(
Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Plugins")); Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Plugins"));
pluginDirectories.Add(
Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".Wox"),"Plugins"));
MakesurePluginDirectoriesExist(); MakesurePluginDirectoriesExist();
} }
@@ -37,17 +61,28 @@ namespace Wox.Core.Plugin
foreach (string pluginDirectory in pluginDirectories) foreach (string pluginDirectory in pluginDirectories)
{ {
if (!Directory.Exists(pluginDirectory)) if (!Directory.Exists(pluginDirectory))
{
try
{ {
Directory.CreateDirectory(pluginDirectory); Directory.CreateDirectory(pluginDirectory);
} }
catch (System.Exception e)
{
Log.Error(e.Message);
}
}
} }
} }
/// <summary> /// <summary>
/// Load and init all Wox plugins /// Load and init all Wox plugins
/// </summary> /// </summary>
public static void Init() public static void Init(IPublicAPI api)
{ {
if (api == null) throw new WoxCritialException("api is null");
SetupPluginDirectories();
API = api;
plugins.Clear(); plugins.Clear();
List<PluginMetadata> pluginMetadatas = PluginConfig.Parse(pluginDirectories); List<PluginMetadata> pluginMetadatas = PluginConfig.Parse(pluginDirectories);
@@ -61,11 +96,21 @@ namespace Wox.Core.Plugin
{ {
CurrentPluginMetadata = pair.Metadata, CurrentPluginMetadata = pair.Metadata,
Proxy = HttpProxy.Instance, Proxy = HttpProxy.Instance,
API = App.Window API = API
})); }));
} }
} }
public static void InstallPlugin(string path)
{
PluginInstaller.Install(path);
}
public static void Query(Query query)
{
QueryDispatcher.QueryDispatcher.Dispatch(query);
}
public static List<PluginPair> AllPlugins public static List<PluginPair> AllPlugins
{ {
get get
@@ -74,11 +119,11 @@ namespace Wox.Core.Plugin
} }
} }
public static bool HitThirdpartyKeyword(Query query) public static bool IsUserPluginQuery(Query query)
{ {
if (string.IsNullOrEmpty(query.ActionName)) return false; if (string.IsNullOrEmpty(query.ActionName)) return false;
return plugins.Any(o => o.Metadata.PluginType == PluginType.ThirdParty && o.Metadata.ActionKeyword == query.ActionName); return plugins.Any(o => o.Metadata.PluginType == PluginType.User && o.Metadata.ActionKeyword == query.ActionName);
} }
public static void ActivatePluginDebugger(string path) public static void ActivatePluginDebugger(string path)

View File

@@ -0,0 +1,7 @@
namespace Wox.Core.Plugin.QueryDispatcher
{
internal interface IQueryDispatcher
{
void Dispatch(Wox.Plugin.Query query);
}
}

View File

@@ -0,0 +1,21 @@

namespace Wox.Core.Plugin.QueryDispatcher
{
internal static class QueryDispatcher
{
private static IQueryDispatcher pluginCmd = new UserPluginQueryDispatcher();
private static IQueryDispatcher systemCmd = new SystemPluginQueryDispatcher();
public static void Dispatch(Wox.Plugin.Query query)
{
if (PluginManager.IsUserPluginQuery(query))
{
pluginCmd.Dispatch(query);
}
else
{
systemCmd.Dispatch(query);
}
}
}
}

View File

@@ -1,20 +1,17 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading; using System.Threading;
using Wox.Core.Plugin;
using Wox.Infrastructure.Storage.UserSettings; using Wox.Infrastructure.Storage.UserSettings;
using Wox.Plugin; using Wox.Plugin;
using Wox.Plugin.SystemPlugins; using Wox.Plugin.SystemPlugins;
namespace Wox.Commands namespace Wox.Core.Plugin.QueryDispatcher
{ {
public class SystemCommand : BaseCommand public class SystemPluginQueryDispatcher : IQueryDispatcher
{ {
private IEnumerable<PluginPair> allSytemPlugins = PluginManager.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.System); private IEnumerable<PluginPair> allSytemPlugins = PluginManager.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.System);
public override void Dispatch(Query query) public void Dispatch(Query query)
{ {
var queryPlugins = allSytemPlugins; var queryPlugins = allSytemPlugins;
if (UserSettingStorage.Instance.WebSearches.Exists(o => o.ActionWord == query.ActionName && o.Enabled)) if (UserSettingStorage.Instance.WebSearches.Exists(o => o.ActionWord == query.ActionName && o.Enabled))
@@ -22,7 +19,7 @@ namespace Wox.Commands
//websearch mode //websearch mode
queryPlugins = new List<PluginPair>() queryPlugins = new List<PluginPair>()
{ {
allSytemPlugins.First(o => ((ISystemPlugin)o.Plugin).ID == "565B73353DBF4806919830B9202EE3BF") allSytemPlugins.First(o => o.Metadata.ID == "565B73353DBF4806919830B9202EE3BF")
}; };
} }
@@ -34,7 +31,7 @@ namespace Wox.Commands
List<Result> results = pair1.Plugin.Query(query); List<Result> results = pair1.Plugin.Query(query);
results.ForEach(o => { o.AutoAjustScore = true; }); results.ForEach(o => { o.AutoAjustScore = true; });
App.Window.PushResults(query, pair1.Metadata, results); PluginManager.API.PushResults(query, pair1.Metadata, results);
}); });
} }
} }

View File

@@ -2,26 +2,24 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Wox.Core.Plugin;
using Wox.Helper;
using Wox.Infrastructure.Logger; using Wox.Infrastructure.Logger;
using Wox.Infrastructure.Storage.UserSettings; using Wox.Infrastructure.Storage.UserSettings;
using Wox.Plugin; using Wox.Plugin;
namespace Wox.Commands namespace Wox.Core.Plugin.QueryDispatcher
{ {
public class PluginCommand : BaseCommand public class UserPluginQueryDispatcher : IQueryDispatcher
{ {
public override void Dispatch(Query query) public void Dispatch(Query query)
{ {
PluginPair thirdPlugin = PluginManager.AllPlugins.FirstOrDefault(o => o.Metadata.ActionKeyword == query.ActionName); PluginPair userPlugin = PluginManager.AllPlugins.FirstOrDefault(o => o.Metadata.ActionKeyword == query.ActionName);
if (thirdPlugin != null && !string.IsNullOrEmpty(thirdPlugin.Metadata.ActionKeyword)) if (userPlugin != null && !string.IsNullOrEmpty(userPlugin.Metadata.ActionKeyword))
{ {
var customizedPluginConfig = UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == thirdPlugin.Metadata.ID); var customizedPluginConfig = UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == userPlugin.Metadata.ID);
if (customizedPluginConfig != null && customizedPluginConfig.Disabled) if (customizedPluginConfig != null && customizedPluginConfig.Disabled)
{ {
//need to stop the loading animation //need to stop the loading animation
UpdateResultView(null); PluginManager.API.StopLoadingBar();
return; return;
} }
@@ -29,12 +27,12 @@ namespace Wox.Commands
{ {
try try
{ {
List<Result> results = thirdPlugin.Plugin.Query(query) ?? new List<Result>(); List<Result> results = userPlugin.Plugin.Query(query) ?? new List<Result>();
App.Window.PushResults(query,thirdPlugin.Metadata,results); PluginManager.API.PushResults(query,userPlugin.Metadata,results);
} }
catch (Exception queryException) catch (System.Exception queryException)
{ {
Log.Error(string.Format("Plugin {0} query failed: {1}", thirdPlugin.Metadata.Name, Log.Error(string.Format("Plugin {0} query failed: {1}", userPlugin.Metadata.Name,
queryException.Message)); queryException.Message));
#if (DEBUG) #if (DEBUG)
{ {

5
Wox.Core/README.md Normal file
View File

@@ -0,0 +1,5 @@
What does Wox.Core do?
=====
* Handle Query
* Loading Plugins (including system plugin and user plugin)

View File

@@ -1,4 +0,0 @@
What does Wox.Core do?
* Handle Query
* Loading Plugins

View File

@@ -18,7 +18,7 @@
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath> <OutputPath>..\Output\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
@@ -32,18 +32,33 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.6.0.7\lib\net35\Newtonsoft.Json.dll</HintPath> <HintPath>..\packages\Newtonsoft.Json.6.0.7\lib\net35\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Exception\ExceptionFormatter.cs" />
<Compile Include="Exception\WoxCritialException.cs" />
<Compile Include="Exception\WoxException.cs" />
<Compile Include="Exception\WoxHttpException.cs" />
<Compile Include="Exception\WoxJsonRPCException.cs" />
<Compile Include="Plugin\PluginInstaller.cs" />
<Compile Include="Plugin\QueryDispatcher\IQueryDispatcher.cs" />
<Compile Include="Plugin\QueryDispatcher\QueryDispatcher.cs" />
<Compile Include="Plugin\QueryDispatcher\UserPluginQueryDispatcher.cs" />
<Compile Include="Plugin\QueryDispatcher\SystemPluginQueryDispatcher.cs" />
<Compile Include="Plugin\JsonRPCPlugin.cs" /> <Compile Include="Plugin\JsonRPCPlugin.cs" />
<Compile Include="Plugin\JsonRPCPluginLoader.cs" /> <Compile Include="Plugin\JsonRPCPluginLoader.cs" />
<Compile Include="Plugin\CSharpPluginLoader.cs" /> <Compile Include="Plugin\CSharpPluginLoader.cs" />
@@ -55,7 +70,7 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="README.txt" /> <None Include="README.md" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Wox.Infrastructure\Wox.Infrastructure.csproj"> <ProjectReference Include="..\Wox.Infrastructure\Wox.Infrastructure.csproj">

View File

@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Newtonsoft.Json" version="6.0.7" targetFramework="net35" /> <package id="Newtonsoft.Json" version="6.0.7" targetFramework="net35" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net35" />
</packages> </packages>

View File

@@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Wox.Infrastructure
{
public static class ChineseToPinYin
{
[Obsolete]
public static string ToPinYin(string txt)
{
return txt.Unidecode();
}
}
}

View File

@@ -1,13 +0,0 @@
using System;
namespace Wox.Infrastructure.Exceptions
{
public class WoxException : Exception
{
public WoxException(string msg)
: base(msg)
{
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Reflection; using System;
using System.Reflection;
using log4net; using log4net;
namespace Wox.Infrastructure.Logger namespace Wox.Infrastructure.Logger

View File

@@ -12,13 +12,30 @@ namespace Wox.Infrastructure.Storage
[Serializable] [Serializable]
public abstract class BaseStorage<T> : IStorage where T : class,IStorage, new() public abstract class BaseStorage<T> : IStorage where T : class,IStorage, new()
{ {
private readonly string configFolder = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "Config"); private string configFolder;
private string ConfigFolder
{
get
{
if (string.IsNullOrEmpty(configFolder))
{
string userProfilePath = Environment.GetEnvironmentVariable("USERPROFILE");
if (userProfilePath == null)
{
throw new ArgumentException("Environment variable USERPROFILE is empty");
}
configFolder = Path.Combine(Path.Combine(userProfilePath, ".Wox"), "Config");
}
return configFolder;
}
}
protected string ConfigPath protected string ConfigPath
{ {
get get
{ {
return Path.Combine(configFolder, ConfigName + FileSuffix); return Path.Combine(ConfigFolder, ConfigName + FileSuffix);
} }
} }
@@ -72,9 +89,9 @@ namespace Wox.Infrastructure.Storage
{ {
if (!File.Exists(ConfigPath)) if (!File.Exists(ConfigPath))
{ {
if (!Directory.Exists(configFolder)) if (!Directory.Exists(ConfigFolder))
{ {
Directory.CreateDirectory(configFolder); Directory.CreateDirectory(ConfigFolder);
} }
File.Create(ConfigPath).Close(); File.Create(ConfigPath).Close();
} }

View File

@@ -175,6 +175,14 @@ namespace Wox.Infrastructure.Storage.UserSettings
{ {
storage.ProgramSuffixes = "lnk;exe;appref-ms;bat"; storage.ProgramSuffixes = "lnk;exe;appref-ms;bat";
} }
if (storage.QueryBoxFont == null)
{
storage.QueryBoxFont = FontFamily.GenericSansSerif.Name;
}
if (storage.ResultItemFont == null)
{
storage.ResultItemFont = FontFamily.GenericSansSerif.Name;
}
} }
} }

View File

@@ -56,9 +56,6 @@
<Reference Include="WindowsBase" /> <Reference Include="WindowsBase" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Exceptions\WoxException.cs" />
<Compile Include="Exceptions\WoxHttpException.cs" />
<Compile Include="Exceptions\WoxJsonRPCException.cs" />
<Compile Include="Http\HttpProxy.cs" /> <Compile Include="Http\HttpProxy.cs" />
<Compile Include="Logger\Log.cs" /> <Compile Include="Logger\Log.cs" />
<Compile Include="PeHeaderReader.cs" /> <Compile Include="PeHeaderReader.cs" />
@@ -67,21 +64,18 @@
<Compile Include="Storage\JsonStrorage.cs" /> <Compile Include="Storage\JsonStrorage.cs" />
<Compile Include="Storage\UserSettings\CustomizedPluginConfig.cs" /> <Compile Include="Storage\UserSettings\CustomizedPluginConfig.cs" />
<Compile Include="Storage\UserSettings\FolderLink.cs" /> <Compile Include="Storage\UserSettings\FolderLink.cs" />
<Compile Include="Storage\UserSettings\PluginHotkey.cs" />
<Compile Include="Storage\UserSettings\ProgramSource.cs" />
<Compile Include="Storage\UserSettings\UserSettingStorage.cs" />
<Compile Include="Storage\UserSettings\WebSearch.cs" />
<Compile Include="Timeit.cs" /> <Compile Include="Timeit.cs" />
<Compile Include="Unidecoder.Characters.cs" /> <Compile Include="Unidecoder.Characters.cs" />
<Compile Include="ChineseToPinYin.cs" />
<Compile Include="Http\HttpRequest.cs" /> <Compile Include="Http\HttpRequest.cs" />
<Compile Include="Storage\BaseStorage.cs" /> <Compile Include="Storage\BaseStorage.cs" />
<Compile Include="FuzzyMatcher.cs" /> <Compile Include="FuzzyMatcher.cs" />
<Compile Include="Hotkey\GlobalHotkey.cs" /> <Compile Include="Hotkey\GlobalHotkey.cs" />
<Compile Include="Hotkey\HotkeyModel.cs" /> <Compile Include="Hotkey\HotkeyModel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Storage\UserSelectedRecordStorage.cs" />
<Compile Include="Storage\UserSettings\UserSettingStorage.cs" />
<Compile Include="Storage\UserSettings\PluginHotkey.cs" />
<Compile Include="Storage\UserSettings\ProgramSource.cs" />
<Compile Include="Storage\UserSettings\WebSearch.cs" />
<Compile Include="StringEmptyConverter.cs" />
<Compile Include="Unidecoder.cs" /> <Compile Include="Unidecoder.cs" />
<Compile Include="WindowsShellRun.cs" /> <Compile Include="WindowsShellRun.cs" />
</ItemGroup> </ItemGroup>

View File

@@ -4,6 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:infrastructure="clr-namespace:Wox.Infrastructure;assembly=Wox.Infrastructure" xmlns:infrastructure="clr-namespace:Wox.Infrastructure;assembly=Wox.Infrastructure"
xmlns:program="clr-namespace:Wox.Plugin.SystemPlugins.Program"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="600"> d:DesignHeight="300" d:DesignWidth="600">
@@ -26,7 +27,7 @@
<GridViewColumn Header="Location" Width="400"> <GridViewColumn Header="Location" Width="400">
<GridViewColumn.CellTemplate> <GridViewColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<TextBlock Text="{Binding Location, ConverterParameter=(null), Converter={infrastructure:StringEmptyConverter}}"/> <TextBlock Text="{Binding Location, ConverterParameter=(null), Converter={program:StringEmptyConverter}}"/>
</DataTemplate> </DataTemplate>
</GridViewColumn.CellTemplate> </GridViewColumn.CellTemplate>
</GridViewColumn> </GridViewColumn>

View File

@@ -1,11 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Markup; using System.Windows.Markup;
namespace Wox.Infrastructure namespace Wox.Plugin.SystemPlugins.Program
{ {
public class StringEmptyConverter : MarkupExtension, IValueConverter public class StringEmptyConverter : MarkupExtension, IValueConverter
{ {

View File

@@ -8,7 +8,7 @@ using Wox.Infrastructure.Storage.UserSettings;
namespace Wox.Plugin.SystemPlugins namespace Wox.Plugin.SystemPlugins
{ {
public class ThirdpartyPluginIndicator : BaseSystemPlugin public class UserPluginIndicator : BaseSystemPlugin
{ {
private List<PluginPair> allPlugins = new List<PluginPair>(); private List<PluginPair> allPlugins = new List<PluginPair>();
private PluginInitContext context; private PluginInitContext context;

View File

@@ -86,6 +86,7 @@
<Compile Include="Program\ProgramSuffixes.xaml.cs"> <Compile Include="Program\ProgramSuffixes.xaml.cs">
<DependentUpon>ProgramSuffixes.xaml</DependentUpon> <DependentUpon>ProgramSuffixes.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Program\StringEmptyConverter.cs" />
<Compile Include="SuggestionSources\Baidu.cs" /> <Compile Include="SuggestionSources\Baidu.cs" />
<Compile Include="SuggestionSources\SuggestionSourceFactory.cs" /> <Compile Include="SuggestionSources\SuggestionSourceFactory.cs" />
<Compile Include="Sys\SysSettings.xaml.cs"> <Compile Include="Sys\SysSettings.xaml.cs">
@@ -102,7 +103,7 @@
<Compile Include="Program\Programs.cs" /> <Compile Include="Program\Programs.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Sys\Sys.cs" /> <Compile Include="Sys\Sys.cs" />
<Compile Include="ThirdpartyPluginIndicator.cs" /> <Compile Include="UserPluginIndicator.cs" />
<Compile Include="SuggestionSources\Google.cs" /> <Compile Include="SuggestionSources\Google.cs" />
<Compile Include="SuggestionSources\ISuggestionSource.cs" /> <Compile Include="SuggestionSources\ISuggestionSource.cs" />
<Compile Include="WebSearch\WebSearchSetting.xaml.cs"> <Compile Include="WebSearch\WebSearchSetting.xaml.cs">

View File

@@ -6,7 +6,12 @@ namespace Wox.Plugin
{ {
public interface IPublicAPI public interface IPublicAPI
{ {
/// <summary>
/// Push result to query window
/// </summary>
/// <param name="query"></param>
/// <param name="plugin"></param>
/// <param name="results"></param>
void PushResults(Query query,PluginMetadata plugin, List<Result> results); void PushResults(Query query,PluginMetadata plugin, List<Result> results);
bool ShellRun(string cmd, bool runAsAdministrator = false); bool ShellRun(string cmd, bool runAsAdministrator = false);

View File

@@ -8,6 +8,6 @@ namespace Wox.Plugin
public enum PluginType public enum PluginType
{ {
System, System,
ThirdParty User
} }
} }

5
Wox.Plugin/README.md Normal file
View File

@@ -0,0 +1,5 @@
What does Wox.Plugin do?
====
* Define base objects and interfaces for plugins
* Plugin Author who making C# plugin should reference this DLL via nuget

View File

@@ -59,6 +59,9 @@
<Compile Include="Result.cs" /> <Compile Include="Result.cs" />
<Compile Include="ActionContext.cs" /> <Compile Include="ActionContext.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="README.md" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Moq;
using NUnit.Framework;
using Wox.Core.Exception;
using Wox.Core.Plugin;
using Wox.Plugin;
namespace Wox.Test.Plugins
{
[TestFixture]
public class PluginInitTest
{
[Test]
public void CouldNotFindUserProfileTest()
{
var api = new Mock<IPublicAPI>();
Environment.SetEnvironmentVariable("USERPROFILE", "");
Assert.Throws(typeof(WoxCritialException), () => PluginManager.Init(api.Object));
}
[Test]
public void PublicAPIIsNullTest()
{
Assert.Throws(typeof(WoxCritialException), () => PluginManager.Init(null));
}
}
}

View File

@@ -32,6 +32,9 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Moq">
<HintPath>..\packages\Moq.4.2.1409.1722\lib\net35\Moq.dll</HintPath>
</Reference>
<Reference Include="nunit.framework"> <Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath> <HintPath>..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
</Reference> </Reference>
@@ -44,6 +47,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="FuzzyMatcherTest.cs" /> <Compile Include="FuzzyMatcherTest.cs" />
<Compile Include="Plugins\PluginInitTest.cs" />
<Compile Include="QueryTest.cs" /> <Compile Include="QueryTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UrlPluginTest.cs" /> <Compile Include="UrlPluginTest.cs" />
@@ -52,6 +56,10 @@
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Wox.Core\Wox.Core.csproj">
<Project>{B749F0DB-8E75-47DB-9E5E-265D16D0C0D2}</Project>
<Name>Wox.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Wox.Infrastructure\Wox.Infrastructure.csproj"> <ProjectReference Include="..\Wox.Infrastructure\Wox.Infrastructure.csproj">
<Project>{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}</Project> <Project>{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}</Project>
<Name>Wox.Infrastructure</Name> <Name>Wox.Infrastructure</Name>

View File

@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Moq" version="4.2.1409.1722" targetFramework="net35" />
<package id="NUnit" version="2.6.3" targetFramework="net35" /> <package id="NUnit" version="2.6.3" targetFramework="net35" />
</packages> </packages>

View File

@@ -8,7 +8,13 @@
</appSettings> </appSettings>
<log4net> <log4net>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender"> <appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<file value="log.txt"/> <file type="log4net.Util.PatternString">
<converter>
<name value="WoxLogPathConverter" />
<type value="Wox.Helper.WoxLogPathConverter,Wox" />
</converter>
<conversionPattern value="%WoxLogPathConverter{log}\\log.txt" />
</file>
<appendToFile value="true"/> <appendToFile value="true"/>
<rollingStyle value="Date"/> <rollingStyle value="Date"/>
<datePattern value="yyyyMMdd-HH:mm:ss"/> <datePattern value="yyyyMMdd-HH:mm:ss"/>

View File

@@ -4,6 +4,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows; using System.Windows;
using Wox.Core.Plugin;
using Wox.Helper; using Wox.Helper;
namespace Wox.CommandArgs namespace Wox.CommandArgs
@@ -25,7 +26,7 @@ namespace Wox.CommandArgs
MessageBox.Show("Plugin " + path + " didn't exist"); MessageBox.Show("Plugin " + path + " didn't exist");
return; return;
} }
PluginInstaller.Install(path); PluginManager.InstallPlugin(path);
} }
} }
} }

View File

@@ -15,7 +15,7 @@ namespace Wox.CommandArgs
public void Execute(IList<string> args) public void Execute(IList<string> args)
{ {
PluginManager.Init(); PluginManager.Init(App.Window);
} }
} }
} }

View File

@@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wox.Plugin;
namespace Wox.Commands
{
public abstract class BaseCommand
{
public abstract void Dispatch(Query query);
protected void UpdateResultView(List<Result> results)
{
App.Window.OnUpdateResultView(results);
}
}
}

View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wox.Core.Plugin;
using Wox.Helper;
using Wox.Plugin;
namespace Wox.Commands
{
internal static class CommandFactory
{
private static PluginCommand pluginCmd = new PluginCommand();
private static SystemCommand systemCmd = new SystemCommand();
public static void DispatchCommand(Query query)
{
if (PluginManager.HitThirdpartyKeyword(query))
{
pluginCmd.Dispatch(query);
}
else
{
systemCmd.Dispatch(query);
}
}
}
}

View File

@@ -1,38 +0,0 @@
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Data;
using System.Windows.Threading;
namespace Wox.Converters
{
public class AsyncTask : INotifyPropertyChanged
{
public AsyncTask(Func<object> valueFunc)
{
LoadValue(valueFunc);
}
private void LoadValue(Func<object> valueFunc)
{
var frame = new DispatcherFrame();
ThreadPool.QueueUserWorkItem(delegate
{
object returnValue =
AsyncValue = valueFunc();
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("AsyncValue"));
});
}
public event PropertyChangedEventHandler PropertyChanged;
public object AsyncValue
{
get;
set;
}
}
}

View File

@@ -8,6 +8,7 @@ using System.Windows.Forms;
using System.Windows.Threading; using System.Windows.Threading;
using System.Xml; using System.Xml;
using Microsoft.Win32; using Microsoft.Win32;
using Wox.Core.Exception;
using Wox.Infrastructure.Logger; using Wox.Infrastructure.Logger;
namespace Wox.Helper.ErrorReporting namespace Wox.Helper.ErrorReporting
@@ -16,10 +17,9 @@ namespace Wox.Helper.ErrorReporting
{ {
public static void UnhandledExceptionHandle(object sender, System.UnhandledExceptionEventArgs e) public static void UnhandledExceptionHandle(object sender, System.UnhandledExceptionEventArgs e)
{ {
if (System.Diagnostics.Debugger.IsAttached) return; if (Debugger.IsAttached) return;
string error = CreateExceptionReport("System.AppDomain.UnhandledException", e.ExceptionObject);
string error = ExceptionFormatter.FormatExcpetion(e.ExceptionObject);
//e.IsTerminating is always true in most times, so try to avoid use this property //e.IsTerminating is always true in most times, so try to avoid use this property
//http://stackoverflow.com/questions/10982443/what-causes-the-unhandledexceptioneventargs-isterminating-flag-to-be-true-or-fal //http://stackoverflow.com/questions/10982443/what-causes-the-unhandledexceptioneventargs-isterminating-flag-to-be-true-or-fal
Log.Error(error); Log.Error(error);
@@ -31,211 +31,22 @@ namespace Wox.Helper.ErrorReporting
if (Debugger.IsAttached) return; if (Debugger.IsAttached) return;
e.Handled = true; e.Handled = true;
string error = CreateExceptionReport("System.Windows.Application.DispatcherUnhandledException", e.Exception); string error = ExceptionFormatter.FormatExcpetion(e.Exception);
Log.Error(error); Log.Error(error);
TryShowErrorMessageBox(error, e.Exception); TryShowErrorMessageBox(error, e.Exception);
} }
public static void ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) public static void ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{ {
if (Debugger.IsAttached) return; if (Debugger.IsAttached) return;
string error = CreateExceptionReport("System.Windows.Forms.Application.ThreadException", e.Exception); string error = ExceptionFormatter.FormatExcpetion(e.Exception);
Log.Fatal(error); Log.Fatal(error);
TryShowErrorMessageBox(error, e.Exception); TryShowErrorMessageBox(error, e.Exception);
} }
private static string CreateExceptionReport(string ev, object exceptionObject)
{
var sb = new StringBuilder();
sb.AppendLine("## Exception");
sb.AppendLine();
sb.AppendLine("```");
var ex = exceptionObject as Exception;
if (ex != null)
{
var exlist = new List<StringBuilder>();
while (ex != null)
{
var exsb = new StringBuilder();
exsb.Append(ex.GetType().FullName);
exsb.Append(": ");
exsb.AppendLine(ex.Message);
if (ex.Source != null)
{
exsb.Append(" Source: ");
exsb.AppendLine(ex.Source);
}
if (ex.TargetSite != null)
{
exsb.Append(" TargetAssembly: ");
exsb.AppendLine(ex.TargetSite.Module.Assembly.ToString());
exsb.Append(" TargetModule: ");
exsb.AppendLine(ex.TargetSite.Module.ToString());
exsb.Append(" TargetSite: ");
exsb.AppendLine(ex.TargetSite.ToString());
}
exsb.AppendLine(ex.StackTrace);
exlist.Add(exsb);
ex = ex.InnerException;
}
foreach (var result in exlist.Select(o => o.ToString()).Reverse())
{
sb.AppendLine(result);
}
sb.AppendLine("```");
sb.AppendLine();
}
else
{
sb.AppendLine(exceptionObject.GetType().FullName);
sb.AppendLine(new StackTrace().ToString());
sb.AppendLine("```");
sb.AppendLine();
}
sb.AppendLine("## Environment");
sb.AppendLine();
sb.Append("* Command Line: ");
sb.AppendLine(Environment.CommandLine);
sb.Append("* Exception Handle: ");
sb.AppendLine(ev);
sb.Append("* Timestamp: ");
sb.AppendLine(XmlConvert.ToString(DateTime.Now));
sb.Append("* IntPtr Length: ");
sb.AppendLine(IntPtr.Size.ToString());
sb.Append("* System Version: ");
sb.AppendLine(Environment.OSVersion.VersionString);
sb.Append("* CLR Version: ");
sb.AppendLine(Environment.Version.ToString());
sb.AppendLine("* Installed .NET Framework: ");
foreach (var result in GetFrameworkVersionFromRegistry())
{
sb.Append(" * ");
sb.AppendLine(result);
}
sb.AppendLine();
sb.AppendLine("## Assemblies - " + System.AppDomain.CurrentDomain.FriendlyName);
sb.AppendLine();
foreach (var ass in System.AppDomain.CurrentDomain.GetAssemblies().OrderBy(o => o.GlobalAssemblyCache ? 100 : 0))
{
sb.Append("* ");
sb.Append(ass.FullName);
sb.Append(" (");
sb.Append(SyntaxSugars.CallOrRescueDefault(() => ass.Location, "not supported"));
sb.AppendLine(")");
}
var process = System.Diagnostics.Process.GetCurrentProcess();
sb.AppendLine();
sb.AppendLine("## Modules - " + process.ProcessName);
sb.AppendLine();
foreach (ProcessModule mod in process.Modules)
{
sb.Append("* ");
sb.Append(mod.FileName);
sb.Append(" (");
sb.Append(mod.FileVersionInfo.FileDescription);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.FileVersion);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.ProductName);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.ProductVersion);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.CompanyName);
sb.Append("), ");
sb.Append(string.Format("0x{0:X16}", mod.BaseAddress.ToInt64()));
sb.AppendLine();
}
sb.AppendLine();
sb.AppendLine("## Threads - " + process.Threads.Count);
sb.AppendLine();
foreach (ProcessThread th in process.Threads)
{
sb.Append("* ");
sb.AppendLine(string.Format("{0}, {1} {2}, Started: {3}, StartAddress: 0x{4:X16}", th.Id, th.ThreadState, th.PriorityLevel, th.StartTime, th.StartAddress.ToInt64()));
}
return sb.ToString();
}
// http://msdn.microsoft.com/en-us/library/hh925568%28v=vs.110%29.aspx
private static List<string> GetFrameworkVersionFromRegistry()
{
try
{
var result = new List<string>();
using (RegistryKey ndpKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\"))
{
foreach (string versionKeyName in ndpKey.GetSubKeyNames())
{
if (versionKeyName.StartsWith("v"))
{
RegistryKey versionKey = ndpKey.OpenSubKey(versionKeyName);
string name = (string)versionKey.GetValue("Version", "");
string sp = versionKey.GetValue("SP", "").ToString();
string install = versionKey.GetValue("Install", "").ToString();
if (install != "")
if (sp != "" && install == "1")
result.Add(string.Format("{0} {1} SP{2}", versionKeyName, name, sp));
else
result.Add(string.Format("{0} {1}", versionKeyName, name));
if (name != "")
{
continue;
}
foreach (string subKeyName in versionKey.GetSubKeyNames())
{
RegistryKey subKey = versionKey.OpenSubKey(subKeyName);
name = (string)subKey.GetValue("Version", "");
if (name != "")
sp = subKey.GetValue("SP", "").ToString();
install = subKey.GetValue("Install", "").ToString();
if (install != "")
{
if (sp != "" && install == "1")
result.Add(string.Format("{0} {1} {2} SP{3}", versionKeyName, subKeyName, name, sp));
else if (install == "1")
result.Add(string.Format("{0} {1} {2}", versionKeyName, subKeyName, name));
}
}
}
}
}
using (RegistryKey ndpKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\"))
{
int releaseKey = (int)ndpKey.GetValue("Release");
{
if (releaseKey == 378389)
result.Add("v4.5");
if (releaseKey == 378675)
result.Add("v4.5.1 installed with Windows 8.1");
if (releaseKey == 378758)
result.Add("4.5.1 installed on Windows 8, Windows 7 SP1, or Windows Vista SP2");
}
}
return result;
}
catch (Exception e)
{
return new List<string>();
}
}
public static bool TryShowErrorMessageBox(string error, object exceptionObject) public static bool TryShowErrorMessageBox(string error, object exceptionObject)
{ {
var title = "Wox - Unhandled Exception"; var title = "Wox - Unhandled Exception";
@@ -271,11 +82,13 @@ namespace Wox.Helper.ErrorReporting
var dialog = new WPFErrorReportingDialog(error, title, exceptionObject); var dialog = new WPFErrorReportingDialog(error, title, exceptionObject);
dialog.ShowDialog(); dialog.ShowDialog();
} }
private static void ShowWPFMessageBox(string error, string title) private static void ShowWPFMessageBox(string error, string title)
{ {
System.Windows.MessageBox.Show(error, title, MessageBoxButton.OK, MessageBoxImage.Error, System.Windows.MessageBox.Show(error, title, MessageBoxButton.OK, MessageBoxImage.Error,
MessageBoxResult.OK, System.Windows.MessageBoxOptions.None); MessageBoxResult.OK, System.Windows.MessageBoxOptions.None);
} }
private static void ShowWindowsFormsMessageBox(string error, string title) private static void ShowWindowsFormsMessageBox(string error, string title)
{ {
System.Windows.Forms.MessageBox.Show(error, title, MessageBoxButtons.OK, System.Windows.Forms.MessageBox.Show(error, title, MessageBoxButtons.OK,

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace Wox.Helper
{
public class WoxLogPathConverter : log4net.Util.PatternConverter
{
protected override void Convert(TextWriter writer, object state)
{
string userProfilePath = Environment.GetEnvironmentVariable("USERPROFILE");
writer.Write(Path.Combine(userProfilePath, ".Wox"));
}
}
}

View File

@@ -9,8 +9,8 @@ namespace Wox.ImageLoader
[Serializable] [Serializable]
public class ImageCacheStroage : BinaryStorage<ImageCacheStroage> public class ImageCacheStroage : BinaryStorage<ImageCacheStroage>
{ {
public int counter = 0; private int counter = 0;
public const int maxCached = 200; private const int maxCached = 200;
public Dictionary<string, int> TopUsedImages = new Dictionary<string, int>(); public Dictionary<string, int> TopUsedImages = new Dictionary<string, int>();
protected override string ConfigName protected override string ConfigName

View File

@@ -13,7 +13,6 @@ namespace Wox.ImageLoader
public class ImageLoader public class ImageLoader
{ {
private static readonly Dictionary<string, ImageSource> imageCache = new Dictionary<string, ImageSource>(); private static readonly Dictionary<string, ImageSource> imageCache = new Dictionary<string, ImageSource>();
private static object locker = new object();
private static readonly List<string> imageExts = new List<string> private static readonly List<string> imageExts = new List<string>
{ {
@@ -57,15 +56,13 @@ namespace Wox.ImageLoader
using (new Timeit(string.Format("Preload {0} images", imageList.Count))) using (new Timeit(string.Format("Preload {0} images", imageList.Count)))
{ {
foreach (var image in imageList) foreach (var image in imageList)
{
if (!imageCache.ContainsKey(image.Key))
{ {
ImageSource img = Load(image.Key, false); ImageSource img = Load(image.Key, false);
if (img != null) if (img != null)
{ {
img.Freeze(); //to make it copy to UI thread img.Freeze(); //to make it copy to UI thread
if (!imageCache.ContainsKey(image.Key))
{
lock (locker)
{
if (!imageCache.ContainsKey(image.Key)) if (!imageCache.ContainsKey(image.Key))
{ {
KeyValuePair<string, int> copyedImg = image; KeyValuePair<string, int> copyedImg = image;
@@ -76,7 +73,6 @@ namespace Wox.ImageLoader
} }
} }
} }
}
public static ImageSource Load(string path, bool addToCache = true) public static ImageSource Load(string path, bool addToCache = true)
{ {
@@ -109,18 +105,12 @@ namespace Wox.ImageLoader
if (img != null && addToCache) if (img != null && addToCache)
{
if (!imageCache.ContainsKey(path))
{
lock (locker)
{ {
if (!imageCache.ContainsKey(path)) if (!imageCache.ContainsKey(path))
{ {
imageCache.Add(path, img); imageCache.Add(path, img);
} }
} }
}
}
return img; return img;
} }

View File

@@ -14,7 +14,6 @@ using WindowsInput;
using WindowsInput.Native; using WindowsInput.Native;
using NHotkey; using NHotkey;
using NHotkey.Wpf; using NHotkey.Wpf;
using Wox.Commands;
using Wox.Core.Plugin; using Wox.Core.Plugin;
using Wox.Helper; using Wox.Helper;
using Wox.Infrastructure; using Wox.Infrastructure;
@@ -22,6 +21,7 @@ using Wox.Infrastructure.Hotkey;
using Wox.Infrastructure.Storage; using Wox.Infrastructure.Storage;
using Wox.Infrastructure.Storage.UserSettings; using Wox.Infrastructure.Storage.UserSettings;
using Wox.Plugin; using Wox.Plugin;
using Wox.Storage;
using Wox.Update; using Wox.Update;
using Application = System.Windows.Application; using Application = System.Windows.Application;
using Brushes = System.Windows.Media.Brushes; using Brushes = System.Windows.Media.Brushes;
@@ -37,6 +37,7 @@ using Path = System.IO.Path;
using Rectangle = System.Drawing.Rectangle; using Rectangle = System.Drawing.Rectangle;
using TextBox = System.Windows.Controls.TextBox; using TextBox = System.Windows.Controls.TextBox;
using ToolTip = System.Windows.Controls.ToolTip; using ToolTip = System.Windows.Controls.ToolTip;
using Wox.Infrastructure.Logger;
namespace Wox namespace Wox
{ {
@@ -122,12 +123,12 @@ namespace Wox
public void InstallPlugin(string path) public void InstallPlugin(string path)
{ {
Dispatcher.Invoke(new Action(() => PluginInstaller.Install(path))); Dispatcher.Invoke(new Action(() => PluginManager.InstallPlugin(path)));
} }
public void ReloadPlugins() public void ReloadPlugins()
{ {
Dispatcher.Invoke(new Action(PluginManager.Init)); Dispatcher.Invoke(new Action(()=> PluginManager.Init(this)));
} }
public List<PluginPair> GetAllPlugins() public List<PluginPair> GetAllPlugins()
@@ -172,14 +173,8 @@ namespace Wox
pnlResult.RightMouseClickEvent += pnlResult_RightMouseClickEvent; pnlResult.RightMouseClickEvent += pnlResult_RightMouseClickEvent;
ThreadPool.SetMaxThreads(30, 10); ThreadPool.SetMaxThreads(30, 10);
try ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
{
SetTheme(UserSettingStorage.Instance.Theme);
}
catch (Exception)
{
SetTheme(UserSettingStorage.Instance.Theme = "Dark");
}
SetHotkey(UserSettingStorage.Instance.Hotkey, OnHotkey); SetHotkey(UserSettingStorage.Instance.Hotkey, OnHotkey);
SetCustomPluginHotkey(); SetCustomPluginHotkey();
@@ -192,7 +187,7 @@ namespace Wox
ThreadPool.QueueUserWorkItem(o => ThreadPool.QueueUserWorkItem(o =>
{ {
Thread.Sleep(50); Thread.Sleep(50);
PluginManager.Init(); PluginManager.Init(this);
}); });
ThreadPool.QueueUserWorkItem(o => ThreadPool.QueueUserWorkItem(o =>
{ {
@@ -357,9 +352,9 @@ namespace Wox
}, TimeSpan.FromMilliseconds(100), null); }, TimeSpan.FromMilliseconds(100), null);
queryHasReturn = false; queryHasReturn = false;
var q = new Query(lastQuery); var q = new Query(lastQuery);
CommandFactory.DispatchCommand(q); PluginManager.Query(q);
BackToResultMode(); BackToResultMode();
if (PluginManager.HitThirdpartyKeyword(q)) if (PluginManager.IsUserPluginQuery(q))
{ {
Dispatcher.DelayInvoke("ShowProgressbar", originQuery => Dispatcher.DelayInvoke("ShowProgressbar", originQuery =>
{ {
@@ -676,44 +671,6 @@ namespace Wox
} }
} }
public void SetTheme(string themeName)
{
var dict = new ResourceDictionary
{
Source = new Uri(Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), "Themes\\" + themeName + ".xaml"), UriKind.Absolute)
};
Style queryBoxStyle = dict["QueryBoxStyle"] as Style;
if (queryBoxStyle != null)
{
queryBoxStyle.Setters.Add(new Setter(TextBox.FontFamilyProperty, new FontFamily(UserSettingStorage.Instance.QueryBoxFont)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontStyle)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontWeight)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontStretch)));
}
Style resultItemStyle = dict["ItemTitleStyle"] as Style;
Style resultSubItemStyle = dict["ItemSubTitleStyle"] as Style;
Style resultItemSelectedStyle = dict["ItemTitleSelectedStyle"] as Style;
Style resultSubItemSelectedStyle = dict["ItemSubTitleSelectedStyle"] as Style;
if (resultItemStyle != null && resultSubItemStyle != null && resultSubItemSelectedStyle != null && resultItemSelectedStyle != null)
{
Setter fontFamily = new Setter(TextBlock.FontFamilyProperty, new FontFamily(UserSettingStorage.Instance.ResultItemFont));
Setter fontStyle = new Setter(TextBlock.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontStyle));
Setter fontWeight = new Setter(TextBlock.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontWeight));
Setter fontStretch = new Setter(TextBlock.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontStretch));
Setter[] setters = new Setter[] { fontFamily, fontStyle, fontWeight, fontStretch };
Array.ForEach(new Style[] { resultItemStyle, resultSubItemStyle, resultItemSelectedStyle, resultSubItemSelectedStyle }, o => Array.ForEach(setters, p => o.Setters.Add(p)));
}
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(dict);
this.Opacity = this.AllowsTransparency ? UserSettingStorage.Instance.Opacity : 1;
}
public bool ShellRun(string cmd, bool runAsAdministrator = false) public bool ShellRun(string cmd, bool runAsAdministrator = false)
{ {
try try
@@ -739,7 +696,7 @@ namespace Wox
string[] files = (string[])e.Data.GetData(System.Windows.DataFormats.FileDrop); string[] files = (string[])e.Data.GetData(System.Windows.DataFormats.FileDrop);
if (files[0].ToLower().EndsWith(".wox")) if (files[0].ToLower().EndsWith(".wox"))
{ {
PluginInstaller.Install(files[0]); PluginManager.InstallPlugin(files[0]);
} }
else else
{ {

View File

@@ -172,8 +172,7 @@ namespace Wox
} }
//PreviewPanel //PreviewPanel
App.Window.SetTheme(UserSettingStorage.Instance.Theme); ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
#endregion #endregion
#region Plugin #region Plugin
@@ -195,7 +194,7 @@ namespace Wox
new CollectionContainer new CollectionContainer
{ {
Collection = Collection =
PluginManager.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.ThirdParty) PluginManager.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.User)
} }
}; };
lbPlugins.ItemsSource = plugins; lbPlugins.ItemsSource = plugins;
@@ -366,7 +365,7 @@ namespace Wox
private void ThemeComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) private void ThemeComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
string themeName = themeComboBox.SelectedItem.ToString(); string themeName = themeComboBox.SelectedItem.ToString();
MainWindow.SetTheme(themeName); ThemeManager.ChangeTheme(themeName);
UserSettingStorage.Instance.Theme = themeName; UserSettingStorage.Instance.Theme = themeName;
UserSettingStorage.Instance.Save(); UserSettingStorage.Instance.Save();
} }
@@ -379,7 +378,7 @@ namespace Wox
this.cbQueryBoxFontFaces.SelectedItem = ((FontFamily)cbQueryBoxFont.SelectedItem).ChooseRegularFamilyTypeface(); this.cbQueryBoxFontFaces.SelectedItem = ((FontFamily)cbQueryBoxFont.SelectedItem).ChooseRegularFamilyTypeface();
UserSettingStorage.Instance.Save(); UserSettingStorage.Instance.Save();
App.Window.SetTheme(UserSettingStorage.Instance.Theme); ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
} }
private void CbQueryBoxFontFaces_OnSelectionChanged(object sender, SelectionChangedEventArgs e) private void CbQueryBoxFontFaces_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
@@ -399,7 +398,7 @@ namespace Wox
UserSettingStorage.Instance.QueryBoxFontWeight = typeface.Weight.ToString(); UserSettingStorage.Instance.QueryBoxFontWeight = typeface.Weight.ToString();
UserSettingStorage.Instance.QueryBoxFontStyle = typeface.Style.ToString(); UserSettingStorage.Instance.QueryBoxFontStyle = typeface.Style.ToString();
UserSettingStorage.Instance.Save(); UserSettingStorage.Instance.Save();
App.Window.SetTheme(UserSettingStorage.Instance.Theme); ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
} }
} }
@@ -411,7 +410,7 @@ namespace Wox
this.cbResultItemFontFaces.SelectedItem = ((FontFamily)cbResultItemFont.SelectedItem).ChooseRegularFamilyTypeface(); this.cbResultItemFontFaces.SelectedItem = ((FontFamily)cbResultItemFont.SelectedItem).ChooseRegularFamilyTypeface();
UserSettingStorage.Instance.Save(); UserSettingStorage.Instance.Save();
App.Window.SetTheme(UserSettingStorage.Instance.Theme); ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
} }
private void CbResultItemFontFaces_OnSelectionChanged(object sender, SelectionChangedEventArgs e) private void CbResultItemFontFaces_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
@@ -422,8 +421,6 @@ namespace Wox
{ {
if (cbResultItemFontFaces.Items.Count > 0) if (cbResultItemFontFaces.Items.Count > 0)
cbResultItemFontFaces.SelectedIndex = 0; cbResultItemFontFaces.SelectedIndex = 0;
return;
} }
else else
{ {
@@ -431,7 +428,7 @@ namespace Wox
UserSettingStorage.Instance.ResultItemFontWeight = typeface.Weight.ToString(); UserSettingStorage.Instance.ResultItemFontWeight = typeface.Weight.ToString();
UserSettingStorage.Instance.ResultItemFontStyle = typeface.Style.ToString(); UserSettingStorage.Instance.ResultItemFontStyle = typeface.Style.ToString();
UserSettingStorage.Instance.Save(); UserSettingStorage.Instance.Save();
App.Window.SetTheme(UserSettingStorage.Instance.Theme); ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
} }
} }
@@ -445,7 +442,7 @@ namespace Wox
else else
PreviewMainPanel.Opacity = 1; PreviewMainPanel.Opacity = 1;
App.Window.SetTheme(UserSettingStorage.Instance.Theme); ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
} }
#endregion #endregion

View File

@@ -1,12 +1,9 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json; using Newtonsoft.Json;
using Wox.Infrastructure.Storage; using Wox.Infrastructure.Storage;
using Wox.Plugin; using Wox.Plugin;
namespace Wox.Infrastructure.Storage namespace Wox.Storage
{ {
public class UserSelectedRecordStorage : JsonStrorage<UserSelectedRecordStorage> public class UserSelectedRecordStorage : JsonStrorage<UserSelectedRecordStorage>
{ {

111
Wox/ThemeManager.cs Normal file
View File

@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Wox.Helper;
using Wox.Infrastructure.Logger;
using Wox.Infrastructure.Storage.UserSettings;
namespace Wox
{
internal class ThemeManager
{
private static List<string> themeDirectories = new List<string>();
static ThemeManager()
{
themeDirectories.Add(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Themes"));
string userProfilePath = Environment.GetEnvironmentVariable("USERPROFILE");
if (userProfilePath != null)
{
themeDirectories.Add(Path.Combine(Path.Combine(userProfilePath, ".Wox"), "Themes"));
}
MakesureThemeDirectoriesExist();
}
private static void MakesureThemeDirectoriesExist()
{
foreach (string pluginDirectory in themeDirectories)
{
if (!Directory.Exists(pluginDirectory))
{
try
{
Directory.CreateDirectory(pluginDirectory);
}
catch(Exception e)
{
Log.Error(e.Message);
}
}
}
}
public static void ChangeTheme(string themeName)
{
string themePath = GetThemePath(themeName);
if (string.IsNullOrEmpty(themePath))
{
themePath = GetThemePath("Dark");
if (string.IsNullOrEmpty(themePath))
{
throw new Exception("Change theme failed");
}
}
var dict = new ResourceDictionary
{
Source = new Uri(themePath, UriKind.Absolute)
};
Style queryBoxStyle = dict["QueryBoxStyle"] as Style;
if (queryBoxStyle != null)
{
queryBoxStyle.Setters.Add(new Setter(TextBox.FontFamilyProperty, new FontFamily(UserSettingStorage.Instance.QueryBoxFont)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontStyle)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontWeight)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontStretch)));
}
Style resultItemStyle = dict["ItemTitleStyle"] as Style;
Style resultSubItemStyle = dict["ItemSubTitleStyle"] as Style;
Style resultItemSelectedStyle = dict["ItemTitleSelectedStyle"] as Style;
Style resultSubItemSelectedStyle = dict["ItemSubTitleSelectedStyle"] as Style;
if (resultItemStyle != null && resultSubItemStyle != null && resultSubItemSelectedStyle != null && resultItemSelectedStyle != null)
{
Setter fontFamily = new Setter(TextBlock.FontFamilyProperty, new FontFamily(UserSettingStorage.Instance.ResultItemFont));
Setter fontStyle = new Setter(TextBlock.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontStyle));
Setter fontWeight = new Setter(TextBlock.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontWeight));
Setter fontStretch = new Setter(TextBlock.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontStretch));
Setter[] setters = new Setter[] { fontFamily, fontStyle, fontWeight, fontStretch };
Array.ForEach(new Style[] { resultItemStyle, resultSubItemStyle, resultItemSelectedStyle, resultSubItemSelectedStyle }, o => Array.ForEach(setters, p => o.Setters.Add(p)));
}
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(dict);
}
private static string GetThemePath(string themeName)
{
foreach (string themeDirectory in themeDirectories)
{
string path = Path.Combine(themeDirectory, themeName + ".xaml");
if (File.Exists(path))
{
return path;
}
}
return string.Empty;
}
}
}

View File

@@ -104,7 +104,10 @@
<Reference Include="WPFToolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" /> <Reference Include="WPFToolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Helper\WoxLogPathConverter.cs" />
<Compile Include="ImageLoader\ImageCacheStroage.cs" /> <Compile Include="ImageLoader\ImageCacheStroage.cs" />
<Compile Include="Storage\UserSelectedRecordStorage.cs" />
<Compile Include="ThemeManager.cs" />
<Compile Include="Update\NewVersionWindow.xaml.cs"> <Compile Include="Update\NewVersionWindow.xaml.cs">
<DependentUpon>NewVersionWindow.xaml</DependentUpon> <DependentUpon>NewVersionWindow.xaml</DependentUpon>
</Compile> </Compile>
@@ -124,11 +127,6 @@
<Compile Include="CommandArgs\PluginDebuggerCommandArg.cs" /> <Compile Include="CommandArgs\PluginDebuggerCommandArg.cs" />
<Compile Include="CommandArgs\QueryCommandArg.cs" /> <Compile Include="CommandArgs\QueryCommandArg.cs" />
<Compile Include="CommandArgs\ReloadPluginCommandArg.cs" /> <Compile Include="CommandArgs\ReloadPluginCommandArg.cs" />
<Compile Include="Commands\BaseCommand.cs" />
<Compile Include="Commands\CommandFactory.cs" />
<Compile Include="Commands\PluginCommand.cs" />
<Compile Include="Commands\SystemCommand.cs" />
<Compile Include="Converters\AsyncConverter.cs" />
<Compile Include="Converters\ConvertorBase.cs" /> <Compile Include="Converters\ConvertorBase.cs" />
<Compile Include="Helper\DataWebRequestFactory.cs" /> <Compile Include="Helper\DataWebRequestFactory.cs" />
<Compile Include="Helper\ErrorReporting\ErrorReporting.cs" /> <Compile Include="Helper\ErrorReporting\ErrorReporting.cs" />
@@ -148,7 +146,6 @@
</Compile> </Compile>
<Compile Include="Helper\DispatcherExtensions.cs" /> <Compile Include="Helper\DispatcherExtensions.cs" />
<Compile Include="Helper\DWMDropShadow.cs" /> <Compile Include="Helper\DWMDropShadow.cs" />
<Compile Include="Helper\PluginInstaller.cs" />
<Compile Include="HotkeyControl.xaml.cs"> <Compile Include="HotkeyControl.xaml.cs">
<DependentUpon>HotkeyControl.xaml</DependentUpon> <DependentUpon>HotkeyControl.xaml</DependentUpon>
</Compile> </Compile>
@@ -205,11 +202,6 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<None Include="Themes\Dark.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Themes\Light.xaml"> <None Include="Themes\Light.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
@@ -230,6 +222,10 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<Page Include="Themes\Dark.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Update\NewVersionWindow.xaml"> <Page Include="Update\NewVersionWindow.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>