diff --git a/src/modules/launcher/.gitattributes b/src/modules/launcher/.gitattributes new file mode 100644 index 000000000..4f8109456 --- /dev/null +++ b/src/modules/launcher/.gitattributes @@ -0,0 +1,65 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain + +PythonHome/* linguist-vendored \ No newline at end of file diff --git a/src/modules/launcher/.gitignore b/src/modules/launcher/.gitignore new file mode 100644 index 000000000..91216319f --- /dev/null +++ b/src/modules/launcher/.gitignore @@ -0,0 +1,303 @@ +## https://github.com/github/gitignore/blob/master/VisualStudio.gitignore +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +## https://github.com/github/gitignore/blob/master/C%2B%2B.gitignore +## C++ + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# New to Visual Studio +*.VC.db + +## Wox specific +Output/* +/Python.Runtime.dll +Thumbs.db +RELEASES + + +*.sublime-* +*.dgml +migrateToAutomaticPackageRestore.ps1 +*.pyd +*.pyc +*/pinyindb/* +*.diagsession +Output-Performance.txt +*.diff \ No newline at end of file diff --git a/src/modules/launcher/Deploy/local_build.ps1 b/src/modules/launcher/Deploy/local_build.ps1 new file mode 100644 index 000000000..9dd7582b1 --- /dev/null +++ b/src/modules/launcher/Deploy/local_build.ps1 @@ -0,0 +1,4 @@ +New-Alias nuget.exe ".\packages\NuGet.CommandLine.*\tools\NuGet.exe" +$env:APPVEYOR_BUILD_FOLDER = Convert-Path . +$env:APPVEYOR_BUILD_VERSION = "1.2.0" +& .\Deploy\squirrel_installer.ps1 \ No newline at end of file diff --git a/src/modules/launcher/Doc/app.ico b/src/modules/launcher/Doc/app.ico new file mode 100644 index 000000000..38c401c8c Binary files /dev/null and b/src/modules/launcher/Doc/app.ico differ diff --git a/src/modules/launcher/Doc/app.png b/src/modules/launcher/Doc/app.png new file mode 100644 index 000000000..8c9ca7971 Binary files /dev/null and b/src/modules/launcher/Doc/app.png differ diff --git a/src/modules/launcher/Doc/app.psd b/src/modules/launcher/Doc/app.psd new file mode 100644 index 000000000..833fd6529 Binary files /dev/null and b/src/modules/launcher/Doc/app.psd differ diff --git a/src/modules/launcher/Doc/app_error.png b/src/modules/launcher/Doc/app_error.png new file mode 100644 index 000000000..5106d6e8a Binary files /dev/null and b/src/modules/launcher/Doc/app_error.png differ diff --git a/src/modules/launcher/Doc/app_error.psd b/src/modules/launcher/Doc/app_error.psd new file mode 100644 index 000000000..174e9cb62 Binary files /dev/null and b/src/modules/launcher/Doc/app_error.psd differ diff --git a/src/modules/launcher/ISSUE_TEMPLATE.md b/src/modules/launcher/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..affc8518e --- /dev/null +++ b/src/modules/launcher/ISSUE_TEMPLATE.md @@ -0,0 +1,102 @@ + + +### Are you submitting a bug report? + +(write your answer here) + + + + + +### Steps to reproduce + + + +1. +2. +3. + +### Wox Error Window text + + +(paste here) + + +### Detailed logs + + +(drop your log file here) + +### Screenshots (optional) + + +(drop your screenshot here) + diff --git a/src/modules/launcher/JsonRPC/wox.py b/src/modules/launcher/JsonRPC/wox.py new file mode 100644 index 000000000..2e65a629d --- /dev/null +++ b/src/modules/launcher/JsonRPC/wox.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +from __future__ import print_function +import json +import sys +import inspect + +class Wox(object): + """ + Wox python plugin base + """ + + def __init__(self): + rpc_request = json.loads(sys.argv[1]) + # proxy is not working now + self.proxy = rpc_request.get("proxy",{}) + request_method_name = rpc_request.get("method") + request_parameters = rpc_request.get("parameters") + methods = inspect.getmembers(self, predicate=inspect.ismethod) + + request_method = dict(methods)[request_method_name] + results = request_method(*request_parameters) + + if request_method_name == "query" or request_method_name == "context_menu": + print(json.dumps({"result": results})) + + def query(self,query): + """ + sub class need to override this method + """ + return [] + + def context_menu(self, data): + """ + optional context menu entries for a result + """ + return [] + + def debug(self,msg): + """ + alert msg + """ + print("DEBUG:{}".format(msg)) + sys.exit() + +class WoxAPI(object): + + @classmethod + def change_query(cls,query,requery = False): + """ + change wox query + """ + print(json.dumps({"method": "Wox.ChangeQuery","parameters":[query,requery]})) + + @classmethod + def shell_run(cls,cmd): + """ + run shell commands + """ + print(json.dumps({"method": "Wox.ShellRun","parameters":[cmd]})) + + @classmethod + def close_app(cls): + """ + close wox + """ + print(json.dumps({"method": "Wox.CloseApp","parameters":[]})) + + @classmethod + def hide_app(cls): + """ + hide wox + """ + print(json.dumps({"method": "Wox.HideApp","parameters":[]})) + + @classmethod + def show_app(cls): + """ + show wox + """ + print(json.dumps({"method": "Wox.ShowApp","parameters":[]})) + + @classmethod + def show_msg(cls,title,sub_title,ico_path=""): + """ + show messagebox + """ + print(json.dumps({"method": "Wox.ShowMsg","parameters":[title,sub_title,ico_path]})) + + @classmethod + def open_setting_dialog(cls): + """ + open setting dialog + """ + print(json.dumps({"method": "Wox.OpenSettingDialog","parameters":[]})) + + @classmethod + def start_loadingbar(cls): + """ + start loading animation in wox + """ + print(json.dumps({"method": "Wox.StartLoadingBar","parameters":[]})) + + @classmethod + def stop_loadingbar(cls): + """ + stop loading animation in wox + """ + print(json.dumps({"method": "Wox.StopLoadingBar","parameters":[]})) + + @classmethod + def reload_plugins(cls): + """ + reload all wox plugins + """ + print(json.dumps({"method": "Wox.ReloadPlugins","parameters":[]})) diff --git a/src/modules/launcher/LICENSE b/src/modules/launcher/LICENSE new file mode 100644 index 000000000..cb4b563c0 --- /dev/null +++ b/src/modules/launcher/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2015 Wox + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/modules/launcher/Plugins/HelloWorldCSharp/App.config b/src/modules/launcher/Plugins/HelloWorldCSharp/App.config new file mode 100644 index 000000000..88fa4027b --- /dev/null +++ b/src/modules/launcher/Plugins/HelloWorldCSharp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/modules/launcher/Plugins/HelloWorldCSharp/HelloWorldCSharp.csproj b/src/modules/launcher/Plugins/HelloWorldCSharp/HelloWorldCSharp.csproj new file mode 100644 index 000000000..46006f098 --- /dev/null +++ b/src/modules/launcher/Plugins/HelloWorldCSharp/HelloWorldCSharp.csproj @@ -0,0 +1,80 @@ + + + + + Debug + AnyCPU + {03FFA443-5F50-48D5-8869-F3DF316803AA} + Library + Properties + HelloWorldCSharp + HelloWorldCSharp + v4.5.2 + 512 + true + + + AnyCPU + true + full + false + ..\..\Output\Debug\Plugins\HelloWorldCSharp\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + ..\..\Output\Release\Plugins\HelloWorldCSharp\ + TRACE + prompt + 4 + false + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + + {8451ECDD-2EA4-4966-BB0A-7BBC40138E80} + Wox.Plugin + + + + + + PreserveNewest + + + + + \ No newline at end of file diff --git a/src/modules/launcher/Plugins/HelloWorldCSharp/Images/app.png b/src/modules/launcher/Plugins/HelloWorldCSharp/Images/app.png new file mode 100644 index 000000000..8c9ca7971 Binary files /dev/null and b/src/modules/launcher/Plugins/HelloWorldCSharp/Images/app.png differ diff --git a/src/modules/launcher/Plugins/HelloWorldCSharp/Main.cs b/src/modules/launcher/Plugins/HelloWorldCSharp/Main.cs new file mode 100644 index 000000000..4f17cd43d --- /dev/null +++ b/src/modules/launcher/Plugins/HelloWorldCSharp/Main.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Wox.Plugin; + +namespace HelloWorldCSharp +{ + class Main : IPlugin + { + public List Query(Query query) + { + var result = new Result + { + Title = "Hello World from CSharp", + SubTitle = $"Query: {query.Search}", + IcoPath = "app.png" + }; + return new List {result}; + } + + public void Init(PluginInitContext context) + { + + } + } +} diff --git a/src/modules/launcher/Plugins/HelloWorldCSharp/Properties/AssemblyInfo.cs b/src/modules/launcher/Plugins/HelloWorldCSharp/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..39677ff22 --- /dev/null +++ b/src/modules/launcher/Plugins/HelloWorldCSharp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("HelloWorldCSharp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("HelloWorldCSharp")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("03ffa443-5f50-48d5-8869-f3df316803aa")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/modules/launcher/Plugins/HelloWorldCSharp/plugin.json b/src/modules/launcher/Plugins/HelloWorldCSharp/plugin.json new file mode 100644 index 000000000..b7edbd6a9 --- /dev/null +++ b/src/modules/launcher/Plugins/HelloWorldCSharp/plugin.json @@ -0,0 +1,13 @@ +{ + "ID":"CEA0FDFC6D3B4085823D60DC76F28844", + "ActionKeyword":"hc", + "Name":"Hello World CSharp", + "Description":"Hello World CSharp", + "Author":"happlebao", + "Version":"1.0.0", + "Language":"csharp", + "Website":"https://github.com/Wox-launcher/Wox", + "ExecuteFileName":"HelloWorldCSharp.dll", + "IcoPath":"app.png", + "Disabled": true +} \ No newline at end of file diff --git a/src/modules/launcher/Plugins/HelloWorldPython/Images/app.png b/src/modules/launcher/Plugins/HelloWorldPython/Images/app.png new file mode 100644 index 000000000..8c9ca7971 Binary files /dev/null and b/src/modules/launcher/Plugins/HelloWorldPython/Images/app.png differ diff --git a/src/modules/launcher/Plugins/HelloWorldPython/main.py b/src/modules/launcher/Plugins/HelloWorldPython/main.py new file mode 100644 index 000000000..e7b7edfc2 --- /dev/null +++ b/src/modules/launcher/Plugins/HelloWorldPython/main.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- + +from wox import Wox + +class HelloWorld(Wox): + + def query(self, query): + results = [] + results.append({ + "Title": "Hello World", + "SubTitle": "Query: {}".format(query), + "IcoPath":"Images/app.ico", + "ContextData": "ctxData" + }) + return results + + def context_menu(self, data): + results = [] + results.append({ + "Title": "Context menu entry", + "SubTitle": "Data: {}".format(data), + "IcoPath":"Images/app.ico" + }) + return results + +if __name__ == "__main__": + HelloWorld() \ No newline at end of file diff --git a/src/modules/launcher/Plugins/HelloWorldPython/plugin.json b/src/modules/launcher/Plugins/HelloWorldPython/plugin.json new file mode 100644 index 000000000..a928a5ae5 --- /dev/null +++ b/src/modules/launcher/Plugins/HelloWorldPython/plugin.json @@ -0,0 +1,12 @@ +{ + "ID":"2f4e384e-76ce-45c3-aea2-b16f5e5c328f", + "ActionKeyword":"h", + "Name":"Hello World Python", + "Description":"Hello World", + "Author":"happlebao", + "Version":"1.0", + "Language":"python", + "Website":"https://github.com/Wox-launcher/Wox", + "IcoPath":"Images\\app.png", + "ExecuteFileName":"main.py" +} diff --git a/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Bookmark.cs b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Bookmark.cs new file mode 100644 index 000000000..700f253e8 --- /dev/null +++ b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Bookmark.cs @@ -0,0 +1,58 @@ +using BinaryAnalysis.UnidecodeSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + + +namespace Wox.Plugin.BrowserBookmark +{ + public class Bookmark : IEquatable, IEqualityComparer + { + private string m_Name; + public string Name + { + get + { + return m_Name; + } + set + { + m_Name = value; + PinyinName = m_Name.Unidecode(); + } + } + public string PinyinName { get; private set; } + public string Url { get; set; } + public string Source { get; set; } + public int Score { get; set; } + + /* TODO: since Source maybe unimportant, we just need to compare Name and Url */ + public bool Equals(Bookmark other) + { + return Equals(this, other); + } + + public bool Equals(Bookmark x, Bookmark y) + { + if (Object.ReferenceEquals(x, y)) return true; + if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) + return false; + + return x.Name == y.Name && x.Url == y.Url; + } + + public int GetHashCode(Bookmark bookmark) + { + if (Object.ReferenceEquals(bookmark, null)) return 0; + int hashName = bookmark.Name == null ? 0 : bookmark.Name.GetHashCode(); + int hashUrl = bookmark.Url == null ? 0 : bookmark.Url.GetHashCode(); + return hashName ^ hashUrl; + } + + public override int GetHashCode() + { + return GetHashCode(this); + } + } +} diff --git a/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/ChromeBookmarks.cs b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/ChromeBookmarks.cs new file mode 100644 index 000000000..16e5c328c --- /dev/null +++ b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/ChromeBookmarks.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; + +namespace Wox.Plugin.BrowserBookmark +{ + public class ChromeBookmarks + { + private List bookmarks = new List(); + + public List GetBookmarks() + { + bookmarks.Clear(); + LoadChromeBookmarks(); + + return bookmarks; + } + + private void ParseChromeBookmarks(String path, string source) + { + if (!File.Exists(path)) return; + + string all = File.ReadAllText(path); + Regex nameRegex = new Regex("\"name\": \"(?.*?)\""); + MatchCollection nameCollection = nameRegex.Matches(all); + Regex typeRegex = new Regex("\"type\": \"(?.*?)\""); + MatchCollection typeCollection = typeRegex.Matches(all); + Regex urlRegex = new Regex("\"url\": \"(?.*?)\""); + MatchCollection urlCollection = urlRegex.Matches(all); + + List names = (from Match match in nameCollection select match.Groups["name"].Value).ToList(); + List types = (from Match match in typeCollection select match.Groups["type"].Value).ToList(); + List urls = (from Match match in urlCollection select match.Groups["url"].Value).ToList(); + + int urlIndex = 0; + for (int i = 0; i < names.Count; i++) + { + string name = DecodeUnicode(names[i]); + string type = types[i]; + if (type == "url") + { + string url = urls[urlIndex]; + urlIndex++; + + if (url == null) continue; + if (url.StartsWith("javascript:", StringComparison.OrdinalIgnoreCase)) continue; + if (url.StartsWith("vbscript:", StringComparison.OrdinalIgnoreCase)) continue; + + bookmarks.Add(new Bookmark() + { + Name = name, + Url = url, + Source = source + }); + } + } + } + + private void LoadChromeBookmarks(string path, string name) + { + if (!Directory.Exists(path)) return; + var paths = Directory.GetDirectories(path); + + foreach (var profile in paths) + { + if (File.Exists(Path.Combine(profile, "Bookmarks"))) + ParseChromeBookmarks(Path.Combine(profile, "Bookmarks"), name + (Path.GetFileName(profile) == "Default" ? "" : (" (" + Path.GetFileName(profile) + ")"))); + } + } + + private void LoadChromeBookmarks() + { + String platformPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + LoadChromeBookmarks(Path.Combine(platformPath, @"Google\Chrome\User Data"), "Google Chrome"); + LoadChromeBookmarks(Path.Combine(platformPath, @"Google\Chrome SxS\User Data"), "Google Chrome Canary"); + LoadChromeBookmarks(Path.Combine(platformPath, @"Chromium\User Data"), "Chromium"); + } + + private String DecodeUnicode(String dataStr) + { + Regex reg = new Regex(@"(?i)\\[uU]([0-9a-f]{4})"); + return reg.Replace(dataStr, m => ((char)Convert.ToInt32(m.Groups[1].Value, 16)).ToString()); + } + } +} \ No newline at end of file diff --git a/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Commands/Bookmarks.cs b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Commands/Bookmarks.cs new file mode 100644 index 000000000..049b8f166 --- /dev/null +++ b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Commands/Bookmarks.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using System.Linq; +using Wox.Infrastructure; + +namespace Wox.Plugin.BrowserBookmark.Commands +{ + internal static class Bookmarks + { + internal static bool MatchProgram(Bookmark bookmark, string queryString) + { + if (StringMatcher.FuzzySearch(queryString, bookmark.Name).IsSearchPrecisionScoreMet()) return true; + if (StringMatcher.FuzzySearch(queryString, bookmark.PinyinName).IsSearchPrecisionScoreMet()) return true; + if (StringMatcher.FuzzySearch(queryString, bookmark.Url).IsSearchPrecisionScoreMet()) return true; + + return false; + } + + internal static List LoadAllBookmarks() + { + var allbookmarks = new List(); + + var chromeBookmarks = new ChromeBookmarks(); + var mozBookmarks = new FirefoxBookmarks(); + + //TODO: Let the user select which browser's bookmarks are displayed + // Add Firefox bookmarks + mozBookmarks.GetBookmarks().ForEach(x => allbookmarks.Add(x)); + + // Add Chrome bookmarks + chromeBookmarks.GetBookmarks().ForEach(x => allbookmarks.Add(x)); + + return allbookmarks.Distinct().ToList(); + } + } +} diff --git a/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/FirefoxBookmarks.cs b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/FirefoxBookmarks.cs new file mode 100644 index 000000000..7686501cd --- /dev/null +++ b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/FirefoxBookmarks.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Data.SQLite; +using System.IO; +using System.Linq; + +namespace Wox.Plugin.BrowserBookmark +{ + public class FirefoxBookmarks + { + private const string queryAllBookmarks = @"SELECT moz_places.url, moz_bookmarks.title + FROM moz_places + INNER JOIN moz_bookmarks ON ( + moz_bookmarks.fk NOT NULL AND moz_bookmarks.fk = moz_places.id + ) + ORDER BY moz_places.visit_count DESC + "; + + private const string dbPathFormat = "Data Source ={0};Version=3;New=False;Compress=True;"; + + /// + /// Searches the places.sqlite db and returns all bookmarks + /// + public List GetBookmarks() + { + // Return empty list if the places.sqlite file cannot be found + if (string.IsNullOrEmpty(PlacesPath) || !File.Exists(PlacesPath)) + return new List(); + + var bookmarList = new List(); + + // create the connection string and init the connection + string dbPath = string.Format(dbPathFormat, PlacesPath); + using (var dbConnection = new SQLiteConnection(dbPath)) + { + // Open connection to the database file and execute the query + dbConnection.Open(); + var reader = new SQLiteCommand(queryAllBookmarks, dbConnection).ExecuteReader(); + + // return results in List format + bookmarList = reader.Select(x => new Bookmark() + { + Name = (x["title"] is DBNull) ? string.Empty : x["title"].ToString(), + Url = x["url"].ToString() + }).ToList(); + } + + return bookmarList; + } + + /// + /// Path to places.sqlite + /// + private string PlacesPath + { + get + { + var profileFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Mozilla\Firefox"); + var profileIni = Path.Combine(profileFolderPath, @"profiles.ini"); + + if (!File.Exists(profileIni)) + return string.Empty; + + // get firefox default profile directory from profiles.ini + string ini; + using (var sReader = new StreamReader(profileIni)) { + ini = sReader.ReadToEnd(); + } + + /* + Current profiles.ini structure example as of Firefox version 69.0.1 + + [Install736426B0AF4A39CB] + Default=Profiles/7789f565.default-release <== this is the default profile this plugin will get the bookmarks from. When opened Firefox will load the default profile + Locked=1 + + [Profile2] + Name=newblahprofile + IsRelative=0 + Path=C:\t6h2yuq8.newblahprofile <== Note this is a custom location path for the profile user can set, we need to cater for this in code. + + [Profile1] + Name=default + IsRelative=1 + Path=Profiles/cydum7q4.default + Default=1 + + [Profile0] + Name=default-release + IsRelative=1 + Path=Profiles/7789f565.default-release + + [General] + StartWithLastProfile=1 + Version=2 + */ + + var lines = ini.Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList(); + + var defaultProfileFolderNameRaw = lines.Where(x => x.Contains("Default=") && x != "Default=1").FirstOrDefault() ?? string.Empty; + + if (string.IsNullOrEmpty(defaultProfileFolderNameRaw)) + return string.Empty; + + var defaultProfileFolderName = defaultProfileFolderNameRaw.Split('=').Last(); + + var indexOfDefaultProfileAtttributePath = lines.IndexOf("Path="+ defaultProfileFolderName); + + // Seen in the example above, the IsRelative attribute is always above the Path attribute + var relativeAttribute = lines[indexOfDefaultProfileAtttributePath - 1]; + + return relativeAttribute == "0" // See above, the profile is located in a custom location, path is not relative, so IsRelative=0 + ? defaultProfileFolderName + @"\places.sqlite" + : Path.Combine(profileFolderPath, defaultProfileFolderName) + @"\places.sqlite"; + } + } + } + + public static class Extensions + { + public static IEnumerable Select(this SQLiteDataReader reader, Func projection) + { + while (reader.Read()) + { + yield return projection(reader); + } + } + } +} diff --git a/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Images/bookmark.png b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Images/bookmark.png new file mode 100644 index 000000000..b8aee3564 Binary files /dev/null and b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Images/bookmark.png differ diff --git a/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Languages/en.xaml b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Languages/en.xaml new file mode 100644 index 000000000..7db78333b --- /dev/null +++ b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Languages/en.xaml @@ -0,0 +1,9 @@ + + + + Browser Bookmarks + Search your browser bookmarks + + \ No newline at end of file diff --git a/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Languages/tr.xaml b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Languages/tr.xaml new file mode 100644 index 000000000..847d28c7b --- /dev/null +++ b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Languages/tr.xaml @@ -0,0 +1,9 @@ + + + + Yer İşaretleri + Tarayıcılarınızdaki yer işaretlerini arayın. + + \ No newline at end of file diff --git a/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Main.cs b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Main.cs new file mode 100644 index 000000000..a616edce0 --- /dev/null +++ b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Main.cs @@ -0,0 +1,99 @@ +using System.Collections.Generic; +using System.Linq; +using System.Windows.Controls; +using Wox.Infrastructure.Storage; +using Wox.Plugin.BrowserBookmark.Commands; +using Wox.Plugin.BrowserBookmark.Models; +using Wox.Plugin.BrowserBookmark.Views; +using Wox.Plugin.SharedCommands; + +namespace Wox.Plugin.BrowserBookmark +{ + public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, ISavable + { + private PluginInitContext context; + + private List cachedBookmarks = new List(); + + private readonly Settings _settings; + private readonly PluginJsonStorage _storage; + + public Main() + { + _storage = new PluginJsonStorage(); + _settings = _storage.Load(); + + cachedBookmarks = Bookmarks.LoadAllBookmarks(); + } + + public void Init(PluginInitContext context) + { + this.context = context; + } + + public List Query(Query query) + { + string param = query.GetAllRemainingParameter().TrimStart(); + + // Should top results be returned? (true if no search parameters have been passed) + var topResults = string.IsNullOrEmpty(param); + + var returnList = cachedBookmarks; + + if (!topResults) + { + // Since we mixed chrome and firefox bookmarks, we should order them again + returnList = cachedBookmarks.Where(o => Bookmarks.MatchProgram(o, param)).ToList(); + returnList = returnList.OrderByDescending(o => o.Score).ToList(); + } + + return returnList.Select(c => new Result() + { + Title = c.Name, + SubTitle = c.Url, + IcoPath = @"Images\bookmark.png", + Score = 5, + Action = (e) => + { + if (_settings.OpenInNewBrowserWindow) + { + c.Url.NewBrowserWindow(_settings.BrowserPath); + } + else + { + c.Url.NewTabInBrowser(_settings.BrowserPath); + } + + return true; + } + }).ToList(); + } + + public void ReloadData() + { + cachedBookmarks.Clear(); + + cachedBookmarks = Bookmarks.LoadAllBookmarks(); + } + + public string GetTranslatedPluginTitle() + { + return context.API.GetTranslation("wox_plugin_browserbookmark_plugin_name"); + } + + public string GetTranslatedPluginDescription() + { + return context.API.GetTranslation("wox_plugin_browserbookmark_plugin_description"); + } + + public Control CreateSettingPanel() + { + return new SettingsControl(_settings); + } + + public void Save() + { + _storage.Save(); + } + } +} diff --git a/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Models/Settings.cs b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Models/Settings.cs new file mode 100644 index 000000000..41d742fe6 --- /dev/null +++ b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Models/Settings.cs @@ -0,0 +1,9 @@ +namespace Wox.Plugin.BrowserBookmark.Models +{ + public class Settings : BaseModel + { + public bool OpenInNewBrowserWindow { get; set; } = true; + + public string BrowserPath { get; set; } + } +} \ No newline at end of file diff --git a/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Properties/AssemblyInfo.cs b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..982c54999 --- /dev/null +++ b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Wox.Plugin.BrowserBookmark")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Oracle Corporation")] +[assembly: AssemblyProduct("Wox.Plugin.BrowserBookmark")] +[assembly: AssemblyCopyright("Copyright © Oracle Corporation 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("7dd2e33e-d029-4661-8f1d-594e82cef077")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Views/SettingsControl.xaml b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Views/SettingsControl.xaml new file mode 100644 index 000000000..93b272fca --- /dev/null +++ b/src/modules/launcher/Plugins/Wox.Plugin.BrowserBookmark/Views/SettingsControl.xaml @@ -0,0 +1,25 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/ActionKeywords.xaml.cs b/src/modules/launcher/Wox/ActionKeywords.xaml.cs new file mode 100644 index 000000000..68024b127 --- /dev/null +++ b/src/modules/launcher/Wox/ActionKeywords.xaml.cs @@ -0,0 +1,58 @@ +using System.Windows; +using Wox.Core.Plugin; +using Wox.Core.Resource; +using Wox.Infrastructure.Exception; +using Wox.Infrastructure.UserSettings; +using Wox.Plugin; + +namespace Wox +{ + public partial class ActionKeywords : Window + { + private PluginPair _plugin; + private Settings _settings; + private readonly Internationalization _translater = InternationalizationManager.Instance; + + public ActionKeywords(string pluginId, Settings settings) + { + InitializeComponent(); + _plugin = PluginManager.GetPluginForId(pluginId); + _settings = settings; + if (_plugin == null) + { + MessageBox.Show(_translater.GetTranslation("cannotFindSpecifiedPlugin")); + Close(); + } + } + + private void ActionKeyword_OnLoaded(object sender, RoutedEventArgs e) + { + tbOldActionKeyword.Text = string.Join(Query.ActionKeywordSeperater, _plugin.Metadata.ActionKeywords.ToArray()); + tbAction.Focus(); + } + + private void BtnCancel_OnClick(object sender, RoutedEventArgs e) + { + Close(); + } + + private void btnDone_OnClick(object sender, RoutedEventArgs _) + { + var oldActionKeyword = _plugin.Metadata.ActionKeywords[0]; + var newActionKeyword = tbAction.Text.Trim(); + newActionKeyword = newActionKeyword.Length > 0 ? newActionKeyword : "*"; + if (!PluginManager.ActionKeywordRegistered(newActionKeyword)) + { + var id = _plugin.Metadata.ID; + PluginManager.ReplaceActionKeyword(id, oldActionKeyword, newActionKeyword); + MessageBox.Show(_translater.GetTranslation("success")); + Close(); + } + else + { + string msg = _translater.GetTranslation("newActionKeywordsHasBeenAssigned"); + MessageBox.Show(msg); + } + } + } +} diff --git a/src/modules/launcher/Wox/App.config b/src/modules/launcher/Wox/App.config new file mode 100644 index 000000000..aef034f76 --- /dev/null +++ b/src/modules/launcher/Wox/App.config @@ -0,0 +1,19 @@ + + + + + +
+ + + + + + + + + https://github.com/Wox-launcher/Wox + + + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/App.xaml b/src/modules/launcher/Wox/App.xaml new file mode 100644 index 000000000..53341c629 --- /dev/null +++ b/src/modules/launcher/Wox/App.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/App.xaml.cs b/src/modules/launcher/Wox/App.xaml.cs new file mode 100644 index 000000000..0fc1e8c95 --- /dev/null +++ b/src/modules/launcher/Wox/App.xaml.cs @@ -0,0 +1,169 @@ +using System; +using System.Diagnostics; +using System.Threading.Tasks; +using System.Timers; +using System.Windows; +using Wox.Core; +using Wox.Core.Plugin; +using Wox.Core.Resource; +using Wox.Helper; +using Wox.Infrastructure; +using Wox.Infrastructure.Http; +using Wox.Infrastructure.Image; +using Wox.Infrastructure.Logger; +using Wox.Infrastructure.UserSettings; +using Wox.ViewModel; +using Stopwatch = Wox.Infrastructure.Stopwatch; + +namespace Wox +{ + public partial class App : IDisposable, ISingleInstanceApp + { + public static PublicAPIInstance API { get; private set; } + private const string Unique = "Wox_Unique_Application_Mutex"; + private static bool _disposed; + private Settings _settings; + private MainViewModel _mainVM; + private SettingWindowViewModel _settingsVM; + private readonly Updater _updater = new Updater(Wox.Properties.Settings.Default.GithubRepo); + private readonly Alphabet _alphabet = new Alphabet(); + private StringMatcher _stringMatcher; + + [STAThread] + public static void Main() + { + if (SingleInstance.InitializeAsFirstInstance(Unique)) + { + using (var application = new App()) + { + application.InitializeComponent(); + application.Run(); + } + } + } + + private void OnStartup(object sender, StartupEventArgs e) + { + Stopwatch.Normal("|App.OnStartup|Startup cost", () => + { + Log.Info("|App.OnStartup|Begin Wox startup ----------------------------------------------------"); + Log.Info($"|App.OnStartup|Runtime info:{ErrorReporting.RuntimeInfo()}"); + RegisterAppDomainExceptions(); + RegisterDispatcherUnhandledException(); + + ImageLoader.Initialize(); + + _settingsVM = new SettingWindowViewModel(_updater); + _settings = _settingsVM.Settings; + + _alphabet.Initialize(_settings); + _stringMatcher = new StringMatcher(_alphabet); + StringMatcher.Instance = _stringMatcher; + _stringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision; + + PluginManager.LoadPlugins(_settings.PluginSettings); + _mainVM = new MainViewModel(_settings); + var window = new MainWindow(_settings, _mainVM); + API = new PublicAPIInstance(_settingsVM, _mainVM, _alphabet); + PluginManager.InitializePlugins(API); + Log.Info($"|App.OnStartup|Dependencies Info:{ErrorReporting.DependenciesInfo()}"); + + Current.MainWindow = window; + Current.MainWindow.Title = Constant.Wox; + + // happlebao todo temp fix for instance code logic + // load plugin before change language, because plugin language also needs be changed + InternationalizationManager.Instance.Settings = _settings; + InternationalizationManager.Instance.ChangeLanguage(_settings.Language); + // main windows needs initialized before theme change because of blur settigns + ThemeManager.Instance.Settings = _settings; + ThemeManager.Instance.ChangeTheme(_settings.Theme); + + Http.Proxy = _settings.Proxy; + + RegisterExitEvents(); + + AutoStartup(); + AutoUpdates(); + + _mainVM.MainWindowVisibility = _settings.HideOnStartup ? Visibility.Hidden : Visibility.Visible; + Log.Info("|App.OnStartup|End Wox startup ---------------------------------------------------- "); + }); + } + + + private void AutoStartup() + { + if (_settings.StartWoxOnSystemStartup) + { + if (!SettingWindow.StartupSet()) + { + SettingWindow.SetStartup(); + } + } + } + + //[Conditional("RELEASE")] + private void AutoUpdates() + { + Task.Run(async () => + { + if (_settings.AutoUpdates) + { + // check udpate every 5 hours + var timer = new Timer(1000 * 60 * 60 * 5); + timer.Elapsed += async (s, e) => + { + await _updater.UpdateApp(); + }; + timer.Start(); + + // check updates on startup + await _updater.UpdateApp(); + } + }); + } + + private void RegisterExitEvents() + { + AppDomain.CurrentDomain.ProcessExit += (s, e) => Dispose(); + Current.Exit += (s, e) => Dispose(); + Current.SessionEnding += (s, e) => Dispose(); + } + + /// + /// let exception throw as normal is better for Debug + /// + [Conditional("RELEASE")] + private void RegisterDispatcherUnhandledException() + { + DispatcherUnhandledException += ErrorReporting.DispatcherUnhandledException; + } + + + /// + /// let exception throw as normal is better for Debug + /// + [Conditional("RELEASE")] + private static void RegisterAppDomainExceptions() + { + AppDomain.CurrentDomain.UnhandledException += ErrorReporting.UnhandledExceptionHandle; + } + + public void Dispose() + { + // if sessionending is called, exit proverbially be called when log off / shutdown + // but if sessionending is not called, exit won't be called when log off / shutdown + if (!_disposed) + { + API.SaveAppAllSettings(); + _disposed = true; + } + } + + public void OnSecondAppStarted() + { + Current.MainWindow.Visibility = Visibility.Visible; + } + } +} \ No newline at end of file diff --git a/src/modules/launcher/Wox/Converters/HighlightTextConverter.cs b/src/modules/launcher/Wox/Converters/HighlightTextConverter.cs new file mode 100644 index 000000000..b7d6d0683 --- /dev/null +++ b/src/modules/launcher/Wox/Converters/HighlightTextConverter.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Data; +using System.Windows.Documents; + +namespace Wox.Converters +{ + public class HighlightTextConverter : IMultiValueConverter + { + public object Convert(object[] value, Type targetType, object parameter, CultureInfo cultureInfo) + { + var text = value[0] as string; + var highlightData = value[1] as List; + + var textBlock = new Span(); + + if (highlightData == null || !highlightData.Any()) + { + // No highlight data, just return the text + return new Run(text); + } + + for (var i = 0; i < text.Length; i++) + { + var currentCharacter = text.Substring(i, 1); + if (this.ShouldHighlight(highlightData, i)) + { + textBlock.Inlines.Add(new Bold(new Run(currentCharacter))); + } + else + { + textBlock.Inlines.Add(new Run(currentCharacter)); + } + } + return textBlock; + } + + public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture) + { + return new[] { DependencyProperty.UnsetValue, DependencyProperty.UnsetValue }; + } + + private bool ShouldHighlight(List highlightData, int index) + { + return highlightData.Contains(index); + } + } +} diff --git a/src/modules/launcher/Wox/CustomQueryHotkeySetting.xaml b/src/modules/launcher/Wox/CustomQueryHotkeySetting.xaml new file mode 100644 index 000000000..a4e3d77f6 --- /dev/null +++ b/src/modules/launcher/Wox/CustomQueryHotkeySetting.xaml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/CustomQueryHotkeySetting.xaml.cs b/src/modules/launcher/Wox/CustomQueryHotkeySetting.xaml.cs new file mode 100644 index 000000000..f5ce9cabf --- /dev/null +++ b/src/modules/launcher/Wox/CustomQueryHotkeySetting.xaml.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Windows; +using NHotkey; +using NHotkey.Wpf; +using Wox.Core.Resource; +using Wox.Infrastructure.Hotkey; +using Wox.Infrastructure.UserSettings; + +namespace Wox +{ + public partial class CustomQueryHotkeySetting : Window + { + private SettingWindow _settingWidow; + private bool update; + private CustomPluginHotkey updateCustomHotkey; + private Settings _settings; + + public CustomQueryHotkeySetting(SettingWindow settingWidow, Settings settings) + { + _settingWidow = settingWidow; + InitializeComponent(); + _settings = settings; + } + + private void BtnCancel_OnClick(object sender, RoutedEventArgs e) + { + Close(); + } + + private void btnAdd_OnClick(object sender, RoutedEventArgs e) + { + if (!update) + { + if (!ctlHotkey.CurrentHotkeyAvailable) + { + MessageBox.Show(InternationalizationManager.Instance.GetTranslation("hotkeyIsNotUnavailable")); + return; + } + + if (_settings.CustomPluginHotkeys == null) + { + _settings.CustomPluginHotkeys = new ObservableCollection(); + } + + var pluginHotkey = new CustomPluginHotkey + { + Hotkey = ctlHotkey.CurrentHotkey.ToString(), + ActionKeyword = tbAction.Text + }; + _settings.CustomPluginHotkeys.Add(pluginHotkey); + + SetHotkey(ctlHotkey.CurrentHotkey, delegate + { + App.API.ChangeQuery(pluginHotkey.ActionKeyword); + Application.Current.MainWindow.Visibility = Visibility.Visible; + }); + MessageBox.Show(InternationalizationManager.Instance.GetTranslation("success")); + } + else + { + if (updateCustomHotkey.Hotkey != ctlHotkey.CurrentHotkey.ToString() && !ctlHotkey.CurrentHotkeyAvailable) + { + MessageBox.Show(InternationalizationManager.Instance.GetTranslation("hotkeyIsNotUnavailable")); + return; + } + var oldHotkey = updateCustomHotkey.Hotkey; + updateCustomHotkey.ActionKeyword = tbAction.Text; + updateCustomHotkey.Hotkey = ctlHotkey.CurrentHotkey.ToString(); + //remove origin hotkey + RemoveHotkey(oldHotkey); + SetHotkey(new HotkeyModel(updateCustomHotkey.Hotkey), delegate + { + App.API.ChangeQuery(updateCustomHotkey.ActionKeyword); + Application.Current.MainWindow.Visibility = Visibility.Visible; + }); + MessageBox.Show(InternationalizationManager.Instance.GetTranslation("success")); + } + + Close(); + } + + public void UpdateItem(CustomPluginHotkey item) + { + updateCustomHotkey = _settings.CustomPluginHotkeys.FirstOrDefault(o => o.ActionKeyword == item.ActionKeyword && o.Hotkey == item.Hotkey); + if (updateCustomHotkey == null) + { + MessageBox.Show(InternationalizationManager.Instance.GetTranslation("invalidPluginHotkey")); + Close(); + return; + } + + tbAction.Text = updateCustomHotkey.ActionKeyword; + ctlHotkey.SetHotkey(updateCustomHotkey.Hotkey, false); + update = true; + lblAdd.Text = InternationalizationManager.Instance.GetTranslation("update"); + } + + private void BtnTestActionKeyword_OnClick(object sender, RoutedEventArgs e) + { + App.API.ChangeQuery(tbAction.Text); + Application.Current.MainWindow.Visibility = Visibility.Visible; + } + + private void RemoveHotkey(string hotkeyStr) + { + if (!string.IsNullOrEmpty(hotkeyStr)) + { + HotkeyManager.Current.Remove(hotkeyStr); + } + } + + private void SetHotkey(HotkeyModel hotkey, EventHandler action) + { + string hotkeyStr = hotkey.ToString(); + try + { + HotkeyManager.Current.AddOrReplace(hotkeyStr, hotkey.CharKey, hotkey.ModifierKeys, action); + } + catch (Exception) + { + string errorMsg = string.Format(InternationalizationManager.Instance.GetTranslation("registerHotkeyFailed"), hotkeyStr); + MessageBox.Show(errorMsg); + } + } + } +} diff --git a/src/modules/launcher/Wox/FodyWeavers.xml b/src/modules/launcher/Wox/FodyWeavers.xml new file mode 100644 index 000000000..bb0f322ee --- /dev/null +++ b/src/modules/launcher/Wox/FodyWeavers.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Helper/DWMDropShadow.cs b/src/modules/launcher/Wox/Helper/DWMDropShadow.cs new file mode 100644 index 000000000..a998f75a1 --- /dev/null +++ b/src/modules/launcher/Wox/Helper/DWMDropShadow.cs @@ -0,0 +1,73 @@ +using System; +using System.Drawing.Printing; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Interop; + +namespace Wox.Helper +{ + public class DwmDropShadow + { + + [DllImport("dwmapi.dll", PreserveSig = true)] + private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize); + + [DllImport("dwmapi.dll")] + private static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref Margins pMarInset); + + /// + /// Drops a standard shadow to a WPF Window, even if the window isborderless. Only works with DWM (Vista and Seven). + /// This method is much more efficient than setting AllowsTransparency to true and using the DropShadow effect, + /// as AllowsTransparency involves a huge permormance issue (hardware acceleration is turned off for all the window). + /// + /// Window to which the shadow will be applied + public static void DropShadowToWindow(Window window) + { + if (!DropShadow(window)) + { + window.SourceInitialized += window_SourceInitialized; + } + } + + private static void window_SourceInitialized(object sender, EventArgs e) //fixed typo + { + Window window = (Window)sender; + + DropShadow(window); + + window.SourceInitialized -= window_SourceInitialized; + } + + /// + /// The actual method that makes API calls to drop the shadow to the window + /// + /// Window to which the shadow will be applied + /// True if the method succeeded, false if not + private static bool DropShadow(Window window) + { + try + { + WindowInteropHelper helper = new WindowInteropHelper(window); + int val = 2; + int ret1 = DwmSetWindowAttribute(helper.Handle, 2, ref val, 4); + + if (ret1 == 0) + { + Margins m = new Margins { Bottom = 0, Left = 0, Right = 0, Top = 0 }; + int ret2 = DwmExtendFrameIntoClientArea(helper.Handle, ref m); + return ret2 == 0; + } + else + { + return false; + } + } + catch (Exception) + { + // Probably dwmapi.dll not found (incompatible OS) + return false; + } + } + + } +} \ No newline at end of file diff --git a/src/modules/launcher/Wox/Helper/DataWebRequestFactory.cs b/src/modules/launcher/Wox/Helper/DataWebRequestFactory.cs new file mode 100644 index 000000000..61922d29d --- /dev/null +++ b/src/modules/launcher/Wox/Helper/DataWebRequestFactory.cs @@ -0,0 +1,69 @@ +using System; +using System.IO; +using System.Net; + +namespace Wox.Helper +{ + public class DataWebRequestFactory : IWebRequestCreate + { + class DataWebRequest : WebRequest + { + private readonly Uri m_uri; + + public DataWebRequest(Uri uri) + { + m_uri = uri; + } + + public override WebResponse GetResponse() + { + return new DataWebResponse(m_uri); + } + } + + class DataWebResponse : WebResponse + { + private readonly string m_contentType; + private readonly byte[] m_data; + + public DataWebResponse(Uri uri) + { + string uriString = uri.AbsoluteUri; + + int commaIndex = uriString.IndexOf(','); + var headers = uriString.Substring(0, commaIndex).Split(';'); + m_contentType = headers[0]; + string dataString = uriString.Substring(commaIndex + 1); + m_data = Convert.FromBase64String(dataString); + } + + public override string ContentType + { + get { return m_contentType; } + set + { + throw new NotSupportedException(); + } + } + + public override long ContentLength + { + get { return m_data.Length; } + set + { + throw new NotSupportedException(); + } + } + + public override Stream GetResponseStream() + { + return new MemoryStream(m_data); + } + } + + public WebRequest Create(Uri uri) + { + return new DataWebRequest(uri); + } + } +} diff --git a/src/modules/launcher/Wox/Helper/ErrorReporting.cs b/src/modules/launcher/Wox/Helper/ErrorReporting.cs new file mode 100644 index 000000000..e6bec5a45 --- /dev/null +++ b/src/modules/launcher/Wox/Helper/ErrorReporting.cs @@ -0,0 +1,49 @@ +using System; +using System.Windows.Threading; +using NLog; +using Wox.Infrastructure; +using Wox.Infrastructure.Exception; + +namespace Wox.Helper +{ + public static class ErrorReporting + { + private static void Report(Exception e) + { + var logger = LogManager.GetLogger("UnHandledException"); + logger.Fatal(ExceptionFormatter.FormatExcpetion(e)); + var reportWindow = new ReportWindow(e); + reportWindow.Show(); + } + + public static void UnhandledExceptionHandle(object sender, UnhandledExceptionEventArgs e) + { + //handle non-ui thread exceptions + Report((Exception)e.ExceptionObject); + } + + public static void DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) + { + //handle ui thread exceptions + Report(e.Exception); + //prevent application exist, so the user can copy prompted error info + e.Handled = true; + } + + public static string RuntimeInfo() + { + var info = $"\nWox version: {Constant.Version}" + + $"\nOS Version: {Environment.OSVersion.VersionString}" + + $"\nIntPtr Length: {IntPtr.Size}" + + $"\nx64: {Environment.Is64BitOperatingSystem}"; + return info; + } + + public static string DependenciesInfo() + { + var info = $"\nPython Path: {Constant.PythonPath}" + + $"\nEverything SDK Path: {Constant.EverythingSDKPath}"; + return info; + } + } +} diff --git a/src/modules/launcher/Wox/Helper/SingleInstance.cs b/src/modules/launcher/Wox/Helper/SingleInstance.cs new file mode 100644 index 000000000..2ea597a9a --- /dev/null +++ b/src/modules/launcher/Wox/Helper/SingleInstance.cs @@ -0,0 +1,455 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Channels; +using System.Runtime.Remoting.Channels.Ipc; +using System.Runtime.Serialization.Formatters; +using System.Security; +using System.Text; +using System.Threading; +using System.Windows; +using System.Windows.Threading; + +// http://blogs.microsoft.co.il/arik/2010/05/28/wpf-single-instance-application/ +// modified to allow single instace restart +namespace Wox.Helper +{ + internal enum WM + { + NULL = 0x0000, + CREATE = 0x0001, + DESTROY = 0x0002, + MOVE = 0x0003, + SIZE = 0x0005, + ACTIVATE = 0x0006, + SETFOCUS = 0x0007, + KILLFOCUS = 0x0008, + ENABLE = 0x000A, + SETREDRAW = 0x000B, + SETTEXT = 0x000C, + GETTEXT = 0x000D, + GETTEXTLENGTH = 0x000E, + PAINT = 0x000F, + CLOSE = 0x0010, + QUERYENDSESSION = 0x0011, + QUIT = 0x0012, + QUERYOPEN = 0x0013, + ERASEBKGND = 0x0014, + SYSCOLORCHANGE = 0x0015, + SHOWWINDOW = 0x0018, + ACTIVATEAPP = 0x001C, + SETCURSOR = 0x0020, + MOUSEACTIVATE = 0x0021, + CHILDACTIVATE = 0x0022, + QUEUESYNC = 0x0023, + GETMINMAXINFO = 0x0024, + + WINDOWPOSCHANGING = 0x0046, + WINDOWPOSCHANGED = 0x0047, + + CONTEXTMENU = 0x007B, + STYLECHANGING = 0x007C, + STYLECHANGED = 0x007D, + DISPLAYCHANGE = 0x007E, + GETICON = 0x007F, + SETICON = 0x0080, + NCCREATE = 0x0081, + NCDESTROY = 0x0082, + NCCALCSIZE = 0x0083, + NCHITTEST = 0x0084, + NCPAINT = 0x0085, + NCACTIVATE = 0x0086, + GETDLGCODE = 0x0087, + SYNCPAINT = 0x0088, + NCMOUSEMOVE = 0x00A0, + NCLBUTTONDOWN = 0x00A1, + NCLBUTTONUP = 0x00A2, + NCLBUTTONDBLCLK = 0x00A3, + NCRBUTTONDOWN = 0x00A4, + NCRBUTTONUP = 0x00A5, + NCRBUTTONDBLCLK = 0x00A6, + NCMBUTTONDOWN = 0x00A7, + NCMBUTTONUP = 0x00A8, + NCMBUTTONDBLCLK = 0x00A9, + + SYSKEYDOWN = 0x0104, + SYSKEYUP = 0x0105, + SYSCHAR = 0x0106, + SYSDEADCHAR = 0x0107, + COMMAND = 0x0111, + SYSCOMMAND = 0x0112, + + MOUSEMOVE = 0x0200, + LBUTTONDOWN = 0x0201, + LBUTTONUP = 0x0202, + LBUTTONDBLCLK = 0x0203, + RBUTTONDOWN = 0x0204, + RBUTTONUP = 0x0205, + RBUTTONDBLCLK = 0x0206, + MBUTTONDOWN = 0x0207, + MBUTTONUP = 0x0208, + MBUTTONDBLCLK = 0x0209, + MOUSEWHEEL = 0x020A, + XBUTTONDOWN = 0x020B, + XBUTTONUP = 0x020C, + XBUTTONDBLCLK = 0x020D, + MOUSEHWHEEL = 0x020E, + + + CAPTURECHANGED = 0x0215, + + ENTERSIZEMOVE = 0x0231, + EXITSIZEMOVE = 0x0232, + + IME_SETCONTEXT = 0x0281, + IME_NOTIFY = 0x0282, + IME_CONTROL = 0x0283, + IME_COMPOSITIONFULL = 0x0284, + IME_SELECT = 0x0285, + IME_CHAR = 0x0286, + IME_REQUEST = 0x0288, + IME_KEYDOWN = 0x0290, + IME_KEYUP = 0x0291, + + NCMOUSELEAVE = 0x02A2, + + DWMCOMPOSITIONCHANGED = 0x031E, + DWMNCRENDERINGCHANGED = 0x031F, + DWMCOLORIZATIONCOLORCHANGED = 0x0320, + DWMWINDOWMAXIMIZEDCHANGE = 0x0321, + + #region Windows 7 + DWMSENDICONICTHUMBNAIL = 0x0323, + DWMSENDICONICLIVEPREVIEWBITMAP = 0x0326, + #endregion + + USER = 0x0400, + + // This is the hard-coded message value used by WinForms for Shell_NotifyIcon. + // It's relatively safe to reuse. + TRAYMOUSEMESSAGE = 0x800, //WM_USER + 1024 + APP = 0x8000 + } + + [SuppressUnmanagedCodeSecurity] + internal static class NativeMethods + { + /// + /// Delegate declaration that matches WndProc signatures. + /// + public delegate IntPtr MessageHandler(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled); + + [DllImport("shell32.dll", EntryPoint = "CommandLineToArgvW", CharSet = CharSet.Unicode)] + private static extern IntPtr _CommandLineToArgvW([MarshalAs(UnmanagedType.LPWStr)] string cmdLine, out int numArgs); + + + [DllImport("kernel32.dll", EntryPoint = "LocalFree", SetLastError = true)] + private static extern IntPtr _LocalFree(IntPtr hMem); + + + public static string[] CommandLineToArgvW(string cmdLine) + { + IntPtr argv = IntPtr.Zero; + try + { + int numArgs = 0; + + argv = _CommandLineToArgvW(cmdLine, out numArgs); + if (argv == IntPtr.Zero) + { + throw new Win32Exception(); + } + var result = new string[numArgs]; + + for (int i = 0; i < numArgs; i++) + { + IntPtr currArg = Marshal.ReadIntPtr(argv, i * Marshal.SizeOf(typeof(IntPtr))); + result[i] = Marshal.PtrToStringUni(currArg); + } + + return result; + } + finally + { + + IntPtr p = _LocalFree(argv); + // Otherwise LocalFree failed. + // Assert.AreEqual(IntPtr.Zero, p); + } + } + + } + + public interface ISingleInstanceApp + { + void OnSecondAppStarted(); + } + + /// + /// This class checks to make sure that only one instance of + /// this application is running at a time. + /// + /// + /// Note: this class should be used with some caution, because it does no + /// security checking. For example, if one instance of an app that uses this class + /// is running as Administrator, any other instance, even if it is not + /// running as Administrator, can activate it with command line arguments. + /// For most apps, this will not be much of an issue. + /// + public static class SingleInstance + where TApplication: Application , ISingleInstanceApp + + { + #region Private Fields + + /// + /// String delimiter used in channel names. + /// + private const string Delimiter = ":"; + + /// + /// Suffix to the channel name. + /// + private const string ChannelNameSuffix = "SingeInstanceIPCChannel"; + + /// + /// Remote service name. + /// + private const string RemoteServiceName = "SingleInstanceApplicationService"; + + /// + /// IPC protocol used (string). + /// + private const string IpcProtocol = "ipc://"; + + /// + /// Application mutex. + /// + internal static Mutex singleInstanceMutex; + + /// + /// IPC channel for communications. + /// + private static IpcServerChannel channel; + + #endregion + + #region Public Properties + + #endregion + + #region Public Methods + + /// + /// Checks if the instance of the application attempting to start is the first instance. + /// If not, activates the first instance. + /// + /// True if this is the first instance of the application. + public static bool InitializeAsFirstInstance( string uniqueName ) + { + // Build unique application Id and the IPC channel name. + string applicationIdentifier = uniqueName + Environment.UserName; + + string channelName = String.Concat(applicationIdentifier, Delimiter, ChannelNameSuffix); + + // Create mutex based on unique application Id to check if this is the first instance of the application. + bool firstInstance; + singleInstanceMutex = new Mutex(true, applicationIdentifier, out firstInstance); + if (firstInstance) + { + CreateRemoteService(channelName); + return true; + } + else + { + SignalFirstInstance(channelName); + return false; + } + } + + /// + /// Cleans up single-instance code, clearing shared resources, mutexes, etc. + /// + public static void Cleanup() + { + singleInstanceMutex?.ReleaseMutex(); + + if (channel != null) + { + ChannelServices.UnregisterChannel(channel); + channel = null; + } + } + + #endregion + + #region Private Methods + + /// + /// Gets command line args - for ClickOnce deployed applications, command line args may not be passed directly, they have to be retrieved. + /// + /// List of command line arg strings. + private static IList GetCommandLineArgs( string uniqueApplicationName ) + { + string[] args = null; + if (AppDomain.CurrentDomain.ActivationContext == null) + { + // The application was not clickonce deployed, get args from standard API's + args = Environment.GetCommandLineArgs(); + } + else + { + // The application was clickonce deployed + // Clickonce deployed apps cannot recieve traditional commandline arguments + // As a workaround commandline arguments can be written to a shared location before + // the app is launched and the app can obtain its commandline arguments from the + // shared location + string appFolderPath = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), uniqueApplicationName); + + string cmdLinePath = Path.Combine(appFolderPath, "cmdline.txt"); + if (File.Exists(cmdLinePath)) + { + try + { + using (TextReader reader = new StreamReader(cmdLinePath, Encoding.Unicode)) + { + args = NativeMethods.CommandLineToArgvW(reader.ReadToEnd()); + } + + File.Delete(cmdLinePath); + } + catch (IOException) + { + } + } + } + + if (args == null) + { + args = new string[] { }; + } + + return new List(args); + } + + /// + /// Creates a remote service for communication. + /// + /// Application's IPC channel name. + private static void CreateRemoteService(string channelName) + { + BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider(); + serverProvider.TypeFilterLevel = TypeFilterLevel.Full; + IDictionary props = new Dictionary(); + + props["name"] = channelName; + props["portName"] = channelName; + props["exclusiveAddressUse"] = "false"; + + // Create the IPC Server channel with the channel properties + channel = new IpcServerChannel(props, serverProvider); + + // Register the channel with the channel services + ChannelServices.RegisterChannel(channel, true); + + // Expose the remote service with the REMOTE_SERVICE_NAME + IPCRemoteService remoteService = new IPCRemoteService(); + RemotingServices.Marshal(remoteService, RemoteServiceName); + } + + /// + /// Creates a client channel and obtains a reference to the remoting service exposed by the server - + /// in this case, the remoting service exposed by the first instance. Calls a function of the remoting service + /// class to pass on command line arguments from the second instance to the first and cause it to activate itself. + /// + /// Application's IPC channel name. + /// + /// Command line arguments for the second instance, passed to the first instance to take appropriate action. + /// + private static void SignalFirstInstance(string channelName) + { + IpcClientChannel secondInstanceChannel = new IpcClientChannel(); + ChannelServices.RegisterChannel(secondInstanceChannel, true); + + string remotingServiceUrl = IpcProtocol + channelName + "/" + RemoteServiceName; + + // Obtain a reference to the remoting service exposed by the server i.e the first instance of the application + IPCRemoteService firstInstanceRemoteServiceReference = (IPCRemoteService)RemotingServices.Connect(typeof(IPCRemoteService), remotingServiceUrl); + + // Check that the remote service exists, in some cases the first instance may not yet have created one, in which case + // the second instance should just exit + if (firstInstanceRemoteServiceReference != null) + { + // Invoke a method of the remote service exposed by the first instance passing on the command line + // arguments and causing the first instance to activate itself + firstInstanceRemoteServiceReference.InvokeFirstInstance(); + } + } + + /// + /// Callback for activating first instance of the application. + /// + /// Callback argument. + /// Always null. + private static object ActivateFirstInstanceCallback(object o) + { + ActivateFirstInstance(); + return null; + } + + /// + /// Activates the first instance of the application with arguments from a second instance. + /// + /// List of arguments to supply the first instance of the application. + private static void ActivateFirstInstance() + { + // Set main window state and process command line args + if (Application.Current == null) + { + return; + } + + ((TApplication)Application.Current).OnSecondAppStarted(); + } + + #endregion + + #region Private Classes + + /// + /// Remoting service class which is exposed by the server i.e the first instance and called by the second instance + /// to pass on the command line arguments to the first instance and cause it to activate itself. + /// + private class IPCRemoteService : MarshalByRefObject + { + /// + /// Activates the first instance of the application. + /// + public void InvokeFirstInstance() + { + if (Application.Current != null) + { + // Do an asynchronous call to ActivateFirstInstance function + Application.Current.Dispatcher.Invoke(ActivateFirstInstance); + } + } + + /// + /// Remoting Object's ease expires after every 5 minutes by default. We need to override the InitializeLifetimeService class + /// to ensure that lease never expires. + /// + /// Always null. + public override object InitializeLifetimeService() + { + return null; + } + } + + #endregion + } +} diff --git a/src/modules/launcher/Wox/Helper/SingletonWindowOpener.cs b/src/modules/launcher/Wox/Helper/SingletonWindowOpener.cs new file mode 100644 index 000000000..440d223e7 --- /dev/null +++ b/src/modules/launcher/Wox/Helper/SingletonWindowOpener.cs @@ -0,0 +1,20 @@ +using System; +using System.Linq; +using System.Windows; + +namespace Wox.Helper +{ + public static class SingletonWindowOpener + { + public static T Open(params object[] args) where T : Window + { + var window = Application.Current.Windows.OfType().FirstOrDefault(x => x.GetType() == typeof(T)) + ?? (T)Activator.CreateInstance(typeof(T), args); + Application.Current.MainWindow.Hide(); + window.Show(); + window.Focus(); + + return (T)window; + } + } +} \ No newline at end of file diff --git a/src/modules/launcher/Wox/Helper/SyntaxSugars.cs b/src/modules/launcher/Wox/Helper/SyntaxSugars.cs new file mode 100644 index 000000000..fc1bf5089 --- /dev/null +++ b/src/modules/launcher/Wox/Helper/SyntaxSugars.cs @@ -0,0 +1,24 @@ +using System; + +namespace Wox.Helper +{ + public static class SyntaxSugars + { + public static TResult CallOrRescueDefault(Func callback) + { + return CallOrRescueDefault(callback, default(TResult)); + } + + public static TResult CallOrRescueDefault(Func callback, TResult def) + { + try + { + return callback(); + } + catch + { + return def; + } + } + } +} diff --git a/src/modules/launcher/Wox/Helper/WallpaperPathRetrieval.cs b/src/modules/launcher/Wox/Helper/WallpaperPathRetrieval.cs new file mode 100644 index 000000000..95d7a212f --- /dev/null +++ b/src/modules/launcher/Wox/Helper/WallpaperPathRetrieval.cs @@ -0,0 +1,48 @@ +using System; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows.Media; +using Microsoft.Win32; + +namespace Wox.Helper +{ + public static class WallpaperPathRetrieval + { + [DllImport("user32.dll", CharSet = CharSet.Unicode)] + private static extern Int32 SystemParametersInfo(UInt32 action, + Int32 uParam, StringBuilder vParam, UInt32 winIni); + private static readonly UInt32 SPI_GETDESKWALLPAPER = 0x73; + private static int MAX_PATH = 260; + + public static string GetWallpaperPath() + { + var wallpaper = new StringBuilder(MAX_PATH); + SystemParametersInfo(SPI_GETDESKWALLPAPER, MAX_PATH, wallpaper, 0); + + var str = wallpaper.ToString(); + if (string.IsNullOrEmpty(str)) + return null; + + return str; + } + + public static Color GetWallpaperColor() + { + RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Colors", true); + var result = key.GetValue(@"Background", null); + if (result != null && result is string) + { + try + { + var parts = result.ToString().Trim().Split(new[] {' '}, 3).Select(byte.Parse).ToList(); + return Color.FromRgb(parts[0], parts[1], parts[2]); + } + catch + { + } + } + return Colors.Transparent; + } + } +} diff --git a/src/modules/launcher/Wox/Helper/WindowsInteropHelper.cs b/src/modules/launcher/Wox/Helper/WindowsInteropHelper.cs new file mode 100644 index 000000000..462047886 --- /dev/null +++ b/src/modules/launcher/Wox/Helper/WindowsInteropHelper.cs @@ -0,0 +1,163 @@ +using System; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows; +using System.Windows.Forms; +using System.Windows.Interop; +using System.Windows.Media; +using Point = System.Windows.Point; + +namespace Wox.Helper +{ + public class WindowsInteropHelper + { + private const int GWL_STYLE = -16; //WPF's Message code for Title Bar's Style + private const int WS_SYSMENU = 0x80000; //WPF's Message code for System Menu + private static IntPtr _hwnd_shell; + private static IntPtr _hwnd_desktop; + + //Accessors for shell and desktop handlers + //Will set the variables once and then will return them + private static IntPtr HWND_SHELL + { + get + { + return _hwnd_shell != IntPtr.Zero ? _hwnd_shell : _hwnd_shell = GetShellWindow(); + } + } + private static IntPtr HWND_DESKTOP + { + get + { + return _hwnd_desktop != IntPtr.Zero ? _hwnd_desktop : _hwnd_desktop = GetDesktopWindow(); + } + } + + [DllImport("user32.dll", SetLastError = true)] + private static extern int GetWindowLong(IntPtr hWnd, int nIndex); + + [DllImport("user32.dll")] + private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); + + [DllImport("user32.dll")] + private static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll")] + private static extern IntPtr GetDesktopWindow(); + + [DllImport("user32.dll")] + private static extern IntPtr GetShellWindow(); + + [DllImport("user32.dll", SetLastError = true)] + private static extern int GetWindowRect(IntPtr hwnd, out RECT rc); + + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] + private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); + + [DllImport("user32.DLL")] + public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); + + + const string WINDOW_CLASS_CONSOLE = "ConsoleWindowClass"; + const string WINDOW_CLASS_WINTAB = "Flip3D"; + const string WINDOW_CLASS_PROGMAN = "Progman"; + const string WINDOW_CLASS_WORKERW = "WorkerW"; + + public static bool IsWindowFullscreen() + { + //get current active window + IntPtr hWnd = GetForegroundWindow(); + + if (hWnd != null && !hWnd.Equals(IntPtr.Zero)) + { + //if current active window is NOT desktop or shell + if (!(hWnd.Equals(HWND_DESKTOP) || hWnd.Equals(HWND_SHELL))) + { + StringBuilder sb = new StringBuilder(256); + GetClassName(hWnd, sb, sb.Capacity); + string windowClass = sb.ToString(); + + //for Win+Tab (Flip3D) + if (windowClass == WINDOW_CLASS_WINTAB) + { + return false; + } + + RECT appBounds; + GetWindowRect(hWnd, out appBounds); + + //for console (ConsoleWindowClass), we have to check for negative dimensions + if (windowClass == WINDOW_CLASS_CONSOLE) + { + return appBounds.Top < 0 && appBounds.Bottom < 0; + } + + //for desktop (Progman or WorkerW, depends on the system), we have to check + if (windowClass == WINDOW_CLASS_PROGMAN || windowClass == WINDOW_CLASS_WORKERW) + { + IntPtr hWndDesktop = FindWindowEx(hWnd, IntPtr.Zero, "SHELLDLL_DefView", null); + hWndDesktop = FindWindowEx(hWndDesktop, IntPtr.Zero, "SysListView32", "FolderView"); + if (hWndDesktop != null && !hWndDesktop.Equals(IntPtr.Zero)) + { + return false; + } + } + + Rectangle screenBounds = Screen.FromHandle(hWnd).Bounds; + if ((appBounds.Bottom - appBounds.Top) == screenBounds.Height && (appBounds.Right - appBounds.Left) == screenBounds.Width) + { + return true; + } + } + } + + return false; + } + + /// + /// disable windows toolbar's control box + /// this will also disable system menu with Alt+Space hotkey + /// + public static void DisableControlBox(Window win) + { + var hwnd = new WindowInteropHelper(win).Handle; + SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU); + } + + /// + /// Transforms pixels to Device Independent Pixels used by WPF + /// + /// current window, required to get presentation source + /// horizontal position in pixels + /// vertical position in pixels + /// point containing device independent pixels + public static Point TransformPixelsToDIP(Visual visual, double unitX, double unitY) + { + Matrix matrix; + var source = PresentationSource.FromVisual(visual); + if (source != null) + { + matrix = source.CompositionTarget.TransformFromDevice; + } + else + { + using (var src = new HwndSource(new HwndSourceParameters())) + { + matrix = src.CompositionTarget.TransformFromDevice; + } + } + return new Point((int)(matrix.M11 * unitX), (int)(matrix.M22 * unitY)); + } + + + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int Left; + public int Top; + public int Right; + public int Bottom; + } + } +} \ No newline at end of file diff --git a/src/modules/launcher/Wox/HotkeyControl.xaml b/src/modules/launcher/Wox/HotkeyControl.xaml new file mode 100644 index 000000000..affe18556 --- /dev/null +++ b/src/modules/launcher/Wox/HotkeyControl.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/HotkeyControl.xaml.cs b/src/modules/launcher/Wox/HotkeyControl.xaml.cs new file mode 100644 index 000000000..f2ba82a06 --- /dev/null +++ b/src/modules/launcher/Wox/HotkeyControl.xaml.cs @@ -0,0 +1,117 @@ +using System; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using NHotkey.Wpf; +using Wox.Core.Resource; +using Wox.Infrastructure.Hotkey; +using Wox.Plugin; + +namespace Wox +{ + public partial class HotkeyControl : UserControl + { + public HotkeyModel CurrentHotkey { get; private set; } + public bool CurrentHotkeyAvailable { get; private set; } + + public event EventHandler HotkeyChanged; + + protected virtual void OnHotkeyChanged() + { + EventHandler handler = HotkeyChanged; + if (handler != null) handler(this, EventArgs.Empty); + } + + public HotkeyControl() + { + InitializeComponent(); + } + + void TbHotkey_OnPreviewKeyDown(object sender, KeyEventArgs e) + { + e.Handled = true; + tbMsg.Visibility = Visibility.Hidden; + + //when alt is pressed, the real key should be e.SystemKey + Key key = (e.Key == Key.System ? e.SystemKey : e.Key); + + SpecialKeyState specialKeyState = GlobalHotkey.Instance.CheckModifiers(); + + var hotkeyModel = new HotkeyModel( + specialKeyState.AltPressed, + specialKeyState.ShiftPressed, + specialKeyState.WinPressed, + specialKeyState.CtrlPressed, + key); + + var hotkeyString = hotkeyModel.ToString(); + + if (hotkeyString == tbHotkey.Text) + { + return; + } + + Dispatcher.InvokeAsync(async () => + { + await Task.Delay(500); + SetHotkey(hotkeyModel); + }); + } + + public void SetHotkey(HotkeyModel keyModel, bool triggerValidate = true) + { + CurrentHotkey = keyModel; + + tbHotkey.Text = CurrentHotkey.ToString(); + tbHotkey.Select(tbHotkey.Text.Length, 0); + + if (triggerValidate) + { + CurrentHotkeyAvailable = CheckHotkeyAvailability(); + if (!CurrentHotkeyAvailable) + { + tbMsg.Foreground = new SolidColorBrush(Colors.Red); + tbMsg.Text = InternationalizationManager.Instance.GetTranslation("hotkeyUnavailable"); + } + else + { + tbMsg.Foreground = new SolidColorBrush(Colors.Green); + tbMsg.Text = InternationalizationManager.Instance.GetTranslation("success"); + } + tbMsg.Visibility = Visibility.Visible; + OnHotkeyChanged(); + } + } + + public void SetHotkey(string keyStr, bool triggerValidate = true) + { + SetHotkey(new HotkeyModel(keyStr), triggerValidate); + } + + private bool CheckHotkeyAvailability() + { + try + { + HotkeyManager.Current.AddOrReplace("HotkeyAvailabilityTest", CurrentHotkey.CharKey, CurrentHotkey.ModifierKeys, (sender, e) => { }); + + return true; + } + catch + { + } + finally + { + HotkeyManager.Current.Remove("HotkeyAvailabilityTest"); + } + + return false; + } + + public new bool IsFocused + { + get { return tbHotkey.IsFocused; } + } + } +} diff --git a/src/modules/launcher/Wox/Images/Browser.png b/src/modules/launcher/Wox/Images/Browser.png new file mode 100644 index 000000000..619d1ad6a Binary files /dev/null and b/src/modules/launcher/Wox/Images/Browser.png differ diff --git a/src/modules/launcher/Wox/Images/EXE.png b/src/modules/launcher/Wox/Images/EXE.png new file mode 100644 index 000000000..e4c789689 Binary files /dev/null and b/src/modules/launcher/Wox/Images/EXE.png differ diff --git a/src/modules/launcher/Wox/Images/Link.png b/src/modules/launcher/Wox/Images/Link.png new file mode 100644 index 000000000..c0c3607bd Binary files /dev/null and b/src/modules/launcher/Wox/Images/Link.png differ diff --git a/src/modules/launcher/Wox/Images/New Message.png b/src/modules/launcher/Wox/Images/New Message.png new file mode 100644 index 000000000..2dd2c45f2 Binary files /dev/null and b/src/modules/launcher/Wox/Images/New Message.png differ diff --git a/src/modules/launcher/Wox/Images/app.png b/src/modules/launcher/Wox/Images/app.png new file mode 100644 index 000000000..8c9ca7971 Binary files /dev/null and b/src/modules/launcher/Wox/Images/app.png differ diff --git a/src/modules/launcher/Wox/Images/app_error.png b/src/modules/launcher/Wox/Images/app_error.png new file mode 100644 index 000000000..5106d6e8a Binary files /dev/null and b/src/modules/launcher/Wox/Images/app_error.png differ diff --git a/src/modules/launcher/Wox/Images/calculator.png b/src/modules/launcher/Wox/Images/calculator.png new file mode 100644 index 000000000..102a86bde Binary files /dev/null and b/src/modules/launcher/Wox/Images/calculator.png differ diff --git a/src/modules/launcher/Wox/Images/cancel.png b/src/modules/launcher/Wox/Images/cancel.png new file mode 100644 index 000000000..022fbc197 Binary files /dev/null and b/src/modules/launcher/Wox/Images/cancel.png differ diff --git a/src/modules/launcher/Wox/Images/close.png b/src/modules/launcher/Wox/Images/close.png new file mode 100644 index 000000000..17c4363ad Binary files /dev/null and b/src/modules/launcher/Wox/Images/close.png differ diff --git a/src/modules/launcher/Wox/Images/cmd.png b/src/modules/launcher/Wox/Images/cmd.png new file mode 100644 index 000000000..686583653 Binary files /dev/null and b/src/modules/launcher/Wox/Images/cmd.png differ diff --git a/src/modules/launcher/Wox/Images/color.png b/src/modules/launcher/Wox/Images/color.png new file mode 100644 index 000000000..da28583b1 Binary files /dev/null and b/src/modules/launcher/Wox/Images/color.png differ diff --git a/src/modules/launcher/Wox/Images/copy.png b/src/modules/launcher/Wox/Images/copy.png new file mode 100644 index 000000000..8f1fca752 Binary files /dev/null and b/src/modules/launcher/Wox/Images/copy.png differ diff --git a/src/modules/launcher/Wox/Images/down.png b/src/modules/launcher/Wox/Images/down.png new file mode 100644 index 000000000..2349d8917 Binary files /dev/null and b/src/modules/launcher/Wox/Images/down.png differ diff --git a/src/modules/launcher/Wox/Images/file.png b/src/modules/launcher/Wox/Images/file.png new file mode 100644 index 000000000..36156767a Binary files /dev/null and b/src/modules/launcher/Wox/Images/file.png differ diff --git a/src/modules/launcher/Wox/Images/find.png b/src/modules/launcher/Wox/Images/find.png new file mode 100644 index 000000000..a3f0be1f5 Binary files /dev/null and b/src/modules/launcher/Wox/Images/find.png differ diff --git a/src/modules/launcher/Wox/Images/folder.png b/src/modules/launcher/Wox/Images/folder.png new file mode 100644 index 000000000..569fa7049 Binary files /dev/null and b/src/modules/launcher/Wox/Images/folder.png differ diff --git a/src/modules/launcher/Wox/Images/history.png b/src/modules/launcher/Wox/Images/history.png new file mode 100644 index 000000000..2a3b72dc4 Binary files /dev/null and b/src/modules/launcher/Wox/Images/history.png differ diff --git a/src/modules/launcher/Wox/Images/image.png b/src/modules/launcher/Wox/Images/image.png new file mode 100644 index 000000000..7fc14c38e Binary files /dev/null and b/src/modules/launcher/Wox/Images/image.png differ diff --git a/src/modules/launcher/Wox/Images/lock.png b/src/modules/launcher/Wox/Images/lock.png new file mode 100644 index 000000000..4aef7007b Binary files /dev/null and b/src/modules/launcher/Wox/Images/lock.png differ diff --git a/src/modules/launcher/Wox/Images/logoff.png b/src/modules/launcher/Wox/Images/logoff.png new file mode 100644 index 000000000..0d1378830 Binary files /dev/null and b/src/modules/launcher/Wox/Images/logoff.png differ diff --git a/src/modules/launcher/Wox/Images/ok.png b/src/modules/launcher/Wox/Images/ok.png new file mode 100644 index 000000000..f2dde98ef Binary files /dev/null and b/src/modules/launcher/Wox/Images/ok.png differ diff --git a/src/modules/launcher/Wox/Images/open.png b/src/modules/launcher/Wox/Images/open.png new file mode 100644 index 000000000..b5c7a0e19 Binary files /dev/null and b/src/modules/launcher/Wox/Images/open.png differ diff --git a/src/modules/launcher/Wox/Images/plugin.png b/src/modules/launcher/Wox/Images/plugin.png new file mode 100644 index 000000000..6ff9b8b15 Binary files /dev/null and b/src/modules/launcher/Wox/Images/plugin.png differ diff --git a/src/modules/launcher/Wox/Images/recyclebin.png b/src/modules/launcher/Wox/Images/recyclebin.png new file mode 100644 index 000000000..2cc3b0116 Binary files /dev/null and b/src/modules/launcher/Wox/Images/recyclebin.png differ diff --git a/src/modules/launcher/Wox/Images/restart.png b/src/modules/launcher/Wox/Images/restart.png new file mode 100644 index 000000000..aaa2ee711 Binary files /dev/null and b/src/modules/launcher/Wox/Images/restart.png differ diff --git a/src/modules/launcher/Wox/Images/search.png b/src/modules/launcher/Wox/Images/search.png new file mode 100644 index 000000000..a3f0be1f5 Binary files /dev/null and b/src/modules/launcher/Wox/Images/search.png differ diff --git a/src/modules/launcher/Wox/Images/settings.png b/src/modules/launcher/Wox/Images/settings.png new file mode 100644 index 000000000..c61729fe0 Binary files /dev/null and b/src/modules/launcher/Wox/Images/settings.png differ diff --git a/src/modules/launcher/Wox/Images/shutdown.png b/src/modules/launcher/Wox/Images/shutdown.png new file mode 100644 index 000000000..7da7a528d Binary files /dev/null and b/src/modules/launcher/Wox/Images/shutdown.png differ diff --git a/src/modules/launcher/Wox/Images/sleep.png b/src/modules/launcher/Wox/Images/sleep.png new file mode 100644 index 000000000..42426286d Binary files /dev/null and b/src/modules/launcher/Wox/Images/sleep.png differ diff --git a/src/modules/launcher/Wox/Images/up.png b/src/modules/launcher/Wox/Images/up.png new file mode 100644 index 000000000..e68def0b5 Binary files /dev/null and b/src/modules/launcher/Wox/Images/up.png differ diff --git a/src/modules/launcher/Wox/Images/update.png b/src/modules/launcher/Wox/Images/update.png new file mode 100644 index 000000000..6fe579091 Binary files /dev/null and b/src/modules/launcher/Wox/Images/update.png differ diff --git a/src/modules/launcher/Wox/Images/warning.png b/src/modules/launcher/Wox/Images/warning.png new file mode 100644 index 000000000..8d29625ee Binary files /dev/null and b/src/modules/launcher/Wox/Images/warning.png differ diff --git a/src/modules/launcher/Wox/Languages/da.xaml b/src/modules/launcher/Wox/Languages/da.xaml new file mode 100644 index 000000000..f6b05597e --- /dev/null +++ b/src/modules/launcher/Wox/Languages/da.xaml @@ -0,0 +1,132 @@ + + + Kunne ikke registrere genvejstast: {0} + Kunne ikke starte {0} + Ugyldigt Wox plugin filformat + Sæt øverst i denne søgning + Annuller øverst i denne søgning + Udfør søgning: {0} + Seneste afviklingstid: {0} + Åben + Indstillinger + Om + Afslut + + + Wox indstillinger + Generelt + Start Wox ved system start + Skjul Wox ved mistet fokus + Vis ikke notifikationer om nye versioner + Husk seneste position + Sprog + Maksimum antal resultater vist + Ignorer genvejstaster i fuldskærmsmode + Python bibliotek + Autoopdatering + Vælg + Skjul Wox ved opstart + + + Plugin + Find flere plugins + Deaktiver + Nøgleord + Plugin bibliotek + Forfatter + Initaliseringstid: {0}ms + Søgetid: {0}ms + + + Tema + Søg efter flere temaer + Hej Wox + Søgefelt skrifttype + Resultat skrifttype + Vindue mode + Gennemsigtighed + + + Genvejstast + Wox genvejstast + Tilpasset søgegenvejstast + Slet + Rediger + Tilføj + Vælg venligst + Er du sikker på du vil slette {0} plugin genvejstast? + + + HTTP Proxy + Aktiver HTTP Proxy + HTTP Server + Port + Brugernavn + Adgangskode + Test Proxy + Gem + Server felt må ikke være tomt + Port felt må ikke være tomt + Ugyldigt port format + Proxy konfiguration gemt + Proxy konfiguret korrekt + Proxy forbindelse fejlet + + + Om + Website + Version + Du har aktiveret Wox {0} gange + Tjek for opdateringer + Ny version {0} er tilgængelig, genstart venligst Wox + Release Notes: + + + Gammelt nøgleord + Nyt nøgleord + Annuller + Færdig + Kan ikke finde det valgte plugin + Nyt nøgleord må ikke være tomt + Nyt nøgleord er tilknyttet et andet plugin, tilknyt venligst et andet nyt nøgeleord + Fortsæt + Brug * hvis du ikke vil angive et nøgleord + + + Vis + Genvejstast er utilgængelig, vælg venligst en ny genvejstast + Ugyldig plugin genvejstast + Opdater + + + Genvejstast utilgængelig + + + Version + Tid + Beskriv venligst hvordan Wox crashede, så vi kan rette det. + Send rapport + Annuller + Generelt + Exceptions + Exception Type + Kilde + Stack Trace + Sender + Rapport sendt korrekt + Kunne ikke sende rapport + Wox fik en fejl + + + Ny Wox udgivelse {0} er nu tilgængelig + Der skete en fejl ifm. opdatering af Wox + Opdater + Annuler + Denne opdatering vil genstarte Wox + Følgende filer bliver opdateret + Opdatereringsfiler + Opdateringsbeskrivelse + + diff --git a/src/modules/launcher/Wox/Languages/de.xaml b/src/modules/launcher/Wox/Languages/de.xaml new file mode 100644 index 000000000..3efa653e6 --- /dev/null +++ b/src/modules/launcher/Wox/Languages/de.xaml @@ -0,0 +1,132 @@ + + + Tastenkombinationregistrierung: {0} fehlgeschlagen + Kann {0} nicht starten + Fehlerhaftes Wox-Plugin Dateiformat + In dieser Abfrage als oberstes setzen + In dieser Abfrage oberstes abbrechen + Abfrage ausführen:{0} + Letzte Ausführungszeit:{0} + Öffnen + Einstellungen + Über + Schließen + + + Wox Einstellungen + Allgemein + Starte Wox bei Systemstart + Verstecke Wox wenn der Fokus verloren geht + Zeige keine Nachricht wenn eine neue Version vorhanden ist + Merke letzte Ausführungsposition + Sprache + Maximale Anzahl Ergebnissen + Ignoriere Tastenkombination wenn Fenster im Vollbildmodus ist + Python-Verzeichnis + Automatische Aktualisierung + Auswählen + Verstecke Wox bei Systemstart + + + Plugin + Suche nach weiteren Plugins + Deaktivieren + Aktionsschlüsselwörter + Pluginordner + Autor + Initialisierungszeit: {0}ms + Abfragezeit: {0}ms + + + Theme + Suche nach weiteren Themes + Hallo Wox + Abfragebox Schriftart + Ergebnis Schriftart + Fenstermodus + Transparenz + + + Tastenkombination + Wox Tastenkombination + Benutzerdefinierte Abfrage Tastenkombination + Löschen + Bearbeiten + Hinzufügen + Bitte einen Eintrag auswählen + Wollen Sie die {0} Plugin Tastenkombination wirklich löschen? + + + HTTP Proxy + Aktiviere HTTP Proxy + HTTP Server + Port + Benutzername + Passwort + Teste Proxy + Speichern + Server darf nicht leer sein + Server Port darf nicht leer sein + Falsches Port Format + Proxy wurde erfolgreich gespeichert + Proxy ist korrekt + Verbindung zum Proxy fehlgeschlagen + + + Über + Webseite + Version + Sie haben Wox {0} mal aktiviert + Nach Aktuallisierungen Suchen + Eine neue Version ({0}) ist vorhanden. Bitte starten Sie Wox neu. + Versionshinweise: + + + Altes Aktionsschlüsselwort + Neues Aktionsschlüsselwort + Abbrechen + Fertig + Kann das angegebene Plugin nicht finden + Neues Aktionsschlüsselwort darf nicht leer sein + Aktionsschlüsselwort ist schon bei einem anderen Plugin in verwendung. Bitte stellen Sie ein anderes Aktionsschlüsselwort ein. + Erfolgreich + Benutzen Sie * wenn Sie ein Aktionsschlüsselwort definieren wollen. + + + Vorschau + Tastenkombination ist nicht verfügbar, bitte wähle eine andere Tastenkombination + Ungültige Plugin Tastenkombination + Aktualisieren + + + Tastenkombination nicht verfügbar + + + Version + Zeit + Bitte teilen Sie uns mit, wie die Anwendung abgestürzt ist, damit wir den Fehler beheben können. + Sende Report + Abbrechen + Allgemein + Fehler + Fehlertypen + Quelle + Stack Trace + Sende + Report erfolgreich + Report fehlgeschlagen + Wox hat einen Fehler + + + V{0} von Wox ist verfügbar + Es ist ein Fehler während der Installation der Aktualisierung aufgetreten. + Aktualisieren + Abbrechen + Diese Aktualisierung wird Wox neu starten + Folgende Dateien werden aktualisiert + Aktualisiere Dateien + Aktualisierungbeschreibung + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Languages/en.xaml b/src/modules/launcher/Wox/Languages/en.xaml new file mode 100644 index 000000000..dca044dc1 --- /dev/null +++ b/src/modules/launcher/Wox/Languages/en.xaml @@ -0,0 +1,146 @@ + + + Failed to register hotkey: {0} + Could not start {0} + Invalid Wox plugin file format + Set as topmost in this query + Cancel topmost in this query + Execute query: {0} + Last execution time: {0} + Open + Settings + About + Exit + + + Wox Settings + General + Start Wox on system startup + Hide Wox when focus is lost + Do not show new version notifications + Remember last launch location + Language + Last Query Style + Preserve Last Query + Select last Query + Empty last Query + Maximum results shown + Ignore hotkeys in fullscreen mode + Python Directory + Auto Update + Select + Hide Wox on startup + Hide tray icon + Query Search Precision + Should Use Pinyin + + + Plugin + Find more plugins + Disable + Action keywords + Plugin Directory + Author + Init time: {0}ms + Query time: {0}ms + + + Theme + Browse for more themes + Hello Wox + Query Box Font + Result Item Font + Window Mode + Opacity + Theme {0} not exists, fallback to default theme + Fail to load theme {0}, fallback to default theme + + + Hotkey + Wox Hotkey + Custom Query Hotkey + Delete + Edit + Add + Please select an item + Are you sure you want to delete {0} plugin hotkey? + + + HTTP Proxy + Enable HTTP Proxy + HTTP Server + Port + User Name + Password + Test Proxy + Save + Server field can't be empty + Port field can't be empty + Invalid port format + Proxy configuration saved successfully + Proxy configured correctly + Proxy connection failed + + + About + Website + Version + You have activated Wox {0} times + Check for Updates + New version {0} is available, please restart Wox. + Check updates failed, please check your connection and proxy settings to api.github.com. + + Download updates failed, please check your connection and proxy settings to github-cloud.s3.amazonaws.com, + or go to https://github.com/Wox-launcher/Wox/releases to download updates manually. + + Release Notes: + + + Old Action Keyword + New Action Keyword + Cancel + Done + Can't find specified plugin + New Action Keyword can't be empty + New Action Keywords have been assigned to another plugin, please assign other new action keyword + Success + Use * if you don't want to specify an action keyword + + + Preview + Hotkey is unavailable, please select a new hotkey + Invalid plugin hotkey + Update + + + Hotkey unavailable + + + Version + Time + Please tell us how application crashed so we can fix it + Send Report + Cancel + General + Exceptions + Exception Type + Source + Stack Trace + Sending + Report sent successfully + Failed to send report + Wox got an error + + + New Wox release {0} is now available + An error occurred while trying to install software updates + Update + Cancel + This upgrade will restart Wox + Following files will be updated + Update files + Update description + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Languages/fr.xaml b/src/modules/launcher/Wox/Languages/fr.xaml new file mode 100644 index 000000000..2f8ebc8fc --- /dev/null +++ b/src/modules/launcher/Wox/Languages/fr.xaml @@ -0,0 +1,138 @@ + + + Échec lors de l'enregistrement du raccourci : {0} + Impossible de lancer {0} + Le format de fichier n'est pas un plugin Wox valide + Définir en tant que favori pour cette requête + Annuler le favori + Lancer la requête : {0} + Dernière exécution : {0} + Ouvrir + Paramètres + À propos + Quitter + + + Paramètres - Wox + Général + Lancer Wox au démarrage du système + Cacher Wox lors de la perte de focus + Ne pas afficher le message de mise à jour pour les nouvelles versions + Se souvenir du dernier emplacement de la fenêtre + Langue + Affichage de la dernière recherche + Conserver la dernière recherche + Sélectionner la dernière recherche + Ne pas afficher la dernière recherche + Résultats maximums à afficher + Ignore les raccourcis lorsqu'une application est en plein écran + Répertoire de Python + Mettre à jour automatiquement + Sélectionner + Cacher Wox au démarrage + + + Modules + Trouver plus de modules + Désactivé + Mot-clé d'action : + Répertoire + Auteur + Chargement : {0}ms + Utilisation : {0}ms + + + Thèmes + Trouver plus de thèmes + Hello Wox + Police (barre de recherche) + Police (liste des résultats) + Mode fenêtré + Opacité + + + Raccourcis + Ouvrir Wox + Requêtes personnalisées + Supprimer + Modifier + Ajouter + Veuillez sélectionner un élément + Voulez-vous vraiment supprimer {0} raccourci(s) ? + + + Proxy HTTP + Activer le HTTP proxy + Serveur HTTP + Port + Utilisateur + Mot de passe + Tester + Sauvegarder + Un serveur doit être indiqué + Un port doit être indiqué + Format du port invalide + Proxy sauvegardé avec succès + Le proxy est valide + Connexion au proxy échouée + + + À propos + Site web + Version + Vous avez utilisé Wox {0} fois + Vérifier les mises à jour + Nouvelle version {0} disponible, veuillez redémarrer Wox + Échec de la vérification de la mise à jour, vérifiez votre connexion et vos paramètres de configuration proxy pour pouvoir acceder à api.github.com. + Échec du téléchargement de la mise à jour, vérifiez votre connexion et vos paramètres de configuration proxy pour pouvoir acceder à github-cloud.s3.amazonaws.com, ou téléchargez manuelement la mise à jour sur https://github.com/Wox-launcher/Wox/releases. + Notes de changement : + + + Ancien mot-clé d'action + Nouveau mot-clé d'action + Annuler + Terminé + Impossible de trouver le module spécifié + Le nouveau mot-clé d'action doit être spécifié + Le nouveau mot-clé d'action a été assigné à un autre module, veuillez en choisir un autre + Ajouté + Saisissez * si vous ne souhaitez pas utiliser de mot-clé spécifique + + + Prévisualiser + Raccourci indisponible. Veuillez en choisir un autre. + Raccourci invalide + Actualiser + + + Raccourci indisponible + + + Version + Heure + Veuillez nous indiquer comment l'application a planté afin que nous puissions le corriger + Envoyer le rapport + Annuler + Général + Exceptions + Type d'exception + Source + Trace d'appel + Envoi en cours + Signalement envoyé + Échec de l'envoi du signalement + Wox a rencontré une erreur + + + Version v{0} de Wox disponible + Une erreur s'est produite lors de l'installation de la mise à jour + Mettre à jour + Annuler + Wox doit redémarrer pour installer cette mise à jour + Les fichiers suivants seront mis à jour + Fichiers mis à jour + Description de la mise à jour + + diff --git a/src/modules/launcher/Wox/Languages/it.xaml b/src/modules/launcher/Wox/Languages/it.xaml new file mode 100644 index 000000000..7696e9dc9 --- /dev/null +++ b/src/modules/launcher/Wox/Languages/it.xaml @@ -0,0 +1,141 @@ + + + Impossibile salvare il tasto di scelta rapida: {0} + Avvio fallito {0} + Formato file plugin non valido + Risultato prioritario con questa query + Rimuovi risultato prioritario con questa query + Query d'esecuzione: {0} + Ultima esecuzione: {0} + Apri + Impostazioni + About + Esci + + + Impostaizoni Wox + Generale + Avvia Wow all'avvio di Windows + Nascondi Wox quando perde il focus + Non mostrare le notifiche per una nuova versione + Ricorda l'ultima posizione di avvio del launcher + Lingua + Comportamento ultima ricerca + Conserva ultima ricerca + Seleziona ultima ricerca + Cancella ultima ricerca + Numero massimo di risultati mostrati + Ignora i tasti di scelta rapida in applicazione a schermo pieno + Cartella Python + Aggiornamento automatico + Seleziona + Nascondi Wox all'avvio + + + Plugin + Cerca altri plugins + Disabilita + Parole chiave + Cartella Plugin + Autore + Tempo di avvio: {0}ms + Tempo ricerca: {0}ms + + + Tema + Sfoglia per altri temi + Hello Wox + Font campo di ricerca + Font campo risultati + Modalità finestra + Opacità + + + Tasti scelta rapida + Tasto scelta rapida Wox + Tasti scelta rapida per ricerche personalizzate + Cancella + Modifica + Aggiungi + Selezionare un oggetto + Volete cancellare il tasto di scelta rapida per il plugin {0}? + + + Proxy HTTP + Abilita Proxy HTTP + Server HTTP + Porta + User Name + Password + Proxy Test + Salva + Il campo Server non può essere vuoto + Il campo Porta non può essere vuoto + Formato Porta non valido + Configurazione Proxy salvata correttamente + Proxy Configurato correttamente + Connessione Proxy fallita + + + About + Sito web + Versione + Hai usato Wox {0} volte + Cerca aggiornamenti + Una nuova versione {0} è disponibile, riavvia Wox per favore. + Ricerca aggiornamenti fallita, per favore controlla la tua connessione e le eventuali impostazioni proxy per api.github.com. + + Download degli aggiornamenti fallito, per favore controlla la tua connessione ed eventuali impostazioni proxy per github-cloud.s3.amazonaws.com, + oppure vai su https://github.com/Wox-launcher/Wox/releases per scaricare gli aggiornamenti manualmente. + + Note di rilascio: + + + Vecchia parola chiave d'azione + Nuova parola chiave d'azione + Annulla + Conferma + Impossibile trovare il plugin specificato + La nuova parola chiave d'azione non può essere vuota + La nuova parola chiave d'azione è stata assegnata ad un altro plugin, per favore sceglierne una differente + Successo + Usa * se non vuoi specificare una parola chiave d'azione + + + Anteprima + Tasto di scelta rapida non disponibile, per favore scegli un nuovo tasto di scelta rapida + Tasto di scelta rapida plugin non valido + Aggiorna + + + Tasto di scelta rapida non disponibile + + + Versione + Tempo + Per favore raccontaci come l'applicazione si è chiusa inaspettatamente così che possimo risolvere il problema + Invia rapporto + Annulla + Generale + Eccezioni + Tipo di eccezione + Risorsa + Traccia dello stack + Invio in corso + Rapporto inviato correttamente + Invio rapporto fallito + Wox ha riportato un errore + + + E' disponibile la nuova release {0} di Wox + Errore durante l'installazione degli aggiornamenti software + Aggiorna + Annulla + Questo aggiornamento riavvierà Wox + I seguenti file saranno aggiornati + File aggiornati + Descrizione aggiornamento + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Languages/ja.xaml b/src/modules/launcher/Wox/Languages/ja.xaml new file mode 100644 index 000000000..d9a203a24 --- /dev/null +++ b/src/modules/launcher/Wox/Languages/ja.xaml @@ -0,0 +1,144 @@ + + + ホットキー「{0}」の登録に失敗しました + {0}の起動に失敗しました + Woxプラグインの形式が正しくありません + このクエリを最上位にセットする + このクエリを最上位にセットをキャンセル + 次のコマンドを実行します:{0} + 最終実行時間:{0} + 開く + 設定 + Woxについて + 終了 + + + Wox設定 + 一般 + スタートアップ時にWoxを起動する + フォーカスを失った時にWoxを隠す + 最新版が入手可能であっても、アップグレードメッセージを表示しない + 前回のランチャーの位置を記憶 + 言語 + 前回のクエリの扱い + 前回のクエリを保存 + 前回のクエリを選択 + 前回のクエリを消去 + 結果の最大表示件数 + ウィンドウがフルスクリーン時にホットキーを無効にする + Pythonのディレクトリ + 自動更新 + 選択 + 起動時にWoxを隠す + トレイアイコンを隠す + + + プラグイン + プラグインを探す + 無効 + キーワード + プラグイン・ディレクトリ + 作者 + 初期化時間: {0}ms + クエリ時間: {0}ms + + + テーマ + テーマを探す + こんにちは Wox + 検索ボックスのフォント + 検索結果一覧のフォント + ウィンドウモード + 透過度 + テーマ {0} が存在しません、デフォルトのテーマに戻します。 + テーマ {0} を読み込めません、デフォルトのテーマに戻します。 + + + ホットキー + Wox ホットキー + カスタムクエリ ホットキー + 削除 + 編集 + 追加 + 項目選択してください + {0} プラグインのホットキーを本当に削除しますか? + + + HTTP プロキシ + HTTP プロキシを有効化 + HTTP サーバ + ポート + ユーザ名 + パスワード + プロキシをテストする + 保存 + サーバーは空白にできません + ポートは空白にできません + ポートの形式が正しくありません + プロキシの保存に成功しました + プロキシは正しいです + プロキシ接続に失敗しました + + + Woxについて + ウェブサイト + バージョン + あなたはWoxを {0} 回利用しました + アップデートを確認する + 新しいバージョン {0} が利用可能です。Woxを再起動してください。 + アップデートの確認に失敗しました、api.github.com への接続とプロキシ設定を確認してください。 + + 更新のダウンロードに失敗しました、github-cloud.s3.amazonaws.com への接続とプロキシ設定を確認するか、 + https://github.com/Wox-launcher/Wox/releases から手動でアップデートをダウンロードしてください。 + + リリースノート: + + + 古いアクションキーボード + 新しいアクションキーボード + キャンセル + 完了 + プラグインが見つかりません + 新しいアクションキーボードを空にすることはできません + 新しいアクションキーボードは他のプラグインに割り当てられています。他のアクションキーボードを指定してください + 成功しました + アクションキーボードを指定しない場合、* を使用してください + + + プレビュー + ホットキーは使用できません。新しいホットキーを選択してください + プラグインホットキーは無効です + 更新 + + + ホットキーは使用できません + + + バージョン + 時間 + アプリケーションが突然終了した手順を私たちに教えてくださると、バグ修正ができます + クラッシュレポートを送信 + キャンセル + 一般 + 例外 + 例外の種類 + ソース + スタックトレース + 送信中 + クラッシュレポートの送信に成功しました + クラッシュレポートの送信に失敗しました + Woxにエラーが発生しました + + + Wox の最新バージョン V{0} が入手可能です + Woxのアップデート中にエラーが発生しました + アップデート + キャンセル + このアップデートでは、Woxの再起動が必要です + 次のファイルがアップデートされます + 更新ファイル一覧 + アップデートの詳細 + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Languages/ko.xaml b/src/modules/launcher/Wox/Languages/ko.xaml new file mode 100644 index 000000000..7810beec7 --- /dev/null +++ b/src/modules/launcher/Wox/Languages/ko.xaml @@ -0,0 +1,136 @@ + + + 핫키 등록 실패: {0} + {0}을 실행할 수 없습니다. + Wox 플러그인 파일 형식이 유효하지 않습니다. + 이 쿼리의 최상위로 설정 + 이 쿼리의 최상위 설정 취소 + 쿼리 실행: {0} + 마지막 실행 시간: {0} + 열기 + 설정 + 정보 + 종료 + + + Wox 설정 + 일반 + 시스템 시작 시 Wox 실행 + 포커스 잃으면 Wox 숨김 + 새 버전 알림 끄기 + 마지막 실행 위치 기억 + 언어 + 마지막 쿼리 스타일 + 직전 쿼리에 계속 입력 + 직전 쿼리 내용 선택 + 직전 쿼리 지우기 + 표시할 결과 수 + 전체화면 모드에서는 핫키 무시 + Python 디렉토리 + 자동 업데이트 + 선택 + 시작 시 Wox 숨김 + + + 플러그인 + 플러그인 더 찾아보기 + 비활성화 + 액션 키워드 + 플러그인 디렉토리 + 저자 + 초기화 시간: {0}ms + 쿼리 시간: {0}ms + + + 테마 + 테마 더 찾아보기 + Hello Wox + 쿼리 상자 글꼴 + 결과 항목 글꼴 + 윈도우 모드 + 투명도 + + + 핫키 + Wox 핫키 + 사용자지정 쿼리 핫키 + 삭제 + 편집 + 추가 + 항목을 선택하세요. + {0} 플러그인 핫키를 삭제하시겠습니까? + + + HTTP 프록시 + HTTP 프록시 켜기 + HTTP 서버 + 포트 + 사용자명 + 패스워드 + 프록시 테스트 + 저장 + 서버를 입력하세요. + 포트를 입력하세요. + 유효하지 않은 포트 형식 + 프록시 설정이 저장되었습니다. + 프록시 설정 정상 + 프록시 연결 실패 + + + 정보 + 웹사이트 + 버전 + Wox를 {0}번 실행했습니다. + 업데이트 확인 + 새 버전({0})이 있습니다. Wox를 재시작하세요. + 릴리즈 노트: + + + 예전 액션 키워드 + 새 액션 키워드 + 취소 + 완료 + 플러그인을 찾을 수 없습니다. + 새 액션 키워드를 입력하세요. + 새 액션 키워드가 할당된 플러그인이 이미 있습니다. 다른 액션 키워드를 입력하세요. + 성공 + 액션 키워드를 지정하지 않으려면 *를 사용하세요. + + + 미리보기 + 핫키를 사용할 수 없습니다. 다른 핫키를 입력하세요. + 플러그인 핫키가 유효하지 않습니다. + 업데이트 + + + 핫키를 사용할 수 없습니다. + + + 버전 + 시간 + 수정을 위해 애플리케이션이 어떻게 충돌했는지 알려주세요. + 보고서 보내기 + 취소 + 일반 + 예외 + 예외 유형 + 소스 + 스택 추적 + 보내는 중 + 보고서를 정상적으로 보냈습니다. + 보고서를 보내지 못했습니다. + Wox에 문제가 발생했습니다. + + + 새 Wox 버전({0})을 사용할 수 있습니다. + 소프트웨어 업데이트를 설치하는 중에 오류가 발생했습니다. + 업데이트 + 취소 + 업데이트를 위해 Wox를 재시작합니다. + 아래 파일들이 업데이트됩니다. + 업데이트 파일 + 업데이트 설명 + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Languages/nb-NO.xaml b/src/modules/launcher/Wox/Languages/nb-NO.xaml new file mode 100644 index 000000000..c7f294d93 --- /dev/null +++ b/src/modules/launcher/Wox/Languages/nb-NO.xaml @@ -0,0 +1,141 @@ + + + Kunne ikke registrere hurtigtast: {0} + Kunne ikke starte {0} + Ugyldig filformat for Wox-utvidelse + Sett til øverste for denne spørringen + Avbryt øverste for denne spørringen + Utfør spørring: {0} + Tid for siste gjennomføring: {0} + Åpne + Innstillinger + Om + Avslutt + + + Wox-innstillinger + Generelt + Start Wox ved systemstart + Skjul Wox ved mistet fokus + Ikke vis varsel om ny versjon + Husk siste plassering + Språk + Stil for siste spørring + Bevar siste spørring + Velg siste spørring + Tøm siste spørring + Maks antall resultater vist + Ignorer hurtigtaster i fullskjermsmodus + Python-mappe + Oppdater automatisk + Velg + Skjul Wox ved oppstart + + + Utvidelse + Finn flere utvidelser + Deaktiver + Handlingsnøkkelord + Utvidelseskatalog + Forfatter + Oppstartstid: {0}ms + Spørringstid: {0}ms + + + Tema + Finn flere temaer + Hallo Wox + Font for spørringsboks + Font for resultat + Vindusmodus + Gjennomsiktighet + + + Hurtigtast + Wox-hurtigtast + Egendefinerd spørringshurtigtast + Slett + Rediger + Legg til + Vennligst velg et element + Er du sikker på at du vil slette utvidelserhurtigtasten for {0}? + + + HTTP-proxy + Aktiver HTTP-proxy + HTTP-server + Port + Brukernavn + Passord + Test proxy + Lagre + Serverfeltet kan ikke være tomt + Portfelter kan ikke være tomt + Ugyldig portformat + Proxy-konfigurasjon lagret med suksess + Proxy konfigurert riktig + Proxy-tilkobling feilet + + + Om + Netside + Versjon + Du har aktivert Wox {0} ganger + Sjekk for oppdatering + Ny versjon {0} er tilgjengelig, vennligst start Wox på nytt. + Oppdateringssjekk feilet, vennligst sjekk tilkoblingen og proxy-innstillene for api.github.com. + + Nedlastning av oppdateringer feilet, vennligst sjekk tilkoblingen og proxy-innstillene for github-cloud.s3.amazonaws.com, + eller gå til https://github.com/Wox-launcher/Wox/releases for å laste ned oppdateringer manuelt. + + Versjonsmerknader: + + + Gammelt handlingsnøkkelord + Nytt handlingsnøkkelord + Avbryt + Ferdig + Kan ikke finne den angitte utvidelsen + Nytt handlingsnøkkelord kan ikke være tomt + De nye handlingsnøkkelordene er tildelt en annen utvidelse, vennligst velg et annet nøkkelord + Vellykket + Bruk * hvis du ikke ønsker å angi et handlingsnøkkelord + + + Forhåndsvis + Hurtigtasten er ikke tilgjengelig, vennligst velg en ny hurtigtast + Ugyldig hurtigtast for utvidelse + Oppdater + + + Hurtigtast utilgjengelig + + + Versjon + Tid + Fortell oss hvordan programmet krasjet, så vi kan fikse det + Send rapport + Avbryt + Generelt + Unntak + Unntakstype + Kilde + Stack Trace + Sender + Rapport sendt med suksess + Kunne ikke sende rapport + Wox møtte på en feil + + + Versjon {0} av Wox er nå tilgjengelig + En feil oppstod under installasjon av programvareoppdateringer + Oppdater + Avbryt + Denne opgraderingen vil starte Wox på nytt + Følgende filer vil bli oppdatert + Oppdateringsfiler + Oppdateringsbeskrivelse + + diff --git a/src/modules/launcher/Wox/Languages/nl.xaml b/src/modules/launcher/Wox/Languages/nl.xaml new file mode 100644 index 000000000..ffb77a793 --- /dev/null +++ b/src/modules/launcher/Wox/Languages/nl.xaml @@ -0,0 +1,132 @@ + + + Sneltoets registratie: {0} mislukt + Kan {0} niet starten + Ongeldige Wox plugin bestandsextensie + Stel in als hoogste in deze query + Annuleer hoogste in deze query + Executeer query: {0} + Laatste executie tijd: {0} + Open + Instellingen + About + Afsluiten + + + Wox Instellingen + Algemeen + Start Wox als systeem opstart + Verberg Wox als focus verloren is + Laat geen nieuwe versie notificaties zien + Herinner laatste opstart locatie + Taal + Laat maximale resultaten zien + Negeer sneltoetsen in fullscreen mode + Python map + Automatische Update + Selecteer + Verberg Wox als systeem opstart + + + Plugin + Zoek meer plugins + Disable + Action terfwoorden + Plugin map + Auteur + Init tijd: {0}ms + Query tijd: {0}ms + + + Thema + Zoek meer thema´s + Hallo Wox + Query Box lettertype + Resultaat Item lettertype + Window Mode + Ondoorzichtigheid + + + Sneltoets + Wox Sneltoets + Custom Query Sneltoets + Verwijder + Bewerken + Toevoegen + Selecteer een item + Weet u zeker dat je {0} plugin sneltoets wilt verwijderen? + + + HTTP Proxy + Enable HTTP Proxy + HTTP Server + Poort + Gebruikersnaam + Wachtwoord + Test Proxy + Opslaan + Server moet ingevuld worden + Poort moet ingevuld worden + Ongeldige poort formaat + Proxy succesvol opgeslagen + Proxy correct geconfigureerd + Proxy connectie mislukt + + + Over + Website + Versie + U heeft Wox {0} keer opgestart + Zoek naar Updates + Nieuwe versie {0} beschikbaar, start Wox opnieuw op + Release Notes: + + + Oude actie sneltoets + Nieuwe actie sneltoets + Annuleer + Klaar + Kan plugin niet vinden + Nieuwe actie sneltoets moet ingevuld worden + Nieuwe actie sneltoets is toegewezen aan een andere plugin, wijs een nieuwe actie sneltoets aan + Succesvol + Gebruik * wanneer je geen nieuwe actie sneltoets wilt specificeren + + + Voorbeeld + Sneltoets is niet beschikbaar, selecteer een nieuwe sneltoets + Ongeldige plugin sneltoets + Update + + + Sneltoets niet beschikbaar + + + Versie + Tijd + Vertel ons hoe de applicatie is gecrashed, zodat wij de applicatie kunnen verbeteren + Verstuur Rapport + Annuleer + Algemeen + Uitzonderingen + Uitzondering Type + Bron + Stack Opzoeken + Versturen + Rapport succesvol + Rapport mislukt + Wox heeft een error + + + Nieuwe Wox release {0} nu beschikbaar + Een error is voorgekomen tijdens het installeren van de update + Update + Annuleer + Deze upgrade zal Wox opnieuw opstarten + Volgende bestanden zullen worden geüpdatet + Update bestanden + Update beschrijving + + diff --git a/src/modules/launcher/Wox/Languages/pl.xaml b/src/modules/launcher/Wox/Languages/pl.xaml new file mode 100644 index 000000000..f6d638fbc --- /dev/null +++ b/src/modules/launcher/Wox/Languages/pl.xaml @@ -0,0 +1,132 @@ + + + Nie udało się ustawić skrótu klawiszowego: {0} + Nie udało się uruchomić: {0} + Niepoprawny format pliku wtyczki + Ustaw jako najwyższy wynik dla tego zapytania + Usuń ten najwyższy wynik dla tego zapytania + Wyszukaj: {0} + Ostatni czas wykonywania: {0} + Otwórz + Ustawienia + O programie + Wyjdź + + + Ustawienia Wox + Ogólne + Uruchamiaj Wox przy starcie systemu + Ukryj okno Wox kiedy przestanie ono być aktywne + Nie pokazuj powiadomienia o nowej wersji + Zapamiętaj ostatnią pozycję okna + Język + Maksymalna liczba wyników + Ignoruj skróty klawiszowe w trybie pełnego ekranu + Folder biblioteki Python + Automatyczne aktualizacje + Wybierz + Uruchamiaj Wox zminimalizowany + + + Wtyczki + Znajdź więcej wtyczek + Wyłącz + Wyzwalacze + Folder wtyczki + Autor + Czas ładowania: {0}ms + Czas zapytania: {0}ms + + + Skórka + Znajdź więcej skórek + Witaj Wox + Czcionka okna zapytania + Czcionka okna wyników + Tryb w oknie + Przeźroczystość + + + Skrót klawiszowy + Skrót klawiszowy Wox + Skrót klawiszowy niestandardowych zapytań + Usuń + Edytuj + Dodaj + Musisz coś wybrać + Czy jesteś pewien że chcesz usunąć skrót klawiszowy {0} wtyczki? + + + Serwer proxy HTTP + Używaj HTTP proxy + HTTP Serwer + Port + Nazwa użytkownika + Hasło + Sprawdź proxy + Zapisz + Nazwa serwera nie może być pusta + Numer portu nie może być pusty + Nieprawidłowy format numeru portu + Ustawienia proxy zostały zapisane + Proxy zostało skonfigurowane poprawnie + Nie udało się połączyć z serwerem proxy + + + O programie + Strona internetowa + Wersja + Uaktywniłeś Wox {0} razy + Szukaj aktualizacji + Nowa wersja {0} jest dostępna, uruchom ponownie Wox + Zmiany: + + + Stary wyzwalacz + Nowy wyzwalacz + Anuluj + Zapisz + Nie można odnaleźć podanej wtyczki + Nowy wyzwalacz nie może być pusty + Ten wyzwalacz został już przypisany do innej wtyczki, musisz podać inny wyzwalacz. + Sukces + Użyj * jeżeli nie chcesz podawać wyzwalacza + + + Podgląd + Skrót klawiszowy jest niedostępny, musisz podać inny skrót klawiszowy + Niepoprawny skrót klawiszowy + Aktualizuj + + + Niepoprawny skrót klawiszowy + + + Wersja + Czas + Proszę powiedz nam co się stało zanim wystąpił błąd dzięki czemu będziemy mogli go naprawić (tylko po angielsku) + Wyślij raport błędu + Anuluj + Ogólne + Wyjątki + Typ wyjątku + Źródło + Stos wywołań + Wysyłam raport... + Raport wysłany pomyślnie + Nie udało się wysłać raportu + W programie Wox wystąpił błąd + + + Nowa wersja Wox {0} jest dostępna + Wystąpił błąd podczas instalowania aktualizacji programu + Aktualizuj + Anuluj + Aby dokończyć proces aktualizacji Wox musi zostać zresetowany + Następujące pliki zostaną zaktualizowane + Aktualizuj pliki + Opis aktualizacji + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Languages/pt-br.xaml b/src/modules/launcher/Wox/Languages/pt-br.xaml new file mode 100644 index 000000000..bd4e70f24 --- /dev/null +++ b/src/modules/launcher/Wox/Languages/pt-br.xaml @@ -0,0 +1,141 @@ + + + Falha ao registrar atalho: {0} + Não foi possível iniciar {0} + Formato de plugin Wox inválido + Tornar a principal nessa consulta + Cancelar a principal nessa consulta + Executar consulta: {0} + Última execução: {0} + Abrir + Configurações + Sobre + Sair + + + Configurações do Wox + Geral + Iniciar Wox com inicialização do sistema + Esconder Wox quando foco for perdido + Não mostrar notificações de novas versões + Lembrar última localização de lançamento + Idioma + Estilo da Última Consulta + Preservar Última Consulta + Selecionar última consulta + Limpar última consulta + Máximo de resultados mostrados + Ignorar atalhos em tela cheia + Diretório Python + Atualizar Automaticamente + Selecionar + Esconder Wox na inicialização + + + Plugin + Encontrar mais plugins + Desabilitar + Palavras-chave de ação + Diretório de Plugins + Autor + Tempo de inicialização: {0}ms + Tempo de consulta: {0}ms + + + Tema + Ver mais temas + Olá Wox + Fonte da caixa de Consulta + Fonte do Resultado + Modo Janela + Opacidade + + + Atalho + Atalho do Wox + Atalho de Consulta Personalizada + Apagar + Editar + Adicionar + Por favor selecione um item + Tem cereza de que deseja deletar o atalho {0} do plugin? + + + Proxy HTTP + Habilitar Proxy HTTP + Servidor HTTP + Porta + Usuário + Senha + Testar Proxy + Salvar + O campo de servidor não pode ser vazio + O campo de porta não pode ser vazio + Formato de porta inválido + Configuração de proxy salva com sucesso + Proxy configurado corretamente + Conexão por proxy falhou + + + Sobre + Website + Versão + Você ativou o Wox {0} vezes + Procurar atualizações + A nova versão {0} está disponível, por favor reinicie o Wox. + Falha ao procurar atualizações, confira sua conexão e configuração de proxy para api.github.com. + + Falha ao baixar atualizações, confira sua conexão e configuração de proxy para github-cloud.s3.amazonaws.com, + ou acesse https://github.com/Wox-launcher/Wox/releases para baixar manualmente. + + Notas de Versão: + + + Antiga palavra-chave da ação + Nova palavra-chave da ação + Cancelar + Finalizado + Não foi possível encontrar o plugin especificado + A nova palavra-chave da ação não pode ser vazia + A nova palavra-chave da ação já foi atribuída a outro plugin, por favor tente outra + Sucesso + Use * se não quiser especificar uma palavra-chave de ação + + + Prévia + Atalho indisponível, escolha outro + Atalho de plugin inválido + Atualizar + + + Atalho indisponível + + + Versão + Horário + Por favor, conte como a aplicação parou de funcionar para que possamos consertar + Enviar Relatório + Cancelar + Geral + Exceções + Tipo de Exceção + Fonte + Rastreamento de pilha + Enviando + Relatório enviado com sucesso + Falha ao enviar relatório + Wox apresentou um erro + + + A nova versão {0} do Wox agora está disponível + Ocorreu um erro ao tentar instalar atualizações do progama + Atualizar + Cancelar + Essa atualização reiniciará o Wox + Os seguintes arquivos serão atualizados + Atualizar arquivos + Atualizar descrição + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Languages/ru.xaml b/src/modules/launcher/Wox/Languages/ru.xaml new file mode 100644 index 000000000..945162b42 --- /dev/null +++ b/src/modules/launcher/Wox/Languages/ru.xaml @@ -0,0 +1,132 @@ + + + Регистрация хоткея {0} не удалась + Не удалось запустить {0} + Неверный формат файла wox плагина + Отображать это окно выше всех при этом запросе + Не отображать это окно выше всех при этом запросе + Выполнить запрос:{0} + Последний раз выполнен в:{0} + Открыть + Настройки + О Wox + Закрыть + + + Настройки Wox + Общие + Запускать Wox при запуске системы + Скрывать Wox если потерян фокус + Не отображать сообщение об обновлении когда доступна новая версия + Запомнить последнее место запуска + Язык + Максимальное количество результатов + Игнорировать горячие клавиши, если окно в полноэкранном режиме + Python Directory + Auto Update + Select + Hide Wox on startup + + + Плагины + Найти больше плагинов + Отключить + Ключевое слово + Папка + Автор + Инициализация: {0}ms + Запрос: {0}ms + + + Темы + Найти больше тем + Привет Wox + Шрифт запросов + Шрифт результатов + Оконный режим + Прозрачность + + + Горячие клавиши + Горячая клавиша Wox + Задаваемые горячие клавиши для запросов + Удалить + Изменить + Добавить + Сначала выберите элемент + Вы уверены что хотите удалить горячую клавишу для плагина {0}? + + + HTTP Прокси + Включить HTTP прокси + HTTP Сервер + Порт + Логин + Пароль + Проверить + Сохранить + Необходимо задать сервер + Необходимо задать порт + Неверный формат порта + Прокси успешно сохранён + Прокси сервер задан правильно + Подключение к прокси серверу не удалось + + + О Wox + Сайт + Версия + Вы воспользовались Wox уже {0} раз + Check for Updates + New version {0} avaiable, please restart wox + Release Notes: + + + Текущая горячая клавиша + Новая горячая клавиша + Отменить + Подтвердить + Не удалось найти заданный плагин + Новая горячая клавиша не может быть пустой + Новая горячая клавиша уже используется другим плагином. Пожалуйста, задайте новую + Сохранено + Используйте * в случае, если вы не хотите задавать конкретную горячую клавишу + + + Проверить + Горячая клавиша недоступна. Пожалуйста, задайте новую + Недействительная горячая клавиша плагина + Изменить + + + Горячая клавиша недоступна + + + Версия + Время + Пожалуйста, сообщите что произошло когда произошёл сбой в приложении, чтобы мы могли его исправить + Отправить отчёт + Отмена + Общие + Исключения + Тип исключения + Источник + Трессировка стека + Отправляем + Отчёт успешно отправлен + Не удалось отправить отчёт + Произошёл сбой в Wox + + + Доступна новая версия Wox V{0} + Произошла ошибка при попытке установить обновление + Обновить + Отмена + Это обновление перезапустит Wox + Следующие файлы будут обновлены + Обновить файлы + Описание обновления + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Languages/sk.xaml b/src/modules/launcher/Wox/Languages/sk.xaml new file mode 100644 index 000000000..7a7f083ca --- /dev/null +++ b/src/modules/launcher/Wox/Languages/sk.xaml @@ -0,0 +1,142 @@ + + + Nepodarilo sa registrovať klávesovú skratku {0} + Nepodarilo sa spustiť {0} + Neplatný formát súboru pre plugin Wox + Pri tomto dopyte umiestniť navrchu + Zrušiť umiestnenie navrchu pri tomto dopyte + Spustiť dopyt: {0} + Posledný čas realizácie: {0} + Otvoriť + Nastavenia + O aplikácii + Ukončiť + + + Nastavenia Wox + Všeobecné + Spustiť Wox po štarte systému + Schovať Wox po strate fokusu + Nezobrazovať upozornenia na novú verziu + Zapamätať si posledné umiestnenie + Jazyk + Posledný dopyt + Ponechať + Označiť posledný dopyt + Prázdne + Max. výsledkov + Ignorovať klávesové skraty v režime na celú obrazovku + Priečinok s Pythonom + Automatická aktualizácia + Vybrať + Schovať Wox po spustení + Schovať ikonu v oblasti oznámení + + + Plugin + Nájsť ďalšie pluginy + Zakázať + Skratka akcie + Priečinok s pluginmy + Autor + Čas inic.: {0}ms + Čas dopytu: {0}ms + + + Motív + Prehliadať viac motívov + Ahoj Wox + Písmo poľa pre dopyt + Písmo výsledkov + Režim okno + Nepriehľadnosť + + + Klávesová skratka + Klávesová skratka pre Wox + Vlastná klávesová skratka pre dopyt + Odstrániť + Upraviť + Pridať + Vyberte položku, prosím + Ste si istý, že chcete odstrániť klávesovú skratku {0} pre plugin? + + + HTTP Proxy + Povoliť HTTP Proxy + HTTP Server + Port + Používateľské meno + Heslo + Test Proxy + Uložiť + Pole Server nemôže byť prázdne + Pole Port nemôže byť prázdne + Neplatný formát portu + Nastavenie proxy úspešne uložené + Nastavenie proxy je v poriadku + Pripojenie proxy zlyhalo + + + O aplikácii + Webstránka + Verzia + Wox bol aktivovaný {0}-krát + Skontrolovať aktualizácie + Je dostupná nová verzia {0}, prosím, reštartujte Wox. + Kontrola aktualizácií zlyhala, prosím, skontrolujte pripojenie na internet a nastavenie proxy k api.github.com. + + Sťahovanie aktualizácií zlyhalo, skontrolujte pripojenie na internet a nastavenie proxy k github-cloud.s3.amazonaws.com, + alebo prejdite na https://github.com/Wox-launcher/Wox/releases pre manuálne stiahnutie aktualizácií. + + Poznámky k vydaniu: + + + Stará skratka akcie + Nová skratka akcie + Zrušiť + Hotovo + Nepodarilo sa nájsť zadaný plugin + Nová skratka pre akciu nemôže byť prázdna + Nová skratka pre akciu bola priradená pre iný plugin, prosím, zvoľte inú skratku + Úspešné + Použite * ak nechcete určiť skratku pre akciu + + + Náhľad + Klávesová skratka je nedostupná, prosím, zadajte novú + Neplatná klávesová skratka pluginu + Aktualizovať + + + Klávesová skratka nedostupná + + + Verzia + Čas + Prosím, napíšte nám, ako došlo k pádu aplikácie, aby sme to mohli opraviť + Odoslať hlásenie + Zrušiť + Všeobecné + Výnimky + Typ výnimky + Zdroj + Stack Trace + Odosiela sa + Hlásenie bolo úspešne odoslané + Odoslanie hlásenia zlyhalo + Wox zaznamenal chybu + + + Je dostupné nové vydanie Wox {0} + Počas inštalácie aktualizácií došlo k chybe + Aktualizovať + Zrušiť + Tento upgrade reštartuje Wox + Nasledujúce súbory budú aktualizované + Aktualizovať súbory + Aktualizovať popis + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Languages/sr.xaml b/src/modules/launcher/Wox/Languages/sr.xaml new file mode 100644 index 000000000..dd8826e1c --- /dev/null +++ b/src/modules/launcher/Wox/Languages/sr.xaml @@ -0,0 +1,141 @@ + + + Neuspešno registrovana prečica: {0} + Neuspešno pokretanje {0} + Nepravilni Wox plugin format datoteke + Postavi kao najviši u ovom upitu + Poništi najviši u ovom upitu + Izvrši upit: {0} + Vreme poslednjeg izvršenja: {0} + Otvori + Podešavanja + O Wox-u + Izlaz + + + Wox Podešavanja + Opšte + Pokreni Wox pri podizanju sistema + Sakri Wox kada se izgubi fokus + Ne prikazuj obaveštenje o novoj verziji + Zapamti lokaciju poslednjeg pokretanja + Jezik + Stil Poslednjeg upita + Sačuvaj poslednji Upit + Selektuj poslednji Upit + Isprazni poslednji Upit + Maksimum prikazanih rezultata + Ignoriši prečice u fullscreen režimu + Python direktorijum + Auto ažuriranje + Izaberi + Sakrij Wox pri podizanju sistema + + + Plugin + Nađi još plugin-a + Onemogući + Ključne reči + Plugin direktorijum + Autor + Vreme inicijalizacije: {0}ms + Vreme upita: {0}ms + + + Tema + Pretražite još tema + Zdravo Wox + Font upita + Font rezultata + Režim prozora + Neprozirnost + + + Prečica + Wox prečica + prečica za ručno dodat upit + Obriši + Izmeni + Dodaj + Molim Vas izaberite stavku + Da li ste sigurni da želite da obrišete prečicu za {0} plugin? + + + HTTP proksi + Uključi HTTP proksi + HTTP Server + Port + Korisničko ime + Šifra + Test proksi + Sačuvaj + Polje za server ne može da bude prazno + Polje za port ne može da bude prazno + Nepravilan format porta + Podešavanja proksija uspešno sačuvana + Proksi uspešno podešen + Veza sa proksijem neuspešna + + + O Wox-u + Veb sajt + Verzija + Aktivirali ste Wox {0} puta + Proveri ažuriranja + Nove verzija {0} je dostupna, molim Vas ponovo pokrenite Wox. + Neuspešna provera ažuriranja, molim Vas proverite vašu vezu i podešavanja za proksi prema api.github.com. + + Neuspešno preuzimanje ažuriranja, molim Vas proverite vašu vezu i podešavanja za proksi prema github-cloud.s3.amazonaws.com, + ili posetite https://github.com/Wox-launcher/Wox/releases da preuzmete ažuriranja ručno. + + U novoj verziji: + + + Prečica za staru radnju + Prečica za novu radnju + Otkaži + Gotovo + Navedeni plugin nije moguće pronaći + Prečica za novu radnju ne može da bude prazna + Prečica za novu radnju je dodeljena drugom plugin-u, molim Vas dodelite drugu prečicu + Uspešno + Koristite * ako ne želite da navedete prečicu za radnju + + + Pregled + Prečica je nedustupna, molim Vas izaberite drugu prečicu + Nepravlna prečica za plugin + Ažuriraj + + + Prečica nedostupna + + + Verzija + Vreme + Molimo Vas recite nam kako je aplikacija prestala sa radom, da bi smo je ispravili + Pošalji izveštaj + Otkaži + Opšte + Izuzetak + Tipovi Izuzetaka + Izvor + Stack Trace + Slanje + Izveštaj uspešno poslat + Izveštaj neuspešno poslat + Wox je dobio grešku + + + Nova verzija Wox-a {0} je dostupna + Došlo je do greške prilokom instalacije ažuriranja + Ažuriraj + Otkaži + Ova nadogradnja će ponovo pokrenuti Wox + Sledeće datoteke će biti ažurirane + Ažuriraj datoteke + Opis ažuriranja + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Languages/tr.xaml b/src/modules/launcher/Wox/Languages/tr.xaml new file mode 100644 index 000000000..82445e2ac --- /dev/null +++ b/src/modules/launcher/Wox/Languages/tr.xaml @@ -0,0 +1,145 @@ + + + Kısayol tuşu ataması başarısız oldu: {0} + {0} başlatılamıyor + Geçersiz Wox eklenti dosyası formatı + Bu sorgu için başa sabitle + Sabitlemeyi kaldır + Sorguyu çalıştır: {0} + Son çalıştırma zamanı: {0} + + Ayarlar + Hakkında + Çıkış + + + Wox Ayarları + Genel + Wox'u başlangıçta başlat + Odak pencereden ayrıldığında Wox'u gizle + Güncelleme bildirimlerini gösterme + Pencere konumunu hatırla + Dil + Pencere açıldığında + Son sorguyu sakla + Son sorguyu sakla ve tümünü seç + Sorgu kutusunu temizle + Maksimum sonuç sayısı + Tam ekran modunda kısayol tuşunu gözardı et + Python Konumu + Otomatik Güncelle + Seç + Başlangıçta Wox'u gizle + Sistem çekmecesi simgesini gizle + Sorgu Arama Hassasiyeti + + + Eklentiler + Daha fazla eklenti bul + Devre Dışı + Anahtar Kelimeler + Eklenti Klasörü + Yapımcı + Açılış Süresi: {0}ms + Sorgu Süresi: {0}ms + + + Temalar + Daha fazla tema bul + Merhaba Wox + Pencere Yazı Tipi + Sonuç Yazı Tipi + Pencere Modu + Saydamlık + {0} isimli tema bulunamadı, varsayılan temaya dönülüyor. + {0} isimli tema yüklenirken hata oluştu, varsayılan temaya dönülüyor. + + + Kısayol Tuşu + Wox Kısayolu + Özel Sorgu Kısayolları + Sil + Düzenle + Ekle + Lütfen bir öğe seçin + {0} eklentisi için olan kısayolu silmek istediğinize emin misiniz? + + + Vekil Sunucu + HTTP vekil sunucuyu etkinleştir. + Sunucu Adresi + Port + Kullanıcı Adı + Parola + Ayarları Sına + Kaydet + Sunucu adresi boş olamaz + Port boş olamaz + Port biçimi geçersiz + Vekil sunucu ayarları başarıyla kaydedildi + Vekil sunucu doğru olarak ayarlandı + Vekil sunucuya bağlanılırken hata oluştu + + + Hakkında + Web Sitesi + Sürüm + Şu ana kadar Wox'u {0} kez aktifleştirdiniz. + Güncellemeleri Kontrol Et + Uygulamanın yeni sürümü ({0}) mevcut, Lütfen Wox'u yeniden başlatın. + Güncelleme kontrolü başarısız oldu. Lütfen bağlantınız ve vekil sunucu ayarlarınızın api.github.com adresine ulaşabilir olduğunu kontrol edin. + + Güncellemenin yüklenmesi başarısız oldu. Lütfen bağlantınız ve vekil sunucu ayarlarınızın github-cloud.s3.amazonaws.com + adresine ulaşabilir olduğunu kontrol edin ya da https://github.com/Wox-launcher/Wox/releases adresinden güncellemeyi elle indirin. + + Sürüm Notları: + + + Eski Anahtar Kelime + Yeni Anahtar Kelime + İptal + Tamam + Belirtilen eklenti bulunamadı + Yeni anahtar kelime boş olamaz + Yeni anahtar kelime başka bir eklentiye atanmış durumda. Lütfen başka bir anahtar kelime seçin + Başarılı + Anahtar kelime belirlemek istemiyorsanız * kullanın + + + Önizleme + Kısayol tuşu kullanılabilir değil, lütfen başka bir kısayol tuşu seçin + Geçersiz eklenti kısayol tuşu + Güncelle + + + Kısayol tuşu kullanılabilir değil + + + Sürüm + Tarih + Sorunu çözebilmemiz için lütfen uygulamanın ne yaparken çöktüğünü belirtin. + Raporu Gönder + İptal + Genel + Özel Durumlar + Özel Durum Tipi + Kaynak + Yığın İzleme + Gönderiliyor + Hata raporu başarıyla gönderildi + Hata raporu gönderimi başarısız oldu + Wox'ta bir hata oluştu + + + Wox'un yeni bir sürümü ({0}) mevcut + Güncellemelerin kurulması sırasında bir hata oluştu + Güncelle + İptal + Bu güncelleme Wox'u yeniden başlatacaktır + Aşağıdaki dosyalar güncelleştirilecektir + Güncellenecek dosyalar + Güncelleme açıklaması + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Languages/uk-UA.xaml b/src/modules/launcher/Wox/Languages/uk-UA.xaml new file mode 100644 index 000000000..e114c2706 --- /dev/null +++ b/src/modules/launcher/Wox/Languages/uk-UA.xaml @@ -0,0 +1,132 @@ + + + Реєстрація хоткея {0} не вдалася + Не вдалося запустити {0} + Невірний формат файлу плагіна Wox + Відображати першим при такому ж запиті + Відмінити відображення першим при такому ж запиті + Виконати запит: {0} + Час останнього використання: {0} + Відкрити + Налаштування + Про Wox + Закрити + + + Налаштування Wox + Основні + Запускати Wox при запуску системи + Сховати Wox якщо втрачено фокус + Не повідомляти про доступні нові версії + Запам'ятати останнє місце запуску + Мова + Максимальна кількість результатів + Ігнорувати гарячі клавіші в повноекранному режимі + Директорія Python + Автоматичне оновлення + Вибрати + Сховати Wox при запуску системи + + + Плагіни + Знайти більше плагінів + Відключити + Ключове слово + Директорія плагіну + Автор + Ініціалізація: {0}ms + Запит: {0}ms + + + Теми + Знайти більше тем + Привіт Wox + Шрифт запитів + Шрифт результатів + Віконний режим + Прозорість + + + Гарячі клавіші + Гаряча клавіша Wox + Задані гарячі клавіші для запитів + Видалити + Змінити + Додати + Спочатку виберіть елемент + Ви впевнені, що хочете видалити гарячу клавішу ({0}) плагіну? + + + HTTP Proxy + Включити HTTP Proxy + HTTP Сервер + Порт + Логін + Пароль + Перевірити Proxy + Зберегти + Необхідно вказати "HTTP Сервер" + Необхідно вказати "Порт" + Невірний формат порту + Налаштування Proxy успішно збережено + Proxy успішно налаштований + Невдале підключення Proxy + + + Про Wox + Сайт + Версия + Ви скористалися Wox вже {0} разів + Перевірити наявність оновлень + Доступна нова версія {0}, будь ласка, перезавантажте Wox + Примітки до поточного релізу: + + + Поточна гаряча клавіша + Нова гаряча клавіша + Скасувати + Готово + Не вдалося знайти вказаний плагін + Нова гаряча клавіша не може бути порожньою + Нова гаряча клавіша вже використовується іншим плагіном. Будь ласка, вкажіть нову + Збережено + Використовуйте * у разі, якщо ви не хочете ставити конкретну гарячу клавішу + + + Перевірити + Гаряча клавіша недоступна. Будь ласка, вкажіть нову + Недійсна гаряча клавіша плагіна + Оновити + + + Гаряча клавіша недоступна + + + Версія + Час + Будь ласка, розкажіть нам, як додаток вийшов із ладу, щоб ми могли це виправити + Надіслати звіт + Скасувати + Основне + Винятки + Тип винятку + Джерело + Траса стеку + Відправити + Звіт успішно відправлено + Не вдалося відправити звіт + Стався збій в додатоку Wox + + + Доступна нова версія Wox V{0} + Сталася помилка під час спроби встановити оновлення + Оновити + Скасувати + Це оновлення перезавантажить Wox + Ці файли будуть оновлені + Оновити файли + Опис оновлення + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Languages/zh-cn.xaml b/src/modules/launcher/Wox/Languages/zh-cn.xaml new file mode 100644 index 000000000..679040928 --- /dev/null +++ b/src/modules/launcher/Wox/Languages/zh-cn.xaml @@ -0,0 +1,139 @@ + + + 注册热键:{0} 失败 + 启动命令 {0} 失败 + 不是合法的Wox插件格式 + 在当前查询中置顶 + 取消置顶 + 执行查询:{0} + 上次执行时间:{0} + 打开 + 设置 + 关于 + 退出 + + + Wox设置 + 通用 + 开机启动 + 失去焦点时自动隐藏Wox + 不显示新版本提示 + 记住上次启动位置 + 语言 + 上次搜索关键字模式 + 保留上次搜索关键字 + 全选上次搜索关键字 + 清空上次搜索关键字 + 最大结果显示个数 + 全屏模式下忽略热键 + Python 路径 + 自动更新 + Select + 启动时不显示主窗口 + 隐藏任务栏图标 + + + 插件 + 浏览更多插件 + 禁用 + 触发关键字 + 插件目录 + 作者 + 加载耗时 {0}ms + 查询耗时 {0}ms + + + 主题 + 浏览更多主题 + 你好,Wox + 查询框字体 + 结果项字体 + 窗口模式 + 透明度 + 无法找到主题 {0} ,切换为默认主题 + 无法加载主题 {0} ,切换为默认主题 + + + 热键 + Wox激活热键 + 自定义查询热键 + 删除 + 编辑 + 增加 + 请选择一项 + 你确定要删除插件 {0} 的热键吗? + + + HTTP 代理 + 启用 HTTP 代理 + HTTP 服务器 + 端口 + 用户名 + 密码 + 测试代理 + 保存 + 服务器不能为空 + 端口不能为空 + 非法的端口格式 + 保存代理设置成功 + 代理设置正确 + 代理连接失败 + + + 关于 + 网站 + 版本 + 你已经激活了Wox {0} 次 + 检查更新 + 发现新版本 {0} , 请重启 wox。 + 更新说明: + + + 旧触发关键字 + 新触发关键字 + 取消 + 确定 + 找不到指定的插件 + 新触发关键字不能为空 + 新触发关键字已经被指派给其他插件了,请重新选择一个关键字 + 成功 + 如果你不想设置触发关键字,可以使用*代替 + + + 预览 + 热键不可用,请选择一个新的热键 + 插件热键不合法 + 更新 + + + 热键不可用 + + + 版本 + 时间 + 请告诉我们如何重现此问题,以便我们进行修复 + 发送报告 + 取消 + 基本信息 + 异常信息 + 异常类型 + 异常源 + 堆栈信息 + 发送中 + 发送成功 + 发送失败 + Wox出错啦 + + + 发现Wox新版本 V{0} + 更新Wox出错 + 更新 + 取消 + 此更新需要重启Wox + 下列文件会被更新 + 更新文件 + 更新日志 + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Languages/zh-tw.xaml b/src/modules/launcher/Wox/Languages/zh-tw.xaml new file mode 100644 index 000000000..9b26b0d06 --- /dev/null +++ b/src/modules/launcher/Wox/Languages/zh-tw.xaml @@ -0,0 +1,132 @@ + + + 登錄快速鍵:{0} 失敗 + 啟動命令 {0} 失敗 + 無效的 Wox 外掛格式 + 在目前查詢中置頂 + 取消置頂 + 執行查詢:{0} + 上次執行時間:{0} + 開啟 + 設定 + 關於 + 結束 + + + Wox 設定 + 一般 + 開機時啟動 + 失去焦點時自動隱藏 Wox + 不顯示新版本提示 + 記住上次啟動位置 + 語言 + 最大結果顯示個數 + 全螢幕模式下忽略熱鍵 + Python 路徑 + 自動更新 + 選擇 + 啟動時不顯示主視窗 + + + 外掛 + 瀏覽更多外掛 + 停用 + 觸發關鍵字 + 外掛資料夾 + 作者 + 載入耗時:{0}ms + 查詢耗時:{0}ms + + + 主題 + 瀏覽更多主題 + 你好,Wox + 查詢框字體 + 結果項字體 + 視窗模式 + 透明度 + + + 熱鍵 + Wox 執行熱鍵 + 自定義熱鍵查詢 + 刪除 + 編輯 + 新增 + 請選擇一項 + 確定要刪除外掛 {0} 的熱鍵嗎? + + + HTTP 代理 + 啟用 HTTP 代理 + HTTP 伺服器 + Port + 使用者 + 密碼 + 測試代理 + 儲存 + 伺服器不能為空 + Port 不能為空 + 不正確的 Port 格式 + 儲存代理設定成功 + 代理設定完成 + 代理連線失敗 + + + 關於 + 網站 + 版本 + 您已經啟動了 Wox {0} 次 + 檢查更新 + 發現有新版本 {0}, 請重新啟動 Wox。 + 更新說明: + + + 舊觸發關鍵字 + 新觸發關鍵字 + 取消 + 確定 + 找不到指定的外掛 + 新觸發關鍵字不能為空白 + 新觸發關鍵字已經被指派給另一外掛,請設定其他關鍵字。 + 成功 + 如果不想設定觸發關鍵字,可以使用*代替 + + + 預覽 + 熱鍵不存在,請設定一個新的熱鍵 + 外掛熱鍵無法使用 + 更新 + + + 熱鍵無法使用 + + + 版本 + 時間 + 請告訴我們如何重現此問題,以便我們進行修復 + 發送報告 + 取消 + 基本訊息 + 例外訊息 + 例外類型 + 例外來源 + 堆疊資訊 + 傳送中 + 傳送成功 + 傳送失敗 + Wox 出錯啦 + + + 發現 Wox 新版本 V{0} + 更新 Wox 出錯 + 更新 + 取消 + 此更新需要重新啟動 Wox + 下列檔案會被更新 + 更新檔案 + 更新日誌 + + diff --git a/src/modules/launcher/Wox/MainWindow.xaml b/src/modules/launcher/Wox/MainWindow.xaml new file mode 100644 index 000000000..d50411b83 --- /dev/null +++ b/src/modules/launcher/Wox/MainWindow.xaml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/launcher/Wox/MainWindow.xaml.cs b/src/modules/launcher/Wox/MainWindow.xaml.cs new file mode 100644 index 000000000..427f641a4 --- /dev/null +++ b/src/modules/launcher/Wox/MainWindow.xaml.cs @@ -0,0 +1,300 @@ +using System; +using System.ComponentModel; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media.Animation; +using System.Windows.Controls; +using System.Windows.Forms; +using Wox.Core.Plugin; +using Wox.Core.Resource; +using Wox.Helper; +using Wox.Infrastructure.UserSettings; +using Wox.ViewModel; +using Screen = System.Windows.Forms.Screen; +using ContextMenuStrip = System.Windows.Forms.ContextMenuStrip; +using DataFormats = System.Windows.DataFormats; +using DragEventArgs = System.Windows.DragEventArgs; +using KeyEventArgs = System.Windows.Input.KeyEventArgs; +using MessageBox = System.Windows.MessageBox; +using NotifyIcon = System.Windows.Forms.NotifyIcon; + +namespace Wox +{ + public partial class MainWindow + { + + #region Private Fields + + private readonly Storyboard _progressBarStoryboard = new Storyboard(); + private Settings _settings; + private NotifyIcon _notifyIcon; + private MainViewModel _viewModel; + + #endregion + + public MainWindow(Settings settings, MainViewModel mainVM) + { + DataContext = mainVM; + _viewModel = mainVM; + _settings = settings; + InitializeComponent(); + } + public MainWindow() + { + InitializeComponent(); + } + + private void OnClosing(object sender, CancelEventArgs e) + { + _notifyIcon.Visible = false; + _viewModel.Save(); + } + + private void OnInitialized(object sender, EventArgs e) + { + // show notify icon when wox is hided + InitializeNotifyIcon(); + } + + private void OnLoaded(object sender, RoutedEventArgs _) + { + // todo is there a way to set blur only once? + ThemeManager.Instance.SetBlurForWindow(); + WindowsInteropHelper.DisableControlBox(this); + InitProgressbarAnimation(); + InitializePosition(); + // since the default main window visibility is visible + // so we need set focus during startup + QueryTextBox.Focus(); + + _viewModel.PropertyChanged += (o, e) => + { + if (e.PropertyName == nameof(MainViewModel.MainWindowVisibility)) + { + if (Visibility == Visibility.Visible) + { + Activate(); + QueryTextBox.Focus(); + UpdatePosition(); + _settings.ActivateTimes++; + if (!_viewModel.LastQuerySelected) + { + QueryTextBox.SelectAll(); + _viewModel.LastQuerySelected = true; + } + } + } + }; + _settings.PropertyChanged += (o, e) => + { + if (e.PropertyName == nameof(Settings.HideNotifyIcon)) + { + _notifyIcon.Visible = !_settings.HideNotifyIcon; + } + }; + InitializePosition(); + } + + private void InitializePosition() + { + Top = WindowTop(); + Left = WindowLeft(); + _settings.WindowTop = Top; + _settings.WindowLeft = Left; + } + + private void InitializeNotifyIcon() + { + _notifyIcon = new NotifyIcon + { + Text = Infrastructure.Constant.Wox, + Icon = Properties.Resources.app, + Visible = !_settings.HideNotifyIcon + }; + var menu = new ContextMenuStrip(); + var items = menu.Items; + + var open = items.Add(InternationalizationManager.Instance.GetTranslation("iconTrayOpen")); + open.Click += (o, e) => Visibility = Visibility.Visible; + var setting = items.Add(InternationalizationManager.Instance.GetTranslation("iconTraySettings")); + setting.Click += (o, e) => App.API.OpenSettingDialog(); + var exit = items.Add(InternationalizationManager.Instance.GetTranslation("iconTrayExit")); + exit.Click += (o, e) => Close(); + + _notifyIcon.ContextMenuStrip = menu; + _notifyIcon.MouseClick += (o, e) => + { + if (e.Button == MouseButtons.Left) + { + if (menu.Visible) + { + menu.Close(); + } + else + { + var p = System.Windows.Forms.Cursor.Position; + menu.Show(p); + } + } + }; + } + + private void InitProgressbarAnimation() + { + var da = new DoubleAnimation(ProgressBar.X2, ActualWidth + 100, new Duration(new TimeSpan(0, 0, 0, 0, 1600))); + var da1 = new DoubleAnimation(ProgressBar.X1, ActualWidth, new Duration(new TimeSpan(0, 0, 0, 0, 1600))); + Storyboard.SetTargetProperty(da, new PropertyPath("(Line.X2)")); + Storyboard.SetTargetProperty(da1, new PropertyPath("(Line.X1)")); + _progressBarStoryboard.Children.Add(da); + _progressBarStoryboard.Children.Add(da1); + _progressBarStoryboard.RepeatBehavior = RepeatBehavior.Forever; + ProgressBar.BeginStoryboard(_progressBarStoryboard); + _viewModel.ProgressBarVisibility = Visibility.Hidden; + } + + private void OnMouseDown(object sender, MouseButtonEventArgs e) + { + if (e.ChangedButton == MouseButton.Left) DragMove(); + } + + private void OnPreviewMouseButtonDown(object sender, MouseButtonEventArgs e) + { + if (sender != null && e.OriginalSource != null) + { + var r = (ResultListBox)sender; + var d = (DependencyObject)e.OriginalSource; + var item = ItemsControl.ContainerFromElement(r, d) as ListBoxItem; + var result = (ResultViewModel)item?.DataContext; + if (result != null) + { + if (e.ChangedButton == MouseButton.Left) + { + _viewModel.OpenResultCommand.Execute(null); + } + else if (e.ChangedButton == MouseButton.Right) + { + _viewModel.LoadContextMenuCommand.Execute(null); + } + } + } + } + + + private void OnDrop(object sender, DragEventArgs e) + { + if (e.Data.GetDataPresent(DataFormats.FileDrop)) + { + // Note that you can have more than one file. + string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); + if (files[0].ToLower().EndsWith(".wox")) + { + PluginManager.InstallPlugin(files[0]); + } + else + { + MessageBox.Show(InternationalizationManager.Instance.GetTranslation("invalidWoxPluginFileFormat")); + } + } + e.Handled = false; + } + + private void OnPreviewDragOver(object sender, DragEventArgs e) + { + e.Handled = true; + } + + private void OnContextMenusForSettingsClick(object sender, RoutedEventArgs e) + { + App.API.OpenSettingDialog(); + } + + + private void OnDeactivated(object sender, EventArgs e) + { + if (_settings.HideWhenDeactive) + { + Hide(); + } + } + + private void UpdatePosition() + { + if (_settings.RememberLastLaunchLocation) + { + Left = _settings.WindowLeft; + Top = _settings.WindowTop; + } + else + { + Left = WindowLeft(); + Top = WindowTop(); + } + } + + private void OnLocationChanged(object sender, EventArgs e) + { + if (_settings.RememberLastLaunchLocation) + { + _settings.WindowLeft = Left; + _settings.WindowTop = Top; + } + } + + private double WindowLeft() + { + var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); + var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0); + var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0); + var left = (dip2.X - ActualWidth) / 2 + dip1.X; + return left; + } + + private double WindowTop() + { + var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); + var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y); + var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Height); + var top = (dip2.Y - QueryTextBox.ActualHeight) / 4 + dip1.Y; + return top; + } + + /// + /// Register up and down key + /// todo: any way to put this in xaml ? + /// + private void OnKeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Down) + { + _viewModel.SelectNextItemCommand.Execute(null); + e.Handled = true; + } + else if (e.Key == Key.Up) + { + _viewModel.SelectPrevItemCommand.Execute(null); + e.Handled = true; + } + else if (e.Key == Key.PageDown) + { + _viewModel.SelectNextPageCommand.Execute(null); + e.Handled = true; + } + else if (e.Key == Key.PageUp) + { + _viewModel.SelectPrevPageCommand.Execute(null); + e.Handled = true; + } + } + + private void OnTextChanged(object sender, TextChangedEventArgs e) + { + if (_viewModel.QueryTextCursorMovedToEnd) + { + QueryTextBox.CaretIndex = QueryTextBox.Text.Length; + _viewModel.QueryTextCursorMovedToEnd = false; + } + } + + + } +} \ No newline at end of file diff --git a/src/modules/launcher/Wox/Msg.xaml b/src/modules/launcher/Wox/Msg.xaml new file mode 100644 index 000000000..b077be8e0 --- /dev/null +++ b/src/modules/launcher/Wox/Msg.xaml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Title + sdfdsf + + + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Msg.xaml.cs b/src/modules/launcher/Wox/Msg.xaml.cs new file mode 100644 index 000000000..df82edb12 --- /dev/null +++ b/src/modules/launcher/Wox/Msg.xaml.cs @@ -0,0 +1,87 @@ +using System; +using System.IO; +using System.Windows; +using System.Windows.Forms; +using System.Windows.Input; +using System.Windows.Media.Animation; +using System.Windows.Media.Imaging; +using Wox.Helper; +using Wox.Infrastructure; +using Wox.Infrastructure.Image; + +namespace Wox +{ + public partial class Msg : Window + { + Storyboard fadeOutStoryboard = new Storyboard(); + private bool closing; + + public Msg() + { + InitializeComponent(); + var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); + var dipWorkingArea = WindowsInteropHelper.TransformPixelsToDIP(this, + screen.WorkingArea.Width, + screen.WorkingArea.Height); + Left = dipWorkingArea.X - Width; + Top = dipWorkingArea.Y; + showAnimation.From = dipWorkingArea.Y; + showAnimation.To = dipWorkingArea.Y - Height; + + // Create the fade out storyboard + fadeOutStoryboard.Completed += fadeOutStoryboard_Completed; + DoubleAnimation fadeOutAnimation = new DoubleAnimation(dipWorkingArea.Y - Height, dipWorkingArea.Y, new Duration(TimeSpan.FromSeconds(5))) + { + AccelerationRatio = 0.2 + }; + Storyboard.SetTarget(fadeOutAnimation, this); + Storyboard.SetTargetProperty(fadeOutAnimation, new PropertyPath(TopProperty)); + fadeOutStoryboard.Children.Add(fadeOutAnimation); + + imgClose.Source = ImageLoader.Load(Path.Combine(Infrastructure.Constant.ProgramDirectory, "Images\\close.png")); + imgClose.MouseUp += imgClose_MouseUp; + } + + void imgClose_MouseUp(object sender, MouseButtonEventArgs e) + { + if (!closing) + { + closing = true; + fadeOutStoryboard.Begin(); + } + } + + private void fadeOutStoryboard_Completed(object sender, EventArgs e) + { + Close(); + } + + public void Show(string title, string subTitle, string iconPath) + { + tbTitle.Text = title; + tbSubTitle.Text = subTitle; + if (string.IsNullOrEmpty(subTitle)) + { + tbSubTitle.Visibility = Visibility.Collapsed; + } + if (!File.Exists(iconPath)) + { + imgIco.Source = ImageLoader.Load(Path.Combine(Infrastructure.Constant.ProgramDirectory, "Images\\app.png")); + } + else { + imgIco.Source = ImageLoader.Load(iconPath); + } + + Show(); + + Dispatcher.InvokeAsync(async () => + { + if (!closing) + { + closing = true; + await Dispatcher.InvokeAsync(fadeOutStoryboard.Begin); + } + }); + } + } +} diff --git a/src/modules/launcher/Wox/Properties/AssemblyInfo.cs b/src/modules/launcher/Wox/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..3ce943af6 --- /dev/null +++ b/src/modules/launcher/Wox/Properties/AssemblyInfo.cs @@ -0,0 +1,8 @@ +using System.Reflection; +using System.Windows; + +[assembly: AssemblyTitle("Wox")] +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, + ResourceDictionaryLocation.SourceAssembly +)] \ No newline at end of file diff --git a/src/modules/launcher/Wox/Properties/Resources.Designer.cs b/src/modules/launcher/Wox/Properties/Resources.Designer.cs new file mode 100644 index 000000000..20e0fb225 --- /dev/null +++ b/src/modules/launcher/Wox/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Wox.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Wox.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// + internal static System.Drawing.Icon app { + get { + object obj = ResourceManager.GetObject("app", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + } +} diff --git a/src/modules/launcher/Wox/Properties/Resources.resx b/src/modules/launcher/Wox/Properties/Resources.resx new file mode 100644 index 000000000..3ae43d89b --- /dev/null +++ b/src/modules/launcher/Wox/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\app.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/Properties/Settings.Designer.cs b/src/modules/launcher/Wox/Properties/Settings.Designer.cs new file mode 100644 index 000000000..a61339f5e --- /dev/null +++ b/src/modules/launcher/Wox/Properties/Settings.Designer.cs @@ -0,0 +1,35 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Wox.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.3.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("https://github.com/Wox-launcher/Wox")] + public string GithubRepo { + get { + return ((string)(this["GithubRepo"])); + } + } + } +} diff --git a/src/modules/launcher/Wox/Properties/Settings.settings b/src/modules/launcher/Wox/Properties/Settings.settings new file mode 100644 index 000000000..1fc52390b --- /dev/null +++ b/src/modules/launcher/Wox/Properties/Settings.settings @@ -0,0 +1,9 @@ + + + + + + https://github.com/Wox-launcher/Wox + + + \ No newline at end of file diff --git a/src/modules/launcher/Wox/PublicAPIInstance.cs b/src/modules/launcher/Wox/PublicAPIInstance.cs new file mode 100644 index 000000000..58915f87b --- /dev/null +++ b/src/modules/launcher/Wox/PublicAPIInstance.cs @@ -0,0 +1,173 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using System.Windows; +using Squirrel; +using Wox.Core; +using Wox.Core.Plugin; +using Wox.Core.Resource; +using Wox.Helper; +using Wox.Infrastructure; +using Wox.Infrastructure.Hotkey; +using Wox.Infrastructure.Image; +using Wox.Plugin; +using Wox.ViewModel; + +namespace Wox +{ + public class PublicAPIInstance : IPublicAPI + { + private readonly SettingWindowViewModel _settingsVM; + private readonly MainViewModel _mainVM; + private readonly Alphabet _alphabet; + + #region Constructor + + public PublicAPIInstance(SettingWindowViewModel settingsVM, MainViewModel mainVM, Alphabet alphabet) + { + _settingsVM = settingsVM; + _mainVM = mainVM; + _alphabet = alphabet; + GlobalHotkey.Instance.hookedKeyboardCallback += KListener_hookedKeyboardCallback; + WebRequest.RegisterPrefix("data", new DataWebRequestFactory()); + } + + #endregion + + #region Public API + + public void ChangeQuery(string query, bool requery = false) + { + _mainVM.ChangeQueryText(query); + } + + public void ChangeQueryText(string query, bool selectAll = false) + { + _mainVM.ChangeQueryText(query); + } + + [Obsolete] + public void CloseApp() + { + Application.Current.MainWindow.Close(); + } + + public void RestarApp() + { + _mainVM.MainWindowVisibility = Visibility.Hidden; + + // we must manually save + // UpdateManager.RestartApp() will call Environment.Exit(0) + // which will cause ungraceful exit + SaveAppAllSettings(); + + UpdateManager.RestartApp(); + } + + public void CheckForNewUpdate() + { + _settingsVM.UpdateApp(); + } + + public void SaveAppAllSettings() + { + _mainVM.Save(); + _settingsVM.Save(); + PluginManager.Save(); + ImageLoader.Save(); + _alphabet.Save(); + } + + public void ReloadAllPluginData() + { + PluginManager.ReloadData(); + } + + [Obsolete] + public void HideApp() + { + _mainVM.MainWindowVisibility = Visibility.Hidden; + } + + [Obsolete] + public void ShowApp() + { + _mainVM.MainWindowVisibility = Visibility.Visible; + } + + public void ShowMsg(string title, string subTitle = "", string iconPath = "", bool useMainWindowAsOwner = true) + { + Application.Current.Dispatcher.Invoke(() => + { + var msg = useMainWindowAsOwner ? new Msg {Owner = Application.Current.MainWindow} : new Msg(); + msg.Show(title, subTitle, iconPath); + }); + } + + public void OpenSettingDialog() + { + Application.Current.Dispatcher.Invoke(() => + { + SettingWindow sw = SingletonWindowOpener.Open(this, _settingsVM); + }); + } + + public void StartLoadingBar() + { + _mainVM.ProgressBarVisibility = Visibility.Visible; + } + + public void StopLoadingBar() + { + _mainVM.ProgressBarVisibility = Visibility.Collapsed; + } + + public void InstallPlugin(string path) + { + Application.Current.Dispatcher.Invoke(() => PluginManager.InstallPlugin(path)); + } + + public string GetTranslation(string key) + { + return InternationalizationManager.Instance.GetTranslation(key); + } + + public List GetAllPlugins() + { + return PluginManager.AllPlugins.ToList(); + } + + public event WoxGlobalKeyboardEventHandler GlobalKeyboardEvent; + + [Obsolete("This will be removed in Wox 1.3")] + public void PushResults(Query query, PluginMetadata plugin, List results) + { + results.ForEach(o => + { + o.PluginDirectory = plugin.PluginDirectory; + o.PluginID = plugin.ID; + o.OriginQuery = query; + }); + Task.Run(() => + { + _mainVM.UpdateResultView(results, plugin, query); + }); + } + + #endregion + + #region Private Methods + + private bool KListener_hookedKeyboardCallback(KeyEvent keyevent, int vkcode, SpecialKeyState state) + { + if (GlobalKeyboardEvent != null) + { + return GlobalKeyboardEvent((int)keyevent, vkcode, state); + } + return true; + } + #endregion + } +} diff --git a/src/modules/launcher/Wox/ReportWindow.xaml b/src/modules/launcher/Wox/ReportWindow.xaml new file mode 100644 index 000000000..fd53b0182 --- /dev/null +++ b/src/modules/launcher/Wox/ReportWindow.xaml @@ -0,0 +1,23 @@ + + + + diff --git a/src/modules/launcher/Wox/ReportWindow.xaml.cs b/src/modules/launcher/Wox/ReportWindow.xaml.cs new file mode 100644 index 000000000..ac7e986fd --- /dev/null +++ b/src/modules/launcher/Wox/ReportWindow.xaml.cs @@ -0,0 +1,64 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Text; +using System.Linq; +using System.Windows; +using System.Windows.Documents; +using Wox.Helper; +using Wox.Infrastructure; +using Wox.Infrastructure.Logger; + +namespace Wox +{ + internal partial class ReportWindow + { + public ReportWindow(Exception exception) + { + InitializeComponent(); + ErrorTextbox.Document.Blocks.FirstBlock.Margin = new Thickness(0); + SetException(exception); + } + + private void SetException(Exception exception) + { + string path = Log.CurrentLogDirectory; + var directory = new DirectoryInfo(path); + var log = directory.GetFiles().OrderByDescending(f => f.LastWriteTime).First(); + + var paragraph = Hyperlink("Please open new issue in: ", Constant.Issue); + paragraph.Inlines.Add($"1. upload log file: {log.FullName}\n"); + paragraph.Inlines.Add($"2. copy below exception message"); + ErrorTextbox.Document.Blocks.Add(paragraph); + + StringBuilder content = new StringBuilder(); + content.AppendLine(ErrorReporting.RuntimeInfo()); + content.AppendLine(ErrorReporting.DependenciesInfo()); + content.AppendLine($"Date: {DateTime.Now.ToString(CultureInfo.InvariantCulture)}"); + content.AppendLine("Exception:"); + content.AppendLine(exception.ToString()); + paragraph = new Paragraph(); + paragraph.Inlines.Add(content.ToString()); + ErrorTextbox.Document.Blocks.Add(paragraph); + } + + private Paragraph Hyperlink(string textBeforeUrl, string url) + { + var paragraph = new Paragraph(); + paragraph.Margin = new Thickness(0); + + var link = new Hyperlink { IsEnabled = true }; + link.Inlines.Add(url); + link.NavigateUri = new Uri(url); + link.RequestNavigate += (s, e) => Process.Start(e.Uri.ToString()); + link.Click += (s, e) => Process.Start(url); + + paragraph.Inlines.Add(textBeforeUrl); + paragraph.Inlines.Add(link); + paragraph.Inlines.Add("\n"); + + return paragraph; + } + } +} diff --git a/src/modules/launcher/Wox/Resources/app.ico b/src/modules/launcher/Wox/Resources/app.ico new file mode 100644 index 000000000..38c401c8c Binary files /dev/null and b/src/modules/launcher/Wox/Resources/app.ico differ diff --git a/src/modules/launcher/Wox/ResultListBox.xaml b/src/modules/launcher/Wox/ResultListBox.xaml new file mode 100644 index 000000000..dc3100e0e --- /dev/null +++ b/src/modules/launcher/Wox/ResultListBox.xaml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/launcher/Wox/ResultListBox.xaml.cs b/src/modules/launcher/Wox/ResultListBox.xaml.cs new file mode 100644 index 000000000..d448d02ca --- /dev/null +++ b/src/modules/launcher/Wox/ResultListBox.xaml.cs @@ -0,0 +1,50 @@ +using System.Runtime.Remoting.Contexts; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; + +namespace Wox +{ + [Synchronization] + public partial class ResultListBox + { + private Point _lastpos; + private ListBoxItem curItem = null; + public ResultListBox() + { + InitializeComponent(); + } + + private void OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (e.AddedItems.Count > 0 && e.AddedItems[0] != null) + { + ScrollIntoView(e.AddedItems[0]); + } + } + + private void OnMouseEnter(object sender, MouseEventArgs e) + { + curItem = (ListBoxItem)sender; + var p = e.GetPosition((IInputElement)sender); + _lastpos = p; + } + + private void OnMouseMove(object sender, MouseEventArgs e) + { + var p = e.GetPosition((IInputElement)sender); + if (_lastpos != p) + { + ((ListBoxItem) sender).IsSelected = true; + } + } + + private void ListBox_PreviewMouseDown(object sender, MouseButtonEventArgs e) + { + if (curItem != null) + { + curItem.IsSelected = true; + } + } + } +} diff --git a/src/modules/launcher/Wox/SettingWindow.xaml b/src/modules/launcher/Wox/SettingWindow.xaml new file mode 100644 index 000000000..1eddd8ab6 --- /dev/null +++ b/src/modules/launcher/Wox/SettingWindow.xaml @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +