Add QueryHistory to Wox (Ctrl+Up and Ctrl+Down)

This commit is contained in:
qianlifeng
2015-02-09 19:16:13 +08:00
parent b8f829dbc3
commit a942882c73
12 changed files with 232 additions and 94 deletions

View File

@@ -34,8 +34,6 @@ namespace Wox.Plugin.QueryHistory
public void Init(PluginInitContext context) public void Init(PluginInitContext context)
{ {
this.context = context; this.context = context;
context.API.AfterWoxQueryEvent += API_AfterWoxQueryEvent;
context.API.BeforeWoxQueryEvent += API_BeforeWoxQueryEvent;
} }
void API_BeforeWoxQueryEvent(WoxQueryEventArgs e) void API_BeforeWoxQueryEvent(WoxQueryEventArgs e)

View File

@@ -55,13 +55,18 @@ namespace Wox.CrashReporter
private void SendReport() private void SendReport()
{ {
string reproduceSteps = ThreadPool.QueueUserWorkItem(o =>
new TextRange(tbReproduceSteps.Document.ContentStart, tbReproduceSteps.Document.ContentEnd).Text; {
exception.ToExceptionless() string reproduceSteps = new TextRange(tbReproduceSteps.Document.ContentStart, tbReproduceSteps.Document.ContentEnd).Text;
.SetUserDescription(reproduceSteps) exception.ToExceptionless()
.Submit(); .SetUserDescription(reproduceSteps)
ExceptionlessClient.Current.ProcessQueue(); .Submit();
Close(); ExceptionlessClient.Current.ProcessQueue();
Dispatcher.Invoke(new Action(() =>
{
Close();
}));
});
} }
private void btnCancel_Click(object sender, RoutedEventArgs e) private void btnCancel_Click(object sender, RoutedEventArgs e)

View File

@@ -46,7 +46,7 @@ namespace Wox.Plugin
/// Just change the query text, this won't raise search /// Just change the query text, this won't raise search
/// </summary> /// </summary>
/// <param name="query"></param> /// <param name="query"></param>
void ChangeQueryText(string query); void ChangeQueryText(string query, bool selectAll = false);
/// <summary> /// <summary>
/// Close Wox /// Close Wox
@@ -122,16 +122,6 @@ namespace Wox.Plugin
/// </summary> /// </summary>
event WoxGlobalKeyboardEventHandler GlobalKeyboardEvent; event WoxGlobalKeyboardEventHandler GlobalKeyboardEvent;
/// <summary>
/// Fired after wox execute a query
/// </summary>
event AfterWoxQueryEventHandler AfterWoxQueryEvent;
/// <summary>
/// Fired before wox start to execute a query
/// </summary>
event AfterWoxQueryEventHandler BeforeWoxQueryEvent;
/// <summary> /// <summary>
/// Fired after drop to result item of current plugin /// Fired after drop to result item of current plugin
/// </summary> /// </summary>

View File

@@ -39,8 +39,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin.Color", "Plugins
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.CrashReporter", "Wox.CrashReporter\Wox.CrashReporter.csproj", "{2FEB2298-7653-4009-B1EA-FFFB1A768BCC}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.CrashReporter", "Wox.CrashReporter\Wox.CrashReporter.csproj", "{2FEB2298-7653-4009-B1EA-FFFB1A768BCC}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin.QueryHistory", "Plugins\Wox.Plugin.QueryHistory\Wox.Plugin.QueryHistory.csproj", "{B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.UpdateFeedGenerator", "Wox.UpdateFeedGenerator\Wox.UpdateFeedGenerator.csproj", "{D120E62B-EC59-4FB4-8129-EFDD4C446A5F}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.UpdateFeedGenerator", "Wox.UpdateFeedGenerator\Wox.UpdateFeedGenerator.csproj", "{D120E62B-EC59-4FB4-8129-EFDD4C446A5F}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin.Everything", "Plugins\Wox.Plugin.Everything\Wox.Plugin.Everything.csproj", "{230AE83F-E92E-4E69-8355-426B305DA9C0}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin.Everything", "Plugins\Wox.Plugin.Everything\Wox.Plugin.Everything.csproj", "{230AE83F-E92E-4E69-8355-426B305DA9C0}"
@@ -119,10 +117,6 @@ Global
{2FEB2298-7653-4009-B1EA-FFFB1A768BCC}.Debug|Any CPU.Build.0 = Debug|Any CPU {2FEB2298-7653-4009-B1EA-FFFB1A768BCC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2FEB2298-7653-4009-B1EA-FFFB1A768BCC}.Release|Any CPU.ActiveCfg = Release|Any CPU {2FEB2298-7653-4009-B1EA-FFFB1A768BCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2FEB2298-7653-4009-B1EA-FFFB1A768BCC}.Release|Any CPU.Build.0 = Release|Any CPU {2FEB2298-7653-4009-B1EA-FFFB1A768BCC}.Release|Any CPU.Build.0 = Release|Any CPU
{B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0}.Release|Any CPU.Build.0 = Release|Any CPU
{D120E62B-EC59-4FB4-8129-EFDD4C446A5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D120E62B-EC59-4FB4-8129-EFDD4C446A5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D120E62B-EC59-4FB4-8129-EFDD4C446A5F}.Debug|Any CPU.Build.0 = Debug|Any CPU {D120E62B-EC59-4FB4-8129-EFDD4C446A5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D120E62B-EC59-4FB4-8129-EFDD4C446A5F}.Release|Any CPU.ActiveCfg = Release|Any CPU {D120E62B-EC59-4FB4-8129-EFDD4C446A5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -147,7 +141,6 @@ Global
{0B9DE348-9361-4940-ADB6-F5953BFFCCEC} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {0B9DE348-9361-4940-ADB6-F5953BFFCCEC} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
{A3DCCBCA-ACC1-421D-B16E-210896234C26} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {A3DCCBCA-ACC1-421D-B16E-210896234C26} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
{F35190AA-4758-4D9E-A193-E3BDF6AD3567} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {F35190AA-4758-4D9E-A193-E3BDF6AD3567} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
{B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
{230AE83F-E92E-4E69-8355-426B305DA9C0} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {230AE83F-E92E-4E69-8355-426B305DA9C0} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@@ -1,8 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<configuration> <configuration>
<configSections>
<section name="exceptionless" type="Exceptionless.Configuration.ExceptionlessSection, Exceptionless" />
</configSections>
<runtime> <runtime>
<!--http://stackoverflow.com/questions/186854/how-to-prevent-an-exception-in-a-background-thread-from-terminating-an-application--> <!--http://stackoverflow.com/questions/186854/how-to-prevent-an-exception-in-a-background-thread-from-terminating-an-application-->
<!--prevent non-ui exception crash wox--> <!--prevent non-ui exception crash wox-->
@@ -12,5 +9,4 @@
<supportedRuntime version="v2.0.50727" /> <supportedRuntime version="v2.0.50727" />
<supportedRuntime version="v4.0" /> <supportedRuntime version="v4.0" />
</startup> </startup>
<exceptionless apiKey="API_KEY_HERE" />
</configuration> </configuration>

BIN
Wox/Images/history.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -68,13 +68,17 @@ namespace Wox
})); }));
} }
public void ChangeQueryText(string query) public void ChangeQueryText(string query, bool selectAll = false)
{ {
Dispatcher.Invoke(new Action(() => Dispatcher.Invoke(new Action(() =>
{ {
ignoreTextChange = true; ignoreTextChange = true;
tbQuery.Text = query; tbQuery.Text = query;
tbQuery.CaretIndex = tbQuery.Text.Length; tbQuery.CaretIndex = tbQuery.Text.Length;
if (selectAll)
{
tbQuery.SelectAll();
}
})); }));
} }
@@ -144,8 +148,6 @@ namespace Wox
public event WoxKeyDownEventHandler BackKeyDownEvent; public event WoxKeyDownEventHandler BackKeyDownEvent;
public event WoxGlobalKeyboardEventHandler GlobalKeyboardEvent; public event WoxGlobalKeyboardEventHandler GlobalKeyboardEvent;
public event AfterWoxQueryEventHandler AfterWoxQueryEvent;
public event AfterWoxQueryEventHandler BeforeWoxQueryEvent;
public event ResultItemDropEventHandler ResultItemDropEvent; public event ResultItemDropEventHandler ResultItemDropEvent;
public void PushResults(Query query, PluginMetadata plugin, List<Result> results) public void PushResults(Query query, PluginMetadata plugin, List<Result> results)
@@ -433,7 +435,6 @@ namespace Wox
queryHasReturn = false; queryHasReturn = false;
Query query = new Query(lastQuery); Query query = new Query(lastQuery);
query.IsIntantQuery = searchDelay == 0; query.IsIntantQuery = searchDelay == 0;
FireBeforeWoxQueryEvent(query);
Query(query); Query(query);
Dispatcher.DelayInvoke("ShowProgressbar", originQuery => Dispatcher.DelayInvoke("ShowProgressbar", originQuery =>
{ {
@@ -442,10 +443,15 @@ namespace Wox
StartProgress(); StartProgress();
} }
}, TimeSpan.FromMilliseconds(150), tbQuery.Text); }, TimeSpan.FromMilliseconds(150), tbQuery.Text);
FireAfterWoxQueryEvent(query); //reset query history index after user start new query
ResetQueryHistoryIndex();
}, TimeSpan.FromMilliseconds(searchDelay)); }, TimeSpan.FromMilliseconds(searchDelay));
} }
private void ResetQueryHistoryIndex()
{
QueryHistoryStorage.Instance.Reset();
}
private int GetSearchDelay(string query) private int GetSearchDelay(string query)
{ {
if (!string.IsNullOrEmpty(query) && PluginManager.IsInstantQuery(query)) if (!string.IsNullOrEmpty(query) && PluginManager.IsInstantQuery(query))
@@ -458,38 +464,6 @@ namespace Wox
return 200; return 200;
} }
private void FireAfterWoxQueryEvent(Query q)
{
if (AfterWoxQueryEvent != null)
{
//We shouldn't let those events slow down real query
//so I put it in the new thread
ThreadPool.QueueUserWorkItem(o =>
{
AfterWoxQueryEvent(new WoxQueryEventArgs()
{
Query = q
});
});
}
}
private void FireBeforeWoxQueryEvent(Query q)
{
if (BeforeWoxQueryEvent != null)
{
//We shouldn't let those events slow down real query
//so I put it in the new thread
ThreadPool.QueueUserWorkItem(o =>
{
BeforeWoxQueryEvent(new WoxQueryEventArgs()
{
Query = q
});
});
}
}
private void Query(Query q) private void Query(Query q)
{ {
PluginManager.Query(q); PluginManager.Query(q);
@@ -544,6 +518,7 @@ namespace Wox
Activate(); Activate();
Focus(); Focus();
tbQuery.Focus(); tbQuery.Focus();
ResetQueryHistoryIndex();
if (selectAll) tbQuery.SelectAll(); if (selectAll) tbQuery.SelectAll();
} }
@@ -616,12 +591,26 @@ namespace Wox
break; break;
case Key.Down: case Key.Down:
SelectNextItem(); if (GlobalHotkey.Instance.CheckModifiers().CtrlPressed)
{
DisplayNextQuery();
}
else
{
SelectNextItem();
}
e.Handled = true; e.Handled = true;
break; break;
case Key.Up: case Key.Up:
SelectPrevItem(); if (GlobalHotkey.Instance.CheckModifiers().CtrlPressed)
{
DisplayPrevQuery();
}
else
{
SelectPrevItem();
}
e.Handled = true; e.Handled = true;
break; break;
@@ -703,6 +692,40 @@ namespace Wox
} }
} }
private void DisplayPrevQuery()
{
var prev = QueryHistoryStorage.Instance.Previous();
DisplayQueryHistory(prev);
}
private void DisplayNextQuery()
{
var nextQuery = QueryHistoryStorage.Instance.Next();
DisplayQueryHistory(nextQuery);
}
private void DisplayQueryHistory(HistoryItem history)
{
if (history != null)
{
ChangeQueryText(history.Query, true);
pnlResult.Dirty = true;
UpdateResultViewInternal(new List<Result>()
{
new Result(){
Title = "Execute " + history.Query+ " query",
SubTitle = "Last Execute Time: " + history.ExecutedDateTime,
IcoPath = "Images\\history.png",
PluginDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
Action = _ =>{
ChangeQuery(history.Query,true);
return false;
}
}
});
}
}
private void SelectItem(int index) private void SelectItem(int index)
{ {
int zeroBasedIndex = index - 1; int zeroBasedIndex = index - 1;
@@ -775,6 +798,7 @@ namespace Wox
HideWox(); HideWox();
} }
UserSelectedRecordStorage.Instance.Add(result); UserSelectedRecordStorage.Instance.Add(result);
QueryHistoryStorage.Instance.Add(tbQuery.Text);
} }
} }
} }
@@ -792,13 +816,18 @@ namespace Wox
o.Score += UserSelectedRecordStorage.Instance.GetSelectedCount(o) * 5; o.Score += UserSelectedRecordStorage.Instance.GetSelectedCount(o) * 5;
}); });
List<Result> l = list.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == lastQuery).ToList(); List<Result> l = list.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == lastQuery).ToList();
Dispatcher.Invoke(new Action(() => UpdateResultViewInternal(l);
{
pnlResult.AddResults(l);
}));
} }
} }
private void UpdateResultViewInternal(List<Result> list)
{
Dispatcher.Invoke(new Action(() =>
{
pnlResult.AddResults(list);
}));
}
private Result GetTopMostContextMenu(Result result) private Result GetTopMostContextMenu(Result result)
{ {
if (TopMostRecordStorage.Instance.IsTopMost(result)) if (TopMostRecordStorage.Instance.IsTopMost(result))

View File

@@ -20,4 +20,4 @@ using System.Windows;
)] )]
[assembly: AssemblyVersion("1.1.0")] [assembly: AssemblyVersion("1.1.0")]
[assembly: AssemblyFileVersion("1.1.0")] [assembly: AssemblyFileVersion("1.1.0")]
[assembly: Exceptionless.Configuration.Exceptionless("13462a93b5e843c7bae7da13a86bc00b", EnableLogging = true, LogPath = "E:\\exceptionless.log")] [assembly: Exceptionless.Configuration.Exceptionless("e0b256fbe9384498ba89aae2a6b7f8ab")]

View File

@@ -24,7 +24,7 @@
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="32"></ColumnDefinition> <ColumnDefinition Width="32"></ColumnDefinition>
<ColumnDefinition/> <ColumnDefinition/>
<ColumnDefinition Width="32" /> <ColumnDefinition Width="0" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Image x:Name="imgIco" Width="32" Height="32" HorizontalAlignment="Left" Source="{Binding FullIcoPath,Converter={StaticResource ImageConverter},IsAsync=True}" > <Image x:Name="imgIco" Width="32" Height="32" HorizontalAlignment="Left" Source="{Binding FullIcoPath,Converter={StaticResource ImageConverter},IsAsync=True}" >
</Image> </Image>

View File

@@ -145,26 +145,25 @@ namespace Wox
private void UpdateItemNumber() private void UpdateItemNumber()
{ {
VirtualizingStackPanel virtualizingStackPanel = GetInnerStackPanel(lbResults); //VirtualizingStackPanel virtualizingStackPanel = GetInnerStackPanel(lbResults);
int index = 0; //int index = 0;
for (int i = (int)virtualizingStackPanel.VerticalOffset; i <= virtualizingStackPanel.VerticalOffset + virtualizingStackPanel.ViewportHeight; i++) //for (int i = (int)virtualizingStackPanel.VerticalOffset; i <= virtualizingStackPanel.VerticalOffset + virtualizingStackPanel.ViewportHeight; i++)
{ //{
index++; // index++;
ListBoxItem item = lbResults.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem; // ListBoxItem item = lbResults.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem;
if (item != null) // if (item != null)
{ // {
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(item); // ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(item);
if (myContentPresenter != null) // if (myContentPresenter != null)
{ // {
DataTemplate dataTemplate = myContentPresenter.ContentTemplate; // DataTemplate dataTemplate = myContentPresenter.ContentTemplate;
TextBlock tbItemNumber = (TextBlock)dataTemplate.FindName("tbItemNumber", myContentPresenter); // TextBlock tbItemNumber = (TextBlock)dataTemplate.FindName("tbItemNumber", myContentPresenter);
tbItemNumber.Text = index.ToString(); // tbItemNumber.Text = index.ToString();
} // }
} // }
} //}
} }
private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
{ {
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)

View File

@@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
using Wox.Infrastructure.Storage;
namespace Wox.Storage
{
public class QueryHistoryStorage : JsonStrorage<QueryHistoryStorage>
{
[JsonProperty]
private List<HistoryItem> History = new List<HistoryItem>();
private int MaxHistory = 300;
private int cursor = 0;
protected override string ConfigFolder
{
get { return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Config"); }
}
protected override string ConfigName
{
get { return "QueryHistory"; }
}
public HistoryItem Previous()
{
if (History.Count == 0 || cursor == 0) return null;
return History[--cursor];
}
public HistoryItem Next()
{
if (History.Count == 0 || cursor >= History.Count - 1) return null;
return History[++cursor];
}
public void Reset()
{
cursor = History.Count;
}
public void Add(string query)
{
if (string.IsNullOrEmpty(query)) return;
if (History.Count > MaxHistory)
{
History.RemoveAt(0);
}
if (History.Count > 0 && History.Last().Query == query)
{
History.Last().ExecutedDateTime = DateTime.Now;
}
else
{
History.Add(new HistoryItem()
{
Query = query,
ExecutedDateTime = DateTime.Now
});
}
if (History.Count % 5 == 0)
{
Save();
}
Reset();
}
public List<HistoryItem> GetHistory()
{
return History.OrderByDescending(o => o.ExecutedDateTime).ToList();
}
}
public class HistoryItem
{
public string Query { get; set; }
public DateTime ExecutedDateTime { get; set; }
public string GetTimeAgo()
{
return DateTimeAgo(ExecutedDateTime);
}
private string DateTimeAgo(DateTime dt)
{
TimeSpan span = DateTime.Now - dt;
if (span.Days > 365)
{
int years = (span.Days / 365);
if (span.Days % 365 != 0)
years += 1;
return String.Format("about {0} {1} ago",
years, years == 1 ? "year" : "years");
}
if (span.Days > 30)
{
int months = (span.Days / 30);
if (span.Days % 31 != 0)
months += 1;
return String.Format("about {0} {1} ago",
months, months == 1 ? "month" : "months");
}
if (span.Days > 0)
return String.Format("about {0} {1} ago",
span.Days, span.Days == 1 ? "day" : "days");
if (span.Hours > 0)
return String.Format("about {0} {1} ago",
span.Hours, span.Hours == 1 ? "hour" : "hours");
if (span.Minutes > 0)
return String.Format("about {0} {1} ago",
span.Minutes, span.Minutes == 1 ? "minute" : "minutes");
if (span.Seconds > 5)
return String.Format("about {0} seconds ago", span.Seconds);
if (span.Seconds <= 5)
return "just now";
return string.Empty;
}
}
}

View File

@@ -123,6 +123,7 @@
<Compile Include="Converters\StringEmptyConverter.cs" /> <Compile Include="Converters\StringEmptyConverter.cs" />
<Compile Include="Converters\StringNullOrEmptyToVisibilityConverter.cs" /> <Compile Include="Converters\StringNullOrEmptyToVisibilityConverter.cs" />
<Compile Include="ImageLoader\ImageCacheStroage.cs" /> <Compile Include="ImageLoader\ImageCacheStroage.cs" />
<Compile Include="Storage\QueryHistoryStorage.cs" />
<Compile Include="Storage\TopMostRecordStorage.cs" /> <Compile Include="Storage\TopMostRecordStorage.cs" />
<Compile Include="Storage\UserSelectedRecordStorage.cs" /> <Compile Include="Storage\UserSelectedRecordStorage.cs" />
<Compile Include="WoxUpdate.xaml.cs"> <Compile Include="WoxUpdate.xaml.cs">
@@ -194,6 +195,7 @@
<None Include="Images\down.png"> <None Include="Images\down.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<Resource Include="Images\history.png" />
<Content Include="Languages\en.xaml"> <Content Include="Languages\en.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>