diff --git a/TextLocator/AreaEditWindow.xaml b/TextLocator/AreaEditWindow.xaml
new file mode 100644
index 0000000000000000000000000000000000000000..f9830513714bf23b758fcc9ac7f0be37b28a5e88
--- /dev/null
+++ b/TextLocator/AreaEditWindow.xaml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TextLocator/AreaEditWindow.xaml.cs b/TextLocator/AreaEditWindow.xaml.cs
new file mode 100644
index 0000000000000000000000000000000000000000..26fa9e44493db6763db686ea1bbd3a2a23c7abd1
--- /dev/null
+++ b/TextLocator/AreaEditWindow.xaml.cs
@@ -0,0 +1,282 @@
+using log4net;
+using System;
+using System.Collections.Generic;
+using System.Windows;
+using System.Windows.Controls;
+using TextLocator.Entity;
+using TextLocator.Enums;
+using TextLocator.Message;
+using TextLocator.Util;
+
+namespace TextLocator
+{
+ ///
+ /// AreaEditWindow.xaml 的交互逻辑
+ ///
+ public partial class AreaEditWindow : Window
+ {
+ private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+
+ ///
+ /// 搜索区文件夹
+ ///
+ private List _areaFolders = new List();
+ ///
+ /// 搜索区文件类型
+ ///
+ private List _areaFileTypes = new List();
+ ///
+ /// 区域信息
+ ///
+ private AreaInfo _areaInfo;
+
+ ///
+ /// 构造函数
+ ///
+ /// 区域信息对象
+ public AreaEditWindow(AreaInfo areaInfo = null)
+ {
+ InitializeComponent();
+ _areaInfo = areaInfo;
+
+ if (_areaInfo == null)
+ {
+ _areaInfo = new AreaInfo()
+ {
+ AreaId = "Area" + DateTime.Now.ToString("yyyyMMddHHmmssffff"),
+ AreaFileTypes = FileTypeUtil.GetFileTypesNotAll()
+ };
+ }
+ }
+
+ ///
+ /// 加载完毕
+ ///
+ ///
+ ///
+ private void Window_Loaded(object sender, RoutedEventArgs e)
+ {
+ // 初始化加载文件类型
+ LoadFileType();
+
+ // 加载区域信息
+ LoadAreaInfo();
+ }
+
+ ///
+ /// 加载区域信息
+ ///
+ private void LoadAreaInfo()
+ {
+ // 区域名称
+ this.AreaName.Text = _areaInfo.AreaName;
+ // 区域文件夹
+ this.AreaFolders.Items.Clear();
+ if (_areaInfo.AreaFolders != null)
+ {
+ FolderInfoItem folder;
+ foreach (string folderPath in _areaInfo.AreaFolders)
+ {
+ _areaFolders.Add(folderPath);
+
+ folder = new FolderInfoItem(folderPath);
+ folder.DelButton.Click += DelButton_Click; ;
+ folder.DelButton.Tag = folderPath;
+ this.AreaFolders.Items.Add(folder);
+ }
+ }
+ // 区域文件夹类型
+ foreach (UIElement element in this.AreaFileTypes.Children)
+ {
+ CheckBox checkbox = element as CheckBox;
+ if (_areaInfo.AreaFileTypes.Contains((FileType)checkbox.Tag))
+ {
+ checkbox.IsChecked = true;
+ }
+ }
+ }
+
+ ///
+ /// 初始化加载文件类型
+ ///
+ private void LoadFileType()
+ {
+ this.AreaFileTypes.Children.Clear();
+ // 遍历文件类型枚举
+ foreach (FileType fileType in FileTypeUtil.GetFileTypesNotAll())
+ {
+ // 构造UI元素
+ CheckBox checkbox = new CheckBox()
+ {
+ Name = "FileType_" + (int)fileType,
+ Margin = new Thickness(10),
+ Tag = fileType,
+ Content = fileType.ToString() + "(" + fileType.GetDescription() + ")"
+ };
+ checkbox.Checked += FileTypeStatusChange;
+ checkbox.Unchecked += FileTypeStatusChange;
+ this.AreaFileTypes.Children.Add(checkbox);
+ }
+ }
+
+ ///
+ /// 文件类型选中状态切换
+ ///
+ ///
+ ///
+ private void FileTypeStatusChange(object sender, RoutedEventArgs e)
+ {
+ List fileTypes = new List();
+ foreach(UIElement element in this.AreaFileTypes.Children)
+ {
+ CheckBox checkBox = element as CheckBox;
+ if (checkBox.IsChecked == true)
+ {
+ fileTypes.Add((Enums.FileType)System.Enum.Parse(typeof(Enums.FileType), checkBox.Tag.ToString()));
+ }
+ }
+ _areaFileTypes = fileTypes;
+ }
+
+ ///
+ /// 删除文件夹
+ ///
+ ///
+ ///
+ private void DelButton_Click(object sender, RoutedEventArgs e)
+ {
+ // 当前删除文件夹路径
+ string deleteFolderPath = (sender as Button).Tag + "";
+ // UI层删除
+ for (int i = 0; i < this.AreaFolders.Items.Count; i++)
+ {
+ if ((this.AreaFolders.Items[i] as FolderInfoItem).FolderPath.Text.Equals(deleteFolderPath))
+ {
+ this.AreaFolders.Items.RemoveAt(i);
+ break;
+ }
+ }
+ // 缓存列表层删除
+ for (int i = 0; i < _areaFolders.Count; i++)
+ {
+ if (_areaFolders[i].Equals(deleteFolderPath))
+ {
+ _areaFolders.RemoveAt(i);
+ break;
+ }
+ }
+ }
+
+ ///
+ /// 添加文件夹
+ ///
+ ///
+ ///
+ private void AddButton_Click(object sender, RoutedEventArgs e)
+ {
+ System.Windows.Forms.FolderBrowserDialog browserDialog = new System.Windows.Forms.FolderBrowserDialog();
+ if (browserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
+ {
+ string folderPath = browserDialog.SelectedPath;
+
+ // 判断是否已选过
+ if (_areaFolders.Contains(folderPath))
+ {
+ MessageCore.ShowWarning("选定目录已存在");
+ return;
+ }
+
+ // 判断文件夹是否存在于其他区域中
+ if (AreaUtil.GetAreaFolderList().Contains(folderPath))
+ {
+ MessageCore.ShowWarning("该文件夹已存在于其他区域");
+ return;
+ }
+
+ // 加入列表
+ FolderInfoItem folder = new FolderInfoItem(folderPath);
+ folder.DelButton.Click += DelButton_Click;
+ folder.DelButton.Tag = folderPath;
+
+ this.AreaFolders.Items.Add(folder);
+
+ _areaFolders.Add(folderPath);
+ }
+ }
+
+ ///
+ /// 保存
+ ///
+ ///
+ ///
+ private void SaveButton_Click(object sender, RoutedEventArgs e)
+ {
+ string areaName = this.AreaName.Text.Trim();
+
+ if (string.IsNullOrEmpty(areaName))
+ {
+ MessageCore.ShowWarning("区域名称为空");
+ return;
+ }
+ if (AreaUtil.GetAreaNameListRuleOut(_areaInfo).Contains(areaName))
+ {
+ MessageCore.ShowWarning("区域名称不能重复");
+ return;
+ }
+ if (this.AreaFolders.Items.Count <= 0)
+ {
+ MessageCore.ShowWarning("至少需要一个文件夹");
+ return;
+ }
+ if (_areaFileTypes.Count <= 0)
+ {
+ MessageCore.ShowWarning("至少需要一个支持的文件类型");
+ return;
+ }
+
+ // 搜索区名称
+ _areaInfo.AreaName = areaName;
+ // 搜索区文件夹
+ _areaInfo.AreaFolders = _areaFolders;
+ // 搜索区文件类型
+ _areaInfo.AreaFileTypes = _areaFileTypes;
+
+ // 保存区域信息
+ // AreaUtil.SaveAreaInfo(_areaInfo);
+ List areaInfos = CacheUtil.Get>("AreaInfos");
+ if (areaInfos.Contains(_areaInfo))
+ {
+ for (int i = 0; i < areaInfos.Count; i++)
+ {
+ AreaInfo areaInfo = areaInfos[i];
+ if (_areaInfo.AreaId == areaInfo.AreaId)
+ {
+ areaInfos[i] = _areaInfo;
+ }
+ break;
+ }
+ }
+ else
+ {
+ areaInfos.Add(_areaInfo);
+ }
+
+ CacheUtil.Put("AreaInfos", areaInfos);
+
+ // 返回
+ this.DialogResult = true;
+ this.Close();
+ }
+
+ ///
+ /// 退出
+ ///
+ ///
+ ///
+ private void ExitButton_Click(object sender, RoutedEventArgs e)
+ {
+ this.DialogResult = false;
+ this.Close();
+ }
+ }
+}
diff --git a/TextLocator/AreaInfoItem.xaml b/TextLocator/AreaInfoItem.xaml
new file mode 100644
index 0000000000000000000000000000000000000000..d83e250b8cb4ac560737cac4fbf680673df17f62
--- /dev/null
+++ b/TextLocator/AreaInfoItem.xaml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TextLocator/AreaInfoItem.xaml.cs b/TextLocator/AreaInfoItem.xaml.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1d89946268af0c1d5576cfba054ce9e1f32afe58
--- /dev/null
+++ b/TextLocator/AreaInfoItem.xaml.cs
@@ -0,0 +1,63 @@
+using log4net;
+using System;
+using System.Windows.Controls;
+using TextLocator.Entity;
+
+namespace TextLocator
+{
+ ///
+ /// AreaInfoItem.xaml 的交互逻辑
+ ///
+ public partial class AreaInfoItem : UserControl
+ {
+ private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+
+ public AreaInfoItem(AreaInfo areaInfo)
+ {
+ InitializeComponent();
+
+ try
+ {
+ Refresh(areaInfo);
+ }
+ catch
+ {
+ this.Dispatcher.BeginInvoke(new Action(() =>
+ {
+ try
+ {
+ Refresh(areaInfo);
+ }
+ catch (Exception ex)
+ {
+ log.Error(ex.Message, ex);
+ }
+ }));
+ }
+ }
+
+ ///
+ /// 刷新数据
+ ///
+ /// 区域信息
+ public void Refresh(AreaInfo areaInfo)
+ {
+ // 是否启用
+ this.AreaIsEnable.IsChecked = areaInfo.IsEnable;
+ // 区域名称
+ this.AreaName.Text = areaInfo.AreaName;
+ // 区域文件夹
+ this.AreaFolders.Children.Clear();
+ if (areaInfo.AreaFolders != null)
+ {
+ foreach (string path in areaInfo.AreaFolders)
+ {
+ TextBlock text = new TextBlock() { Text = path };
+ this.AreaFolders.Children.Add(text);
+ }
+ }
+ // 区域文件类型
+ this.AreaFileTypes.Text = string.Join(",", areaInfo.AreaFileTypes.ToArray());
+ }
+ }
+}
diff --git a/TextLocator/AreaWindow.xaml b/TextLocator/AreaWindow.xaml
index e586c24a5c849549ec7944f3e8ccc16839b90e5c..c8d945f2739a16e30cb563e9d86a43de631ee3f4 100644
--- a/TextLocator/AreaWindow.xaml
+++ b/TextLocator/AreaWindow.xaml
@@ -5,45 +5,63 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TextLocator"
mc:Ignorable="d"
- Title="区域设置" Height="540" Width="960" WindowStartupLocation="CenterOwner" WindowStyle="ToolWindow" ResizeMode="CanMinimize" Icon="/Resource/App.ico" Loaded="Window_Loaded" >
-
-
-
-
-
-
-
-
-
-
-
-
+ Title="区域设置" Height="465" Width="830" WindowStartupLocation="CenterOwner" WindowStyle="ToolWindow" ResizeMode="CanMinimize" Icon="/Resource/App.ico" Loaded="Window_Loaded" >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
+
+
+
+
diff --git a/TextLocator/AreaWindow.xaml.cs b/TextLocator/AreaWindow.xaml.cs
index a3daee0a03bf298a4af39300af33d2f49c6a555c..6cfc8fa173edcc5f5657bad25b400df664d53eeb 100644
--- a/TextLocator/AreaWindow.xaml.cs
+++ b/TextLocator/AreaWindow.xaml.cs
@@ -1,9 +1,11 @@
-using Rubyer;
+using log4net;
using System;
using System.Collections.Generic;
+using System.IO;
using System.Windows;
using System.Windows.Controls;
-using System.Windows.Media;
+using TextLocator.Core;
+using TextLocator.Entity;
using TextLocator.Message;
using TextLocator.Util;
@@ -14,208 +16,250 @@ namespace TextLocator
///
public partial class AreaWindow : Window
{
+ private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+
///
- /// 索引区文件夹
+ /// 正常区域列表区域信息列表
///
- private List _indexFolder = new List();
+ private List _normalAreaInfos = new List();
///
- /// 排除区文件夹
+ /// 删除区域信息列表
///
- private List _exclusionFolder = new List();
+ private List _deleteAreaInfos = new List();
public AreaWindow()
{
InitializeComponent();
}
+ ///
+ /// 加载完毕
+ ///
+ ///
+ ///
private void Window_Loaded(object sender, RoutedEventArgs e)
{
- // 获取搜索文件夹
- string folderPaths = AppUtil.ReadValue("AppConfig", "FolderPaths", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "," + Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
- // 清空
- this.FolderList.Items.Clear();
- if (!string.IsNullOrEmpty(folderPaths))
- {
- FolderInfoItem folder;
- foreach (string folderPath in folderPaths.Split(','))
- {
- folder = new FolderInfoItem(folderPath);
- folder.DeleteButton.Click += DeleteButton_Click;
- folder.DeleteButton.Tag = folderPath;
-
- this.FolderList.Items.Add(folder);
+ // 加载区域信息列表
+ LoadAreaInfoList();
+ }
- _indexFolder.Add(folderPath);
- }
+ ///
+ /// 加载区域信息列表
+ /// 区域信息列表
+ ///
+ private void LoadAreaInfoList(List areaInfos = null)
+ {
+ // 外部传入区域信息列表为空
+ if (areaInfos == null)
+ {
+ // 重新获取新的列表
+ areaInfos = AreaUtil.GetAreaInfoList();
}
- // 获取排除文件夹
- string exclusionPaths = AppUtil.ReadValue("AppConfig", "ExclusionPaths", "");
- // 清空
- this.ExclusionList.Items.Clear();
- if(!string.IsNullOrEmpty(exclusionPaths))
+ if (areaInfos != null)
{
- FolderInfoItem exclusion;
- foreach (string folderPath in exclusionPaths.Split(','))
+ this.AreaInfoList.Children.Clear();
+ foreach (AreaInfo areaInfo in areaInfos)
{
- exclusion = new FolderInfoItem(folderPath);
- exclusion.FolderPath.Foreground = new SolidColorBrush(Colors.Gray);
- exclusion.DeleteButton.Click += DeleteExclusionButton_Click;
- exclusion.DeleteButton.Tag = folderPath;
-
- this.ExclusionList.Items.Add(exclusion);
-
- _exclusionFolder.Add(folderPath);
+ AreaInfoItem item = new AreaInfoItem(areaInfo);
+ // 编辑按钮
+ item.EditButton.Tag = areaInfo;
+ item.EditButton.Click += EditButton_Click;
+ // 删除按钮
+ item.DeleteButton.Tag = areaInfo;
+ item.DeleteButton.Click += DelButton_Click;
+ // 选中或取消选中事件
+ item.AreaIsEnable.Tag = areaInfo;
+ item.AreaIsEnable.Checked += AreaIsEnable_Checked;
+ item.AreaIsEnable.Unchecked += AreaIsEnable_Unchecked;
+ this.AreaInfoList.Children.Add(item);
}
}
+ _normalAreaInfos = areaInfos;
}
- #region 搜索区文件夹
///
- /// 条目删除按钮
+ /// 区域是否取用未选中
///
///
///
- private void DeleteButton_Click(object sender, RoutedEventArgs e)
+ private void AreaIsEnable_Unchecked(object sender, RoutedEventArgs e)
{
- for(int i = 0; i < this.FolderList.Items.Count; i++)
+ AreaInfo areaInfo = (AreaInfo)(sender as CheckBox).Tag;
+ areaInfo.IsEnable = false;
+
+ // 修改本地列表缓存
+ if (_normalAreaInfos!= null)
{
- if ((this.FolderList.Items[i] as FolderInfoItem).FolderPath.Text.Equals((sender as Button).Tag))
+ for(int i = 0; i < _normalAreaInfos.Count; i++)
{
- this.FolderList.Items.RemoveAt(i);
- break;
+ AreaInfo info = _normalAreaInfos[i];
+ if (info.AreaId.Equals(areaInfo.AreaId))
+ {
+ info = areaInfo;
+ _normalAreaInfos[i] = info;
+ }
}
}
}
///
- /// 添加文件夹
+ /// 区域是否启用选中
///
///
///
- private void AddFolder_Click(object sender, RoutedEventArgs e)
+ private void AreaIsEnable_Checked(object sender, RoutedEventArgs e)
{
- System.Windows.Forms.FolderBrowserDialog browserDialog = new System.Windows.Forms.FolderBrowserDialog();
- if (browserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
- {
- string folderPath = browserDialog.SelectedPath;
+ AreaInfo areaInfo = (AreaInfo)(sender as CheckBox).Tag;
+ areaInfo.IsEnable = true;
- // 判断是否已选过
- if (_indexFolder.Contains(folderPath))
+ // 修改本地列表缓存
+ if (_normalAreaInfos != null)
+ {
+ for (int i = 0; i < _normalAreaInfos.Count; i++)
{
- MessageCore.ShowWarning("选定目录已存在");
- return;
+ AreaInfo info = _normalAreaInfos[i];
+ if (info.AreaId.Equals(areaInfo.AreaId))
+ {
+ info = areaInfo;
+ _normalAreaInfos[i] = info;
+ }
}
-
- // 加入列表
- FolderInfoItem folder = new FolderInfoItem(folderPath);
- folder.DeleteButton.Click += DeleteButton_Click;
- folder.DeleteButton.Tag = folderPath;
-
- this.FolderList.Items.Add(folder);
-
- _indexFolder.Add(folderPath);
}
}
- #endregion
- #region 排除文件夹
///
- /// 排除文件夹条目删除按钮
+ /// 删除
///
///
///
- private void DeleteExclusionButton_Click(object sender, RoutedEventArgs e)
+ private void DelButton_Click(object sender, RoutedEventArgs e)
{
- for (int i = 0; i < this.ExclusionList.Items.Count; i++)
+ AreaInfo areaInfo = (AreaInfo)(sender as Button).Tag;
+ if (areaInfo != null)
{
- if ((this.ExclusionList.Items[i] as FolderInfoItem).FolderPath.Text.Equals((sender as Button).Tag))
+ // AreaUtil.DeleteAreaInfo(areaInfo);
+ for( int i = 0; i < _normalAreaInfos.Count; i++)
{
- this.ExclusionList.Items.RemoveAt(i);
- break;
+ AreaInfo normalAreaInfo = _normalAreaInfos[i];
+ if (normalAreaInfo.AreaId == areaInfo.AreaId)
+ {
+ _normalAreaInfos.RemoveAt(i);
+ _deleteAreaInfos.Add(normalAreaInfo);
+ break;
+ }
}
+
+ // 重新加载区域信息列表(刷新)
+ LoadAreaInfoList(_normalAreaInfos);
}
}
+
///
- /// 添加排除文件夹
+ /// 编辑
///
///
///
- private void AddExclusionFolder_Click(object sender, RoutedEventArgs e)
+ private void EditButton_Click(object sender, RoutedEventArgs e)
{
- System.Windows.Forms.FolderBrowserDialog browserDialog = new System.Windows.Forms.FolderBrowserDialog();
- if (browserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
- {
- // 获得选定文件夹
- string folderPath = browserDialog.SelectedPath;
+ AreaInfo areaInfo = (AreaInfo)(sender as Button).Tag;
+ CacheUtil.Put("AreaInfos", _normalAreaInfos);
+ ShowAreaEditDialog(areaInfo);
+ }
- // 判断是否已选过
- if (_exclusionFolder.Contains(folderPath))
+ ///
+ /// 新增
+ ///
+ ///
+ ///
+ private void AddButton_Click(object sender, RoutedEventArgs e)
+ {
+ CacheUtil.Put("AreaInfos", _normalAreaInfos);
+ ShowAreaEditDialog();
+ }
+
+ ///
+ /// 保存
+ ///
+ ///
+ ///
+ private void SaveButton_Click(object sender, RoutedEventArgs e)
+ {
+ // 保存正常的区域信息列表
+ if (_normalAreaInfos != null)
+ {
+ int enableCount = 0;
+ foreach (AreaInfo info in _normalAreaInfos)
{
- MessageCore.ShowWarning("选定目录已存在");
- return;
+ if (info.IsEnable) enableCount++;
}
- // 判断是否存在于搜索区
- if (_indexFolder.Contains(folderPath))
+ if (enableCount < 1)
{
- MessageCore.ShowWarning("不能排除搜索区目录");
+ MessageCore.ShowWarning("至少保留一个启用的搜索区");
return;
}
- // 加入列表
- FolderInfoItem folder = new FolderInfoItem(folderPath);
- folder.FolderPath.Foreground = new SolidColorBrush(Colors.Gray);
- folder.DeleteButton.Click += DeleteExclusionButton_Click;
- folder.DeleteButton.Tag = folderPath;
+ foreach (AreaInfo areaInfo in _normalAreaInfos)
+ {
+ AreaUtil.SaveAreaInfo(areaInfo);
+ }
+ }
+ // 保存删除的区域信息列表
+ if (_deleteAreaInfos.Count > 0)
+ {
+ foreach (AreaInfo areaInfo in _deleteAreaInfos)
+ {
+ areaInfo.AreaName = null;
+ areaInfo.AreaFolders = null;
+ AreaUtil.DeleteAreaInfo(areaInfo);
- this.ExclusionList.Items.Add(folder);
- _exclusionFolder.Add(folderPath);
+ // 删除区域索引目录
+ try
+ {
+ string areaIndexDir = Path.Combine(AppConst.APP_INDEX_DIR, areaInfo.AreaId);
+ if (Directory.Exists(areaIndexDir))
+ {
+ Directory.Delete(areaIndexDir, true);
+ }
+ }
+ catch (Exception ex)
+ {
+ log.Error("删除区域【" + areaInfo.AreaId + "】索引目录失败:" + ex.Message, ex);
+ }
+ }
}
+ this.DialogResult = true;
}
- #endregion
- #region 保存并关闭
///
- /// 保存并关闭
+ /// 退出
///
///
///
- private void SaveClose_Click(object sender, RoutedEventArgs e)
+ private void ExitButton_Click(object sender, RoutedEventArgs e)
{
- if (this.FolderList.Items.Count <= 0)
- {
- MessageCore.ShowWarning("至少保留一个被搜索文件夹哦");
- return;
- }
- // 搜索区文件夹
- string folderPaths = "";
- foreach(FolderInfoItem item in this.FolderList.Items)
- {
- folderPaths += item.FolderPath.Text + ",";
- }
- folderPaths = folderPaths.Substring(0, folderPaths.Length - 1);
- // 保存到配置文件
- AppUtil.WriteValue("AppConfig", "FolderPaths", folderPaths);
+ this.DialogResult = false;
+ }
- // 排除文件夹
- string exclusionPaths = "";
- foreach (FolderInfoItem item in this.ExclusionList.Items)
- {
- exclusionPaths += item.FolderPath.Text + ",";
- }
- if (!string.IsNullOrEmpty(exclusionPaths))
+ ///
+ /// 显示区域编辑
+ ///
+ ///
+ private void ShowAreaEditDialog(AreaInfo areaInfo = null)
+ {
+ AreaEditWindow editDialog = new AreaEditWindow(areaInfo);
+ editDialog.Topmost = true;
+ editDialog.Owner = this;
+ editDialog.ShowDialog();
+
+ if (editDialog.DialogResult == true)
{
- exclusionPaths = exclusionPaths.Substring(0, exclusionPaths.Length - 1);
+ _normalAreaInfos = CacheUtil.Get>("AreaInfos");
+ // 重新加载区域信息列表(刷新)
+ LoadAreaInfoList(_normalAreaInfos);
}
- // 保存到配置文件
- AppUtil.WriteValue("AppConfig", "ExclusionPaths", exclusionPaths);
-
- this.DialogResult = true;
-
- this.Close();
}
- #endregion
}
}
diff --git a/TextLocator/Core/AppConst.cs b/TextLocator/Core/AppConst.cs
index 87e9fd1018823a064e34af6bdbf37a294865625d..2964a5852b6a04e242060743d3d4cd7ca8c7b068 100644
--- a/TextLocator/Core/AppConst.cs
+++ b/TextLocator/Core/AppConst.cs
@@ -46,10 +46,6 @@ namespace TextLocator.Core
/// 索引更新任务间隔时间,单位:分
///
public static int INDEX_UPDATE_TASK_INTERVAL = int.Parse(AppUtil.ReadValue("AppConfig", "IndexUpdateTaskInterval", "10"));
- ///
- /// 启用XpsDocument预览
- ///
- public static bool ENABLE_XPSDOCUMENT_VIEW = bool.Parse(AppUtil.ReadValue("AppConfig", "EnableXpsDocumentView", "True"));
///
/// AppName
@@ -95,10 +91,6 @@ namespace TextLocator.Core
///
public static readonly Regex REGEX_TAG = new Regex("\\<.[^<>]*\\>");
///
- /// 匹配文件后缀
- ///
- public static readonly Regex REGEX_FILE_EXT = new Regex(@"^.+\.(" + FileTypeUtil.GetFileTypeExts("|") + ")$");
- ///
/// 匹配排除关键词
///
public static readonly Regex REGEX_EXCLUDE_KEYWORD = new Regex(@"(\$RECYCLE|360REC|SYSTEM|TEMP|SYSTEM VOLUME INFOMATION|\{(.*)\})");
@@ -111,7 +103,10 @@ namespace TextLocator.Core
///
public static readonly Regex REGEX_CONTENT_PAGE = new Regex(@"----\d+----");
-
+ ///
+ /// 索引写入器
+ ///
+ public const int INDEX_PARTITION_COUNT = 5;
///
/// 比例最小值
///
@@ -128,6 +123,9 @@ namespace TextLocator.Core
/// 加密解密秘钥(不能随意修改,随意修改将导致注册码失效)
///
public const string AES_KEY = "TextLocator_Activation_2022";
-
+ ///
+ /// 区域配置
+ ///
+ public const string AREA_CONFIG_KEY = "AreaConfig";
}
}
diff --git a/TextLocator/Dict/stopwords.txt b/TextLocator/Dict/stopwords.txt
index 4d5f146b0ef6da6fb3a389c158ae7f216989ea87..d1daf9111e32d3e1cc0bb5d9966398cfb5922a46 100644
--- a/TextLocator/Dict/stopwords.txt
+++ b/TextLocator/Dict/stopwords.txt
@@ -12,6 +12,9 @@ yours
yourself
yourselves
he
+open
+dialog
+window
him
his
himself
diff --git a/TextLocator/Entity/AreaInfo.cs b/TextLocator/Entity/AreaInfo.cs
new file mode 100644
index 0000000000000000000000000000000000000000..66c10be18e3f7b87814809e3e24848a8734ab264
--- /dev/null
+++ b/TextLocator/Entity/AreaInfo.cs
@@ -0,0 +1,33 @@
+using System.Collections.Generic;
+using TextLocator.Enums;
+
+namespace TextLocator.Entity
+{
+ ///
+ /// 区域信息
+ ///
+ public class AreaInfo
+ {
+ ///
+ /// 是否启用
+ ///
+ public bool IsEnable { get; set; }
+
+ ///
+ /// 区域索引
+ ///
+ public string AreaId { get; set; }
+ ///
+ /// 区域名称
+ ///
+ public string AreaName { get; set; }
+ ///
+ /// 区域文件夹路径
+ ///
+ public List AreaFolders { get; set; }
+ ///
+ /// 区域文件类型
+ ///
+ public List AreaFileTypes { get; set; }
+ }
+}
diff --git a/TextLocator/Entity/SearchParam.cs b/TextLocator/Entity/SearchParam.cs
index 0f27a60bc47f96c81cff724a6d6e09e3d2b22083..67fe5eb5287519ed3bef8d1e0a6ba3f5c1adebfa 100644
--- a/TextLocator/Entity/SearchParam.cs
+++ b/TextLocator/Entity/SearchParam.cs
@@ -19,7 +19,7 @@ namespace TextLocator.Entity
///
/// 文件类型
///
- public string FileType { get; set; }
+ public FileType FileType { get; set; }
///
/// 排序规则
///
@@ -29,9 +29,13 @@ namespace TextLocator.Entity
///
public bool IsMatchWords { get; set; }
///
- /// 仅文件名
+ /// 区分大小写
///
- public bool IsOnlyFileName { get; set; }
+ public bool IsMatchCase { get; set; }
+ ///
+ /// 搜索域
+ ///
+ public SearchRegion SearchRegion { get; set; }
///
/// 分页索引
///
diff --git a/TextLocator/Enums/FileType.cs b/TextLocator/Enums/FileType.cs
index 2d0aa68f81db5c9cd57dcc6692954a3f76e1c447..d94aa78767052ea638d3f1e477cdb34c542a2624 100644
--- a/TextLocator/Enums/FileType.cs
+++ b/TextLocator/Enums/FileType.cs
@@ -7,6 +7,11 @@ namespace TextLocator.Enums
///
public enum FileType
{
+ ///
+ /// 全部
+ ///
+ [Description("all")]
+ 全部,
///
/// Word文档
///
diff --git a/TextLocator/Enums/SearchRegion.cs b/TextLocator/Enums/SearchRegion.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d1a33305e703934b05d12ea2b0c2f32fea11fd81
--- /dev/null
+++ b/TextLocator/Enums/SearchRegion.cs
@@ -0,0 +1,22 @@
+namespace TextLocator.Enums
+{
+ ///
+ /// 搜索域
+ ///
+ public enum SearchRegion
+ {
+ ///
+ /// 文件名和内容
+ ///
+ 文件名和内容,
+ ///
+ /// 仅文件名
+ ///
+ 仅文件名,
+ ///
+ /// 进文件内容
+ ///
+ 仅文件内容
+
+ }
+}
diff --git a/TextLocator/FileInfoItem.xaml.cs b/TextLocator/FileInfoItem.xaml.cs
index 0c734e5946d64739715d30e374a798f515fd5ac1..7ac042933665cfd8afd7c9088a5dff9fabad116f 100644
--- a/TextLocator/FileInfoItem.xaml.cs
+++ b/TextLocator/FileInfoItem.xaml.cs
@@ -15,7 +15,12 @@ namespace TextLocator
{
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
- public FileInfoItem(Entity.FileInfo fileInfo)
+ ///
+ /// 文件信息显示条目
+ ///
+ /// 文件信息
+ /// 搜索域
+ public FileInfoItem(Entity.FileInfo fileInfo, Enums.SearchRegion searchRegion)
{
InitializeComponent();
@@ -23,14 +28,14 @@ namespace TextLocator
try
{
- Refresh(fileInfo);
+ Refresh(fileInfo, searchRegion);
}
catch {
this.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
- Refresh(fileInfo);
+ Refresh(fileInfo, searchRegion);
}
catch (Exception ex)
{
@@ -43,8 +48,9 @@ namespace TextLocator
///
/// 刷新数据
///
- ///
- public void Refresh(Entity.FileInfo fileInfo)
+ /// 文件信息
+ /// 搜索域
+ public void Refresh(Entity.FileInfo fileInfo, Enums.SearchRegion searchRegion)
{
// 根据文件类型显示图标
this.FileTypeIcon.Source = FileUtil.GetFileIcon(fileInfo.FileType);
@@ -56,7 +62,10 @@ namespace TextLocator
string fileName = fileInfo.FileName;
// 显示文件名称
RichTextBoxUtil.FillingData(this.FileName, fileName.Length > 55 ? fileName.Substring(0, 55) + "..." : fileName, (Brush)new BrushConverter().ConvertFromString("#1A0DAB"), true);
- RichTextBoxUtil.Highlighted(this.FileName, Colors.Red, fileInfo.Keywords);
+ if (searchRegion == Enums.SearchRegion.文件名和内容 || searchRegion == Enums.SearchRegion.仅文件名)
+ {
+ RichTextBoxUtil.Highlighted(this.FileName, Colors.Red, fileInfo.Keywords);
+ }
string filePath = fileInfo.FilePath.Replace(fileInfo.FileName, "");
// 文件路径
@@ -68,9 +77,24 @@ namespace TextLocator
this.Dispatcher.BeginInvoke(new Action(() =>
{
RichTextBoxUtil.FillingData(this.ContentBreviary, breviary, (Brush)new BrushConverter().ConvertFromString("#545454"));
- RichTextBoxUtil.Highlighted(this.ContentBreviary, Colors.Red, fileInfo.Keywords);
+ if (searchRegion == Enums.SearchRegion.文件名和内容 || searchRegion == Enums.SearchRegion.仅文件内容)
+ {
+ RichTextBoxUtil.Highlighted(this.ContentBreviary, Colors.Red, fileInfo.Keywords);
+ }
}));
});
+
+ /*// 词频统计
+ Task.Factory.StartNew(() => {
+ string keywordFrequency = IndexCore.GetKeywordFrequency(fileInfo, searchRegion);
+ this.Dispatcher.BeginInvoke(new Action(() => {
+ if (!string.IsNullOrWhiteSpace(keywordFrequency))
+ {
+ // 关键词匹配次数
+ this.FileTypeIcon.ToolTip = keywordFrequency;
+ }
+ }));
+ });*/
}
}
}
diff --git a/TextLocator/FolderInfoItem.xaml b/TextLocator/FolderInfoItem.xaml
index bdf5606497810772f72a21a5a10a59e0ba7a40ab..d4bd35db08785defbd607755f7e4a4f83d59260e 100644
--- a/TextLocator/FolderInfoItem.xaml
+++ b/TextLocator/FolderInfoItem.xaml
@@ -5,11 +5,11 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TextLocator"
mc:Ignorable="d"
- d:DesignWidth="430" d:DesignHeight="40">
-
-
-
+ d:DesignWidth="430" d:DesignHeight="30">
+
+
+
-
+
diff --git a/TextLocator/HotkeyWindow.xaml b/TextLocator/HotkeyWindow.xaml
index 9e462da476ea0fb5a15ab01d596a7a36ee6a3460..ff58c20c5be9d6ddac2e265c1aee15db90a0faed 100644
--- a/TextLocator/HotkeyWindow.xaml
+++ b/TextLocator/HotkeyWindow.xaml
@@ -6,7 +6,7 @@
xmlns:local="clr-namespace:TextLocator"
mc:Ignorable="d"
x:Name="hotkey"
- Title="热键设置" Height="380" Width="520" WindowStartupLocation="CenterOwner" WindowStyle="ToolWindow" ResizeMode="CanMinimize" Icon="/Resource/App.ico" Loaded="Window_Loaded" Closed="Window_Closed" >
+ Title="热键设置" Height="380" Width="520" WindowStartupLocation="CenterScreen" WindowStyle="ToolWindow" ResizeMode="CanMinimize" Icon="/Resource/App.ico" Loaded="Window_Loaded" Closed="Window_Closed" >
diff --git a/TextLocator/Index/IndexCore.cs b/TextLocator/Index/IndexCore.cs
index 490a2c0d642f1bfc11bc5127f89913750fe64255..21660df9bf6d2c6146e287de6f0ba13a94bd432f 100644
--- a/TextLocator/Index/IndexCore.cs
+++ b/TextLocator/Index/IndexCore.cs
@@ -57,7 +57,7 @@ namespace TextLocator.Index
/// 删除索引
///
private static volatile Queue _indexDeleted = new Queue();
-
+
#region 索引写入器
///
/// 索引写入初始化(FSDirectory表示索引存放在硬盘上,RAMDirectory表示放在内存上)
@@ -75,15 +75,16 @@ namespace TextLocator.Index
///
/// 创建索引写入器
///
+ /// 区域ID(区域索引标识符)
/// 是否是创建
/// 索引写入器下标
- private static void CreateIndexWriter(bool create, int index = -1)
+ private static void CreateIndexWriter(string areaId, bool create, int index = -1)
{
// 内部函数
void BuiltIn(int subIndex, bool isNew = false)
{
// 索引子目录
- string appIndexDirSub = Path.Combine(AppConst.APP_INDEX_DIR, subIndex + "");
+ string appIndexDirSub = Path.Combine(AppConst.APP_INDEX_DIR, areaId, subIndex + "");
if (!Directory.Exists(appIndexDirSub)) Directory.CreateDirectory(appIndexDirSub);
// 如果目录下的文件为空,说明是新建
@@ -95,9 +96,13 @@ namespace TextLocator.Index
// ---- 索引目录
Lucene.Net.Store.FSDirectory indexWriterDir = Lucene.Net.Store.FSDirectory.Open(new DirectoryInfo(appIndexDirSub), new Lucene.Net.Store.NativeFSLockFactory());
if (isNew)
+ {
indexWriterDirs.Add(indexWriterDir);
+ }
else
+ {
indexWriterDirs[subIndex] = indexWriterDir;
+ }
// 如果索引目录被锁定(比如索引过程中程序异常退出),则首先解锁
// Lucene.Net在写索引库之前会自动加锁,在Close的时候会自动解锁
@@ -139,10 +144,10 @@ namespace TextLocator.Index
if (index <= -1)
{
// 创建10个写入器
- for (int i = 0; i < 10; i++)
+ for (int i = 0; i < AppConst.INDEX_PARTITION_COUNT; i++)
{
BuiltIn(i, true);
- }
+ }
}
else
{
@@ -173,7 +178,7 @@ namespace TextLocator.Index
}
if (index <= -1)
{
- for (int i = 0; i < indexWriters.Count; i++)
+ for(int i = 0; i < indexWriters.Count; i++)
{
BuiltIn(i);
}
@@ -184,6 +189,18 @@ namespace TextLocator.Index
{
BuiltIn(index);
}
+
+ }
+
+ ///
+ /// 区域索引标记
+ ///
+ /// 区域ID,不允许为空
+ ///
+ private static string AreaIndexTag(string areaId)
+ {
+ // 不同区域,索引分开记录
+ return areaId + "Index";
}
#endregion
@@ -191,12 +208,16 @@ namespace TextLocator.Index
///
/// 创建或更新索引
///
+ /// 区域ID(区域索引标识符)
/// 文件列表
/// 删除文件列表
/// 是否重建,true表示重建,false表示更新
/// 消息回调
- public static int CreateIndex(List updateFilePaths, List deleteFilePaths, bool isRebuild, CallbackStatus callback)
+ public static int CreateIndex(string areaId, List updateFilePaths, List deleteFilePaths, bool isRebuild, CallbackStatus callback)
{
+ // 不同区域,索引分开记录
+ string areaIdIndex = AreaIndexTag(areaId);
+
// 排重 => 排序
updateFilePaths = ListUtil.Shuffle(updateFilePaths.Distinct().ToList());
@@ -213,30 +234,30 @@ namespace TextLocator.Index
_errorCount = 0;
// 判断是创建索引还是增量索引(如果索引目录不存在,重建)
- bool create = !Directory.Exists(AppConst.APP_INDEX_DIR);
+ bool create = !Directory.Exists(Path.Combine(AppConst.APP_INDEX_DIR, areaId));
// 入参为true,表示重建
if (isRebuild)
{
create = isRebuild;
}
- // 创建还是更新?
+ // 创建则删除全部标记
if (create)
{
// 重建时,删除全部标记
- AppUtil.DeleteSection("FileIndex");
+ AppUtil.DeleteSection(areaIdIndex);
}
// -------- 以下4个函数调用顺序不能更改 --------
// 1、-------- 创建索引写入器(创建索引任务执行前,创建写入器很关键)
- CreateIndexWriter(create);
+ CreateIndexWriter(areaId, create);
- // 2、-------- 删除文件索引(更新ini文件的FileIndex标记,便于更新方法检测时使用)
- DeleteFileIndex(deleteFilePaths);
+ // 2、-------- 删除文件索引(更新ini文件的AreaIdIndex标记,便于更新方法检测时使用)
+ DeleteFileIndex(areaId, deleteFilePaths);
// 3、-------- 更新文件索引
- UpdateFileIndex(updateFilePaths, create);
+ UpdateFileIndex(areaId, updateFilePaths, create);
// 4、-------- 删除搜索时标记的索引
DeleteFileIndexForSearch();
@@ -270,10 +291,11 @@ namespace TextLocator.Index
///
/// 更新文件索引
///
+ /// 区域ID(区域索引标识符)
/// 更新文件列表
/// 是否是创建
///
- private static void UpdateFileIndex(List updateFilePaths, bool create)
+ private static void UpdateFileIndex(string areaId, List updateFilePaths, bool create)
{
if (updateFilePaths.Count > 0)
{
@@ -284,13 +306,14 @@ namespace TextLocator.Index
{
string filePath = updateFilePaths[i];
// 忽略已存在索引的文件
- if (SkipFile(create, filePath, resetEvent))
+ if (SkipFile(areaId, create, filePath, resetEvent))
{
continue;
}
// 加入线程池
ThreadPool.QueueUserWorkItem(new WaitCallback(CreateIndexTask), new TaskInfo()
{
+ AreaId = areaId,
FilePath = filePath,
ResetEvent = resetEvent
});
@@ -309,12 +332,16 @@ namespace TextLocator.Index
///
/// 删除文件索引
///
+ /// 区域ID(区域索引标识符)
/// 删除文件列表
///
- private static void DeleteFileIndex(List deleteFilePaths)
+ private static void DeleteFileIndex(string areaId, List deleteFilePaths)
{
if (deleteFilePaths.Count > 0)
{
+ // 不同区域,索引分开记录
+ string areaIdIndex = AreaIndexTag(areaId);
+
foreach (string filePath in deleteFilePaths)
{
// 文件标记
@@ -332,7 +359,7 @@ namespace TextLocator.Index
}
// 删除标记和缓存
- AppUtil.WriteValue("FileIndex", filePath, null);
+ AppUtil.WriteValue(areaIdIndex, filePath, null);
}
}
else
@@ -376,18 +403,22 @@ namespace TextLocator.Index
///
/// 忽略文件
///
+ /// 区域ID(区域索引标识符),不允许为空
/// 是否是创建,true为创建、false为更新
/// 文件路径
/// 多线程任务标记
- private static bool SkipFile(bool create, string filePath, MutipleThreadResetEvent resetEvent)
+ private static bool SkipFile(string areaId, bool create, string filePath, MutipleThreadResetEvent resetEvent)
{
try
{
+ // 不同区域,索引分开记录
+ string areaIdIndex = AreaIndexTag(areaId);
+
FileInfo fileInfo = new FileInfo(filePath);
// 当前文件修改时间
string lastWriteTime = fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss.ffff");
// 上次索引时文件修改时间标记
- string lastWriteTimeTag = AppUtil.ReadValue("FileIndex", filePath);
+ string lastWriteTimeTag = AppUtil.ReadValue(areaIdIndex, filePath);
// 非重建 && 文件已经被索引过
bool isUpdate = !create;
@@ -409,9 +440,7 @@ namespace TextLocator.Index
// 当前任务执行完成,唤醒等待线程继续执行
resetEvent.SetOne();
-#if !DEBUG
log.Debug(skip);
-#endif
return true;
}
}
@@ -423,12 +452,15 @@ namespace TextLocator.Index
///
/// 创建索引任务方法
///
- ///
+ /// 实际传入TaskInfo
private static void CreateIndexTask(object obj)
{
TaskInfo taskInfo = obj as TaskInfo;
try
{
+ // 不同区域,索引分开记录
+ string areaIdIndex = AreaIndexTag(taskInfo.AreaId);
+
// 解析时间
var taskMark = TaskTime.StartNew();
@@ -447,7 +479,7 @@ namespace TextLocator.Index
string updateTime = fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss");
// ---- 写入已索引标记 ----
- AppUtil.WriteValue("FileIndex", filePath, fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss.ffff"));
+ AppUtil.WriteValue(areaIdIndex, filePath, fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss.ffff"));
// 根据文件路径获取文件类型(自定义文件类型分类)
FileType fileType = FileTypeUtil.GetFileType(filePath);
@@ -496,7 +528,7 @@ namespace TextLocator.Index
doc.Add(new Lucene.Net.Documents.Field("Preview", content, Lucene.Net.Documents.Field.Store.YES, Lucene.Net.Documents.Field.Index.NOT_ANALYZED));
// 执行删除、添加逻辑
- AddDocument(filePath, doc);
+ AddDocument(taskInfo.AreaId, filePath, doc);
}
msg.Append(",索引:" + taskMark.ConsumeTime);
}
@@ -532,13 +564,14 @@ namespace TextLocator.Index
///
/// 添加文件索引Doc
///
+ /// 区域ID(区域索引标识符),不允许为null
/// 文件路径
- /// 文件索引Doc
- private static void AddDocument(string filePath, Lucene.Net.Documents.Document doc)
+ /// 文件索引Doc对象
+ private static void AddDocument(string areaId, string filePath, Lucene.Net.Documents.Document doc)
{
// -------- 获取索引写入器
// 随机索引写入器
- int index = new Random().Next(10);
+ int index = filePath.Length % AppConst.INDEX_PARTITION_COUNT; // new Random().Next(10);
try
{
@@ -547,20 +580,20 @@ namespace TextLocator.Index
indexWriters[index].UpdateDocument(new Lucene.Net.Index.Term("FileMark", fileMark), doc);
}
- catch(Exception ex)
+ catch (Exception ex)
{
log.Error(filePath + " -> " + ex.Message + " => 重启索引写入器!", ex);
- // 关闭索引写入器
- CloseIndexWriter();
+ // 关闭索引写入器(写入器索引)
+ CloseIndexWriter(index);
- // 创建索引写入器
- CreateIndexWriter(false, index);
+ // 创建索引写入器(区域ID + 更新 + 写入器索引)
+ CreateIndexWriter(areaId, false, index);
log.Debug(filePath + " -> 重新执行添加操作");
- AddDocument(filePath, doc);
+ AddDocument(areaId, filePath, doc);
}
}
#endregion
@@ -590,43 +623,51 @@ namespace TextLocator.Index
List searchers = new List();
// 构造全部搜索区索引路径
- for (int i = 0; i < 10; i++)
+ foreach(Entity.AreaInfo areaInfo in AreaUtil.GetEnableAreaInfoList())
{
- try
- {
- string subDir = Path.Combine(AppConst.APP_INDEX_DIR, i + "");
- log.Debug("搜索缩影路径:" + subDir);
- Lucene.Net.Store.FSDirectory directory = Lucene.Net.Store.FSDirectory.Open(new DirectoryInfo(subDir), new Lucene.Net.Store.NoLockFactory());
- directorys.Add(directory);
- searchers.Add(new Lucene.Net.Search.IndexSearcher(directory, true));
- }
- catch (Exception ex)
+ for(int i = 0; i < AppConst.INDEX_PARTITION_COUNT; i++)
{
- log.Error("搜索器初始化失败:" + ex.Message, ex);
+ try
+ {
+ string subDir = Path.Combine(AppConst.APP_INDEX_DIR, areaInfo.AreaId, i + "");
+ log.Debug("搜索缩影路径:" + subDir);
+ Lucene.Net.Store.FSDirectory directory = Lucene.Net.Store.FSDirectory.Open(new DirectoryInfo(subDir), new Lucene.Net.Store.NoLockFactory());
+ directorys.Add(directory);
+ searchers.Add(new Lucene.Net.Search.IndexSearcher(directory, true));
+ }
+ catch (Exception ex)
+ {
+ log.Error("搜索器初始化失败:" + ex.Message, ex);
+ }
}
}
-
// 并行多搜索器(搜索结果去重合并)
Lucene.Net.Search.ParallelMultiSearcher parallelMultiSearcher = new Lucene.Net.Search.ParallelMultiSearcher(searchers.ToArray());
try
{
// 搜索域加权
Dictionary boosts = new Dictionary();
- boosts["Content"] = 1.2f;
- boosts["FileName"] = 1.0f;
-
// 搜索域列表
List fields = new List();
- fields.Add("FileName");
- if (!param.IsOnlyFileName)
+ // 搜索域判断(文件名 || 文件内容 || 文件名和文件内容)
+ bool isSearchFileName = param.SearchRegion == SearchRegion.文件名和内容 || param.SearchRegion == SearchRegion.仅文件名;
+ bool isSearchContent = param.SearchRegion == SearchRegion.文件名和内容 || param.SearchRegion == SearchRegion.仅文件内容;
+ // 文件名
+ if (isSearchFileName)
{
+ boosts["FileName"] = 1.0f;
+ fields.Add("FileName");
+ }
+ // 文件内容
+ if (isSearchContent)
+ {
+ boosts["Content"] = 1.2f;
fields.Add("Content");
}
// 查询转换器
- Lucene.Net.QueryParsers.QueryParser parser =
- new Lucene.Net.QueryParsers.MultiFieldQueryParser(
+ Lucene.Net.QueryParsers.QueryParser queryParser = new Lucene.Net.QueryParsers.MultiFieldQueryParser(
// Lucence版本
Lucene.Net.Util.Version.LUCENE_30,
// 搜索域列表
@@ -641,29 +682,32 @@ namespace TextLocator.Index
// 遍历关键词列表
string text = "";
- string tag = "分词";
+ string keywordType = "分词";
foreach (string keyword in param.Keywords)
{
text += keyword + ",";
// 正则
if (AppConst.REGEX_SUPPORT_WILDCARDS.IsMatch(keyword))
{
- tag = "正则";
- // 文件名
- RegexQuery regexFileName = new RegexQuery(new Lucene.Net.Index.Term("FileName", keyword));
- boolQuery.Add(regexFileName, Lucene.Net.Search.Occur.SHOULD);
+ keywordType = "正则";
- if (!param.IsOnlyFileName)
+ // 文件名
+ if (param.SearchRegion == SearchRegion.文件名和内容 || param.SearchRegion == SearchRegion.仅文件名)
+ {
+ RegexQuery regexFileName = new RegexQuery(new Lucene.Net.Index.Term("FileName", keyword));
+ boolQuery.Add(regexFileName, Lucene.Net.Search.Occur.SHOULD);
+ }
+ // 文件内容
+ if (param.SearchRegion == SearchRegion.文件名和内容 || param.SearchRegion == SearchRegion.仅文件内容)
{
- // 文件内容
RegexQuery regexContentQuery = new RegexQuery(new Lucene.Net.Index.Term("Content", keyword));
boolQuery.Add(regexContentQuery, Lucene.Net.Search.Occur.SHOULD);
- }
+ }
}
// 常规
else
{
- Lucene.Net.Search.Query query = parser.Parse(Lucene.Net.QueryParsers.QueryParser.Escape(keyword));
+ Lucene.Net.Search.Query query = queryParser.Parse(Lucene.Net.QueryParsers.QueryParser.Escape(keyword));
boolQuery.Add(query, param.IsMatchWords ? Lucene.Net.Search.Occur.MUST : Lucene.Net.Search.Occur.SHOULD);
}
}
@@ -672,10 +716,10 @@ namespace TextLocator.Index
// 文件类型筛选(文件类型为全部时,则为空)
Lucene.Net.Search.TermsFilter filter = null;
- if (!string.IsNullOrEmpty(param.FileType))
+ if (param.FileType != FileType.全部)
{
filter = new Lucene.Net.Search.TermsFilter();
- filter.AddTerm(new Lucene.Net.Index.Term("FileType", param.FileType));
+ filter.AddTerm(new Lucene.Net.Index.Term("FileType", param.FileType.ToString()));
}
log.Debug("组合搜索条件:" + boolQuery.ToString());
@@ -775,12 +819,10 @@ namespace TextLocator.Index
fileInfos.Add(fileInfo);
}
- string msg = string.Format("检索完成。{0}:( {1} ),结果:{2}个符合条件的结果 (第 {3} 页),耗时:{4}。", tag, (text.Length > 50 ? text.Substring(0, 50) + "..." : text), totalHits - deleteCount, param.PageIndex, taskMark.ConsumeTime);
+ string msg = string.Format("检索完成。{0}:( {1} ),结果:{2}个符合条件的结果 (第 {3} 页),耗时:{4}。", keywordType, (text.Length > 50 ? text.Substring(0, 50) + "..." : text), totalHits - deleteCount, param.PageIndex, taskMark.ConsumeTime);
log.Debug(msg);
if (_searchCallback != null)
- {
_searchCallback(msg);
- }
// 返回查询结果
return new Entity.SearchResult()
@@ -796,7 +838,7 @@ namespace TextLocator.Index
}
finally
{
- foreach (var searcher in searchers)
+ foreach(var searcher in searchers)
{
try
{
@@ -807,7 +849,7 @@ namespace TextLocator.Index
}
catch { }
}
- foreach (var dir in directorys)
+ foreach(var dir in directorys)
{
try
{
@@ -824,43 +866,55 @@ namespace TextLocator.Index
///
/// 获取关键词词频
///
- /// 关键词列表
- /// 文件名
- /// 文件内容
+ /// 文件信息
+ /// 搜索域
/// 自动换行
///
- private static string GetKeywordFrequency(List keywords, string fileName, string preview, bool autoNewLine = true)
+ public static string GetKeywordFrequency(Entity.FileInfo fileInfo, SearchRegion searchRegion, bool autoNewLine = true)
{
try
{
- // 获取内容(预览内容替换----\d+----)
- string content = AppConst.REGEX_CONTENT_PAGE.Replace(preview, "");
-
TaskTime taskTime = TaskTime.StartNew();
// 定义词频词典
Dictionary frequencyDic = new Dictionary();
// 遍历关键词
- foreach (string keyword in keywords)
+ foreach (string keyword in fileInfo.Keywords)
{
- // 声明正则
- Regex regex = new Regex(keyword);
- // 匹配文件名
- Match matchName = regex.Match(fileName), matchContent = regex.Match(content);
// 匹配内容
int matchNameCount = 0, matchContentCount = 0;
- // 文件名匹配成功
- if (matchName.Success)
+ // 声明正则
+ Regex regex = new Regex(keyword);
+
+ // ---- 匹配文件名
+ if (searchRegion == SearchRegion.文件名和内容 || searchRegion == SearchRegion.仅文件名)
{
- // 获取匹配次数
- matchNameCount = regex.Matches(fileName).Count;
+ // 匹配文件名
+ Match matchName = regex.Match(fileInfo.FileName);
+ // 文件名匹配成功
+ if (matchName.Success)
+ {
+ // 获取匹配次数
+ matchNameCount = regex.Matches(fileInfo.FileName).Count;
+ }
}
- // 文件内容匹配成功
- if (matchContent.Success)
+
+ // ---- 匹配文件内容
+ if (searchRegion == SearchRegion.文件名和内容 || searchRegion == SearchRegion.仅文件内容)
{
- // 获取匹配次数
- matchContentCount = regex.Matches(content).Count;
+ // 获取内容(预览内容替换----\d+----)
+ string content = AppConst.REGEX_CONTENT_PAGE.Replace(fileInfo.Preview, "");
+
+ // 匹配文件内容
+ Match matchContent = regex.Match(content);
+ // 文件内容匹配成功
+ if (matchContent.Success)
+ {
+ // 获取匹配次数
+ matchContentCount = regex.Matches(content).Count;
+ }
}
+
// 匹配数量合并
int count = matchNameCount + matchContentCount;
// 匹配次数大于才是有效值
@@ -886,7 +940,7 @@ namespace TextLocator.Index
{
text = text.Substring(0, text.Length - 1);
}
- log.Debug(fileName + " -> 词频统计耗时:" + taskTime.ConsumeTime + " 统计词频:" + text);
+ log.Debug(fileInfo.FileName + " -> 词频统计耗时:" + taskTime.ConsumeTime + " 统计词频:" + text);
return text;
}
catch (Exception ex)
@@ -979,6 +1033,10 @@ namespace TextLocator.Index
///
class TaskInfo
{
+ ///
+ /// 区域ID(区域唯一标识符)
+ ///
+ public string AreaId { get; set; }
///
/// 文件路径
///
diff --git a/TextLocator/MainWindow.xaml b/TextLocator/MainWindow.xaml
index 88115a0adfe6aec5c1059b90a56ab9c1b9d89895..a418d719383aee83e17c2550e39cce4bb2152428 100644
--- a/TextLocator/MainWindow.xaml
+++ b/TextLocator/MainWindow.xaml
@@ -60,16 +60,16 @@
-
- 全部
- Word文档
- Excel表格
- PPT文稿
- PDF文档
- DOM文档
- TXT文本
- 常用图片
- 代码文件
+
+ 全部
+ Word文档
+ Excel表格
+ PPT文稿
+ PDF文档
+ DOM文档
+ TXT文本
+ 常用图片
+ 代码文件
@@ -81,29 +81,15 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
@@ -128,33 +114,30 @@
-
+
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
-
@@ -206,6 +189,9 @@
+
+
+
private RadioButton _radioButtonAll;
///
- /// 索引文件夹列表
- ///
- private List _indexFolders = new List();
- ///
- /// 排除文件夹列表
- ///
- private List _exclusionFolders = new List();
- ///
- /// 正则匹配排除文件夹
- ///
- private Regex _exclusionFolderRegex;
- ///
/// 时间戳
///
private long _timestamp;
@@ -61,11 +51,14 @@ namespace TextLocator
/// 上次预览区搜索文本
///
private string _lastPreviewSearchText;
-
///
/// 索引构建中
///
private static volatile bool build = false;
+ ///
+ /// 数据导出中
+ ///
+ private static volatile bool export = false;
#region 热键
///
@@ -122,12 +115,15 @@ namespace TextLocator
// 初始化配置文件信息
InitializeAppConfig();
- // 初始化文件类型过滤器列表
- InitializeFileTypeFilters();
+ // 初始化文件类型列表
+ InitializeSearchFileType();
// 初始化排序类型列表
InitializeSortType();
+ // 初始化搜索域列表
+ InitializeSearchRegion();
+
// 清理事件(必须放在初始化之后,否则类型筛选的选中Reset可能存在错误)
ResetSearchResult();
@@ -173,9 +169,10 @@ namespace TextLocator
{
// 获取程序版本
Version version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
+
+ // 设置标题
+ this.Title = string.Format("{0} v{1} (开放版)", this.Title, version);
- // 设置标题
- this.Title = string.Format("{0} v{1} ({2})", this.Title, version, "开放版");
}
///
@@ -194,58 +191,58 @@ namespace TextLocator
}
///
- /// 初始化文件类型过滤器列表
+ /// 初始化搜索域
///
- private void InitializeFileTypeFilters()
+ private void InitializeSearchRegion()
{
TaskTime taskTime = TaskTime.StartNew();
- // 文件类型筛选下拉框数据初始化
- FileTypeFilter.Children.Clear();
- FileTypeNames.Children.Clear();
-
- _radioButtonAll = new RadioButton()
+ Array regions = Enum.GetValues(typeof(SearchRegion));
+ SearchScope.Items.Clear();
+ foreach (var region in regions)
{
- GroupName = "FileTypeFilter",
- Width = 80,
- Margin = new Thickness(1),
- Tag = "全部",
- Content = "全部",
- Name = "FileTypeAll",
- IsChecked = true,
- ToolTip = "All"
- };
- _radioButtonAll.Checked += FileType_Checked;
- FileTypeFilter.Children.Add(_radioButtonAll);
-
+ SearchScope.Items.Add(region);
+ }
+ log.Debug("InitializeSearchRegion 耗时:" + taskTime.ConsumeTime + "。");
+ }
- // 获取文件类型枚举,遍历并加入下拉列表
+ ///
+ /// 初始化文件类型过滤器列表
+ ///
+ private void InitializeSearchFileType()
+ {
+ TaskTime taskTime = TaskTime.StartNew();
+ // 文件类型筛选下拉框数据初始化
+ SearchFileType.Children.Clear();
+ // 遍历文件类型枚举
foreach (FileType fileType in Enum.GetValues(typeof(FileType)))
{
+ // 构造UI元素
RadioButton radioButton = new RadioButton()
{
- GroupName = "FileTypeFilter",
+ GroupName = "SearchFileType",
+ Name = "FileType" + fileType.ToString(),
Width = 80,
Margin = new Thickness(1),
- Tag = fileType.ToString(),
- Content = fileType.ToString(),
- Name = "FileType" + fileType.ToString(),
- IsChecked = false,
- ToolTip = fileType.GetDescription()
+ Tag = fileType,
+ Content = fileType.ToString(),
+ IsChecked = fileType == FileType.全部
};
+ if (fileType != FileType.全部)
+ {
+ radioButton.ToolTip = fileType.GetDescription();
+ }
radioButton.Checked += FileType_Checked;
- FileTypeFilter.Children.Add(radioButton);
+ SearchFileType.Children.Add(radioButton);
- // 标签
- FileTypeNames.Children.Add(new Button()
+ // 缓存全部,用于还原到默认值(因为默认选中全部)
+ if (fileType == FileType.全部)
{
- Content = fileType.ToString(),
- Height = 20,
- Margin = new Thickness(2, 0, 0, 0),
- ToolTip = fileType.GetDescription(),
- Background = Brushes.DarkGray
- });
+ _radioButtonAll = radioButton;
+ }
}
- log.Debug("InitializeFileTypeFilters 耗时:" + taskTime.ConsumeTime + "。");
+ // 搜索筛选条件直接读取的当前值,初始化时默认赋值全部。其他选项修改时会更改此值
+ SearchFileType.Tag = FileType.全部;
+ log.Debug("InitializeSearchFileTypes 耗时:" + taskTime.ConsumeTime + "。");
}
///
@@ -254,40 +251,33 @@ namespace TextLocator
private void InitializeAppConfig()
{
TaskTime taskTime = TaskTime.StartNew();
- // 初始化显示被索引的文件夹列表
- _indexFolders.Clear();
- // 读取被索引文件夹配置信息,如果配置信息为空:默认为我的文档和我的桌面
- string folderPaths = AppUtil.ReadValue("AppConfig", "FolderPaths", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "," + Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
- // 配置信息不为空
- if (!string.IsNullOrEmpty(folderPaths))
+ // 启用的搜索区域信息显示
+ List enableAreaInfos = AreaUtil.GetEnableAreaInfoList();
+ string enableAreaNames = "";
+ string enableAreaNameDescs = "";
+ foreach (Entity.AreaInfo areaInfo in enableAreaInfos)
{
- string[] folderPathArray = folderPaths.Split(',');
- foreach (string folderPath in folderPathArray)
- {
- _indexFolders.Add(folderPath);
- }
+ enableAreaNames += areaInfo.AreaName + ",";
+ enableAreaNameDescs += areaInfo.AreaName + ":" + string.Join(",", areaInfo.AreaFolders.ToArray()) + "\r\n";
}
- FolderPaths.Text = folderPaths;
- FolderPaths.ToolTip = FolderPaths.Text;
-
- // 读取排除文件夹,
- string exclusionPaths = AppUtil.ReadValue("AppConfig", "ExclusionPaths", "");
- if (!string.IsNullOrEmpty(exclusionPaths))
+ this.EnableAreaInfos.Text = enableAreaNames.Substring(0, enableAreaNames.Length - 1);
+ this.EnableAreaInfos.ToolTip = enableAreaNameDescs.Substring(0, enableAreaNameDescs.Length - 2);
+
+ // 未启用的搜索区域信息显示
+ List disableAreaInfos = AreaUtil.GetDisableAreaInfoList();
+ string disableAreaNames = "";
+ string disableAreaNameDescs = "";
+ foreach (Entity.AreaInfo areaInfo in disableAreaInfos)
{
- string[] exclusionPathArray = exclusionPaths.Split(',');
- foreach (string exclusionPath in exclusionPathArray)
- {
- _exclusionFolders.Add(exclusionPath);
- }
- _exclusionFolderRegex = new Regex(@"(" + exclusionPaths.Replace("\\", "\\\\").Replace(',', '|') + ")");
+ disableAreaNames += areaInfo.AreaName + ",";
+ disableAreaNameDescs += areaInfo.AreaName + ":" + string.Join(",", areaInfo.AreaFolders.ToArray()) + "\r\n";
}
- else
+ this.DisableAreaInfos.Text = string.IsNullOrEmpty(disableAreaNames) ? disableAreaNames : disableAreaNames.Substring(0, disableAreaNames.Length - 1);
+ if (!string.IsNullOrEmpty(disableAreaNameDescs))
{
- _exclusionFolderRegex = null;
- }
- ExclusionPaths.Text = exclusionPaths;
- ExclusionPaths.ToolTip = ExclusionPaths.Text;
+ this.DisableAreaInfos.ToolTip = disableAreaNameDescs.Substring(0, disableAreaNameDescs.Length - 2);
+ }
// 读取分页每页显示条数
if (string.IsNullOrEmpty(AppUtil.ReadValue("AppConfig", "ResultListPageSize", "")))
@@ -334,7 +324,6 @@ namespace TextLocator
if (!win.IsVisible)
{
win.Topmost = true;
- win.Owner = this;
win.ShowDialog();
}
else
@@ -424,11 +413,19 @@ namespace TextLocator
return;
}
- // 搜索按钮时,下拉框和其他筛选条件全部恢复默认值
+ // ---- 搜索按钮时,下拉框和其他筛选条件全部恢复默认值
+ // 取消匹配全词
MatchWords.IsChecked = false;
- OnlyFileName.IsChecked = false;
- (this.FindName("FileTypeAll") as RadioButton).IsChecked = true;
+
+ // 全部文件类型
+ ToggleButtonAutomationPeer toggleButtonAutomationPeer = new ToggleButtonAutomationPeer(_radioButtonAll);
+ IToggleProvider toggleProvider = toggleButtonAutomationPeer.GetPattern(PatternInterface.Toggle) as IToggleProvider;
+ toggleProvider.Toggle();
+
+ // 默认排序
SortOptions.SelectedIndex = 0;
+ // 文件名和内容
+ // SearchScope.SelectedIndex = 0;
BeforeSearch();
}
@@ -442,14 +439,22 @@ namespace TextLocator
{
if (e.Key == Key.Enter)
{
- // 光标移除文本框
+ // ---- 光标移除文本框
SearchText.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
- // 搜索按钮时,下拉框和其他筛选条件全部恢复默认值
+ // ---- 搜索按钮时,下拉框和其他筛选条件全部恢复默认值
+ // 取消匹配全词
MatchWords.IsChecked = false;
- OnlyFileName.IsChecked = false;
- (this.FindName("FileTypeAll") as RadioButton).IsChecked = true;
+
+ // 全部文件类型
+ ToggleButtonAutomationPeer toggleButtonAutomationPeer = new ToggleButtonAutomationPeer(_radioButtonAll);
+ IToggleProvider toggleProvider = toggleButtonAutomationPeer.GetPattern(PatternInterface.Toggle) as IToggleProvider;
+ toggleProvider.Toggle();
+
+ // 默认排序
SortOptions.SelectedIndex = 0;
+ // 文件名和内容
+ // SearchScope.SelectedIndex = 0;
BeforeSearch();
@@ -467,36 +472,14 @@ namespace TextLocator
{
// 如果文本为空则隐藏清空按钮,如果不为空则显示清空按钮
this.CleanButton.Visibility = this.SearchText.Text.Length > 0 ? Visibility.Visible : Visibility.Hidden;
- /*try
- {
- // 搜索关键词
- string text = SearchText.Text;
-
- // 替换特殊字符
- text = AppConst.REGEX_SPECIAL_CHARACTER.Replace(text, "");
-
- // 回写处理过的字符
- SearchText.Text = text;
-
- // 光标定位到最后
- SearchText.SelectionStart = SearchText.Text.Length;
-
- // 如果文本为空则隐藏清空按钮,如果不为空则显示清空按钮
- CleanButton.Visibility = text.Length > 0 ? Visibility.Visible : Visibility.Hidden;
- }
- catch { }*/
}
///
/// 搜索
///
/// 时间戳,用于校验为同一子任务;时间戳不相同表名父任务结束,子任务跳过执行
- /// 关键词
- /// 文件类型
- /// 排序类型
- /// 仅文件名
- /// 匹配全词
- private void Search(long timestamp, List keywords, string fileType, SortType sortType, bool onlyFileName = false, bool matchWords = false)
+ /// 搜索条件
+ private void Search(long timestamp, Entity.SearchParam searchParam)
{
if (!CheckIndexExist())
{
@@ -509,26 +492,14 @@ namespace TextLocator
{
try
{
- // 清空搜索结果列表
+ // 1、---- 清空搜索结果列表
Dispatcher.Invoke(new Action(() =>
{
this.SearchResultList.Items.Clear();
}));
- // 保存当前搜索条件
- _searchParam = new Entity.SearchParam()
- {
- Keywords = keywords,
- FileType = fileType,
- SortType = sortType,
- IsMatchWords = matchWords,
- IsOnlyFileName = onlyFileName,
- PageSize = PageSize,
- PageIndex = PageNow
- };
-
- // 查询列表(参数,消息回调)
- Entity.SearchResult searchResult = IndexCore.Search(_searchParam, ShowStatus);
+ // 2、---- 查询列表(参数,消息回调)
+ Entity.SearchResult searchResult = IndexCore.Search(searchParam, ShowStatus);
// 验证列表数据
if (null == searchResult || searchResult.Results.Count <= 0)
@@ -540,7 +511,7 @@ namespace TextLocator
return;
}
- // 遍历结果
+ // 3、---- 遍历结果
foreach (Entity.FileInfo fileInfo in searchResult.Results)
{
if (_timestamp != timestamp)
@@ -549,11 +520,11 @@ namespace TextLocator
}
this.Dispatcher.Invoke(new Action(() =>
{
- this.SearchResultList.Items.Add(new FileInfoItem(fileInfo));
+ this.SearchResultList.Items.Add(new FileInfoItem(fileInfo, searchParam.SearchRegion));
}));
}
- // 分页总数
+ // 4、---- 分页总数
this.Dispatcher.BeginInvoke(new Action(() =>
{
// 如果总条数小于等于分页条数,则不显示分页
@@ -605,15 +576,11 @@ namespace TextLocator
}
}
+ // 切换页码
private void PageBar_PageIndexChanged(object sender, RoutedPropertyChangedEventArgs e)
{
log.Debug($"pageIndex : {e.OldValue} => {e.NewValue}");
- // 搜索按钮时,下拉框和其他筛选条件全部恢复默认值
- MatchWords.IsChecked = false;
- OnlyFileName.IsChecked = false;
- (this.FindName("FileTypeAll") as RadioButton).IsChecked = true;
-
BeforeSearch(e.NewValue);
}
@@ -665,12 +632,13 @@ namespace TextLocator
IToggleProvider toggleProvider = toggleButtonAutomationPeer.GetPattern(PatternInterface.Toggle) as IToggleProvider;
toggleProvider.Toggle();
- // 仅文件名 和 全词匹配取消选中
- OnlyFileName.IsChecked = false;
- MatchWords.IsChecked = false;
+ // 匹配全词
+ MatchWords.IsChecked = false;
// 排序类型切换为默认
- this.SortOptions.SelectedIndex = 0;
+ SortOptions.SelectedIndex = 0;
+ // 文件名和内容
+ SearchScope.SelectedIndex = 0;
// -------- 搜索结果列表
// 搜索结果列表清空
@@ -838,62 +806,40 @@ namespace TextLocator
#endregion
#region 界面事件
- ///
- /// 文件类型过滤器选中事件
- ///
- ///
- ///
- private void FileType_Checked(object sender, RoutedEventArgs e)
- {
- if (!"全部".Equals((sender as RadioButton).Content) && GetSearchTextKeywords().Count <= 0)
- {
- ResetSearchResult();
- return;
- }
-
- FileTypeFilter.Tag = (sender as RadioButton).Content;
-
- BeforeSearch();
- }
///
- /// 仅文件名选中时
+ /// 搜索域切换事件
///
///
///
- private void OnlyFileName_Checked(object sender, RoutedEventArgs e)
+ private void SearchScope_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
-
BeforeSearch();
}
-
///
- /// 仅文件名取消选中时
+ /// 文件类型过滤器选中事件
///
///
///
- private void OnlyFileName_Unchecked(object sender, RoutedEventArgs e)
+ private void FileType_Checked(object sender, RoutedEventArgs e)
{
- BeforeSearch();
- }
+ if (!"全部".Equals((sender as RadioButton).Content) && GetSearchTextKeywords().Count <= 0)
+ {
+ ResetSearchResult();
+ return;
+ }
- ///
- /// 匹配全瓷选中
- ///
- ///
- ///
- private void MatchWords_Checked(object sender, RoutedEventArgs e)
- {
+ SearchFileType.Tag = (sender as RadioButton).Tag;
BeforeSearch();
}
///
- /// 匹配全瓷取消选中
+ /// 匹配全词
///
///
///
- private void MatchWords_Unchecked(object sender, RoutedEventArgs e)
+ private void CheckChange(object sender, RoutedEventArgs e)
{
BeforeSearch();
}
@@ -957,20 +903,19 @@ namespace TextLocator
}
///
- /// 搜索区域
+ /// 搜索区双击事件
///
///
///
- private void FolderPaths_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
+ private void AreaInfos_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
AreaWindow areaDialog = new AreaWindow();
- areaDialog.Topmost = true;
areaDialog.Owner = this;
+ areaDialog.Topmost = true;
areaDialog.ShowDialog();
- if (areaDialog.DialogResult == true)
- {
- InitializeAppConfig();
- }
+
+ // 不管是否修改都刷新
+ InitializeAppConfig();
}
///
@@ -1082,120 +1027,163 @@ namespace TextLocator
// 提示语
string tag = isRebuild ? "重建" : "更新";
- var taskMark = TaskTime.StartNew();
-
- // 1、-------- 开始获取文件列表
- string msg = string.Format("开始{0}索引,正在扫描文件...", tag);
- log.Info(msg);
- ShowStatus(msg);
- var fileScanMark = TaskTime.StartNew();
- // 定义全部文件列表
- List allFilePaths = new List();
- // 定义更新文件列表
- List updateFilePaths = new List();
- // 定义删除文件列表
- List deleteFilePaths = new List();
-
- // 扫描需要建立索引的文件列表
- foreach (string s in _indexFolders)
+ // 1、-------- 定义总数
+ // 文件总数
+ int fileTotalCount = 0;
+ // 更新总数
+ int updateTotalCount = 0;
+ // 删除总数
+ int deleteTotalCount = 0;
+ // 错误总数
+ int errorTotalCount = 0;
+
+ // 总任务消耗时间
+ var totalTaskMark = TaskTime.StartNew();
+
+ // 2、-------- 遍历搜索区
+ List areaInfos = AreaUtil.GetEnableAreaInfoList();
+ foreach(Entity.AreaInfo areaInfo in areaInfos)
{
- log.Info("目录:" + s);
- // 获取文件信息列表
- FileUtil.GetAllFiles(allFilePaths, s, _exclusionFolderRegex);
- }
+ var singleTaskMark = TaskTime.StartNew();
- msg = string.Format("文件扫描完成,文件总数:{0},耗时:{1}。开始分析需要更新的文件列表...", allFilePaths.Count, fileScanMark.ConsumeTime);
- log.Info(msg);
- ShowStatus(msg);
+ // 不同区域,索引分开记录
+ string areaIdIndex = areaInfo.AreaId + "Index";
- var fileAnalysisMark = TaskTime.StartNew();
- // 如果是更新操作,判断文件格式是否变化 -> 判断文件更新时间变化找到最终需要更新的文件列表
- // 2、-------- 获取需要删除的文件列表
- if (AppUtil.ReadSectionList("FileIndex") != null)
- {
- foreach (string filePath in AppUtil.ReadSectionList("FileIndex"))
+ // 重建则删除全部标记
+ if (isRebuild)
{
- // 不存在,则表示文件已删除
- if (!allFilePaths.Contains(filePath))
+ // 重建时,删除全部标记
+ AppUtil.DeleteSection(areaIdIndex);
+ }
+
+ // 2.1、-------- 开始获取文件列表
+ string msg = string.Format("搜索区【{0}】,开始扫描文件...", areaInfo.AreaName);
+ log.Info(msg);
+ ShowStatus(msg);
+
+ var scanTaskMark = TaskTime.StartNew();
+ // 定义全部文件列表
+ List allFilePaths = new List();
+ // 定义更新文件列表
+ List updateFilePaths = new List();
+ // 定义删除文件列表
+ List deleteFilePaths = new List();
+
+ // 2.2、-------- 获取支持的文件类型后缀
+ Regex fileExtRegex = new Regex(@"^.+\.(" + FileTypeUtil.ConvertToFileTypeExts(areaInfo.AreaFileTypes, "|") + ")$");
+
+ // 扫描需要建立索引的文件列表
+ foreach (string s in areaInfo.AreaFolders)
+ {
+ log.Info("目录:" + s);
+ // 获取文件信息列表
+ FileUtil.GetAllFiles(allFilePaths, s, fileExtRegex);
+ }
+
+ msg = string.Format("搜索区【{0}】,文件扫描完成;文件数:{1},耗时:{2};开始分析需要更新的文件列表...", areaInfo.AreaName, allFilePaths.Count, scanTaskMark.ConsumeTime);
+ log.Info(msg);
+ ShowStatus(msg);
+
+ // 2.3、-------- 获取需要删除的文件列表
+ if (AppUtil.ReadSectionList(areaIdIndex) != null)
+ {
+ foreach (string filePath in AppUtil.ReadSectionList(areaIdIndex))
{
- deleteFilePaths.Add(filePath);
- AppUtil.WriteValue("FileIndex", filePath, null);
+ // 不存在,则表示文件已删除
+ if (!allFilePaths.Contains(filePath))
+ {
+ deleteFilePaths.Add(filePath);
+ AppUtil.WriteValue(areaIdIndex, filePath, null);
+ }
}
}
- }
-
- // 3、-------- 更新是才需要校验,重建是直接跳过
- if (isRebuild)
- {
- // 3.1、重建时为全部文件
- updateFilePaths.AddRange(allFilePaths);
- }
- else
- {
- // 3.2、获取需要更新的文件列表
- foreach (string filePath in allFilePaths)
+
+ // 2.4、-------- 如果是更新操作,判断文件格式是否变化 -> 判断文件更新时间变化找到最终需要更新的文件列表
+ var analysisTaskMark = TaskTime.StartNew();
+ // 更新是才需要校验,重建是直接跳过
+ if (!isRebuild)
{
- try
+ // 更新:需要更新的文件列表
+ foreach (string filePath in allFilePaths)
{
- FileInfo fileInfo = new FileInfo(filePath);
- // 当前文件修改时间
- string lastWriteTime = fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss.ffff");
- // 上次索引时文件修改时间标记
- string lastWriteTimeTag = AppUtil.ReadValue("FileIndex", filePath);
-
- // 文件修改时间不一致,说明文件已修改
- if (!lastWriteTime.Equals(lastWriteTimeTag))
+ try
{
- updateFilePaths.Add(filePath);
+ FileInfo fileInfo = new FileInfo(filePath);
+ // 当前文件修改时间
+ string lastWriteTime = fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss.ffff");
+ // 上次索引时文件修改时间标记
+ string lastWriteTimeTag = AppUtil.ReadValue(areaIdIndex, filePath);
+
+ // 文件修改时间不一致,说明文件已修改
+ if (!lastWriteTime.Equals(lastWriteTimeTag))
+ {
+ updateFilePaths.Add(filePath);
+ }
}
+ catch { }
}
- catch { }
}
- }
+ else
+ {
+ // 重建:全部文件列表
+ updateFilePaths.AddRange(allFilePaths);
+ }
- msg = string.Format("文件分析完成,{0}总数:{1},删除总数:{2},耗时:{3}。开始{4}索引...", tag, updateFilePaths.Count, deleteFilePaths.Count, fileAnalysisMark.ConsumeTime, tag);
- log.Info(msg);
- ShowStatus(msg);
+ msg = string.Format("搜索区【{0}】,文件分析完成;{1}数:{2},删除数:{3},耗时:{4};开始{5}索引...", areaInfo.AreaName, tag, updateFilePaths.Count, deleteFilePaths.Count, analysisTaskMark.ConsumeTime, tag);
+ log.Info(msg);
+ ShowStatus(msg);
- // 4、-------- 如果是更新操作,判断文件格式是否变化 -> 判断文件更新时间变化找到最终需要更新的文件列表
- // 验证扫描文件列表是否为空
- if (updateFilePaths.Count <= 0 && deleteFilePaths.Count <= 0)
- {
- build = false;
+ // 2.5、-------- 验证扫描文件列表是否为空(如果是更新操作,判断文件格式是否变化 -> 判断文件更新时间变化找到最终需要更新的文件列表)
+ if (updateFilePaths.Count <= 0 && deleteFilePaths.Count <= 0)
+ {
+ build = false;
+ msg = string.Format("搜索区【{0}】,无更新文件和删除文件,不{1}索引...", areaInfo.AreaName, tag);
+ log.Info(msg);
+ ShowStatus(msg);
+ continue;
+ }
- ShowStatus("就绪");
+ // 后台执行时修改为最小线程单位,反之恢复为系统配置线程数
+ AppCore.SetThreadPoolSize(!isBackground);
- // 标记索引文件数量 和 最后更新时间
- AppUtil.WriteValue("AppConfig", "IndexFileCount", allFilePaths.Count + "");
- AppUtil.WriteValue("AppConfig", "LastIndexTime", DateTime.Now.ToString());
- return;
- }
+ // 2.6、-------- 创建索引方法
+ int errorCount = IndexCore.CreateIndex(areaInfo.AreaId, updateFilePaths, deleteFilePaths, isRebuild, ShowStatus);
- // 后台执行时修改为最小线程单位,反之恢复为系统配置线程数
- AppCore.SetThreadPoolSize(!isBackground);
+ // 2.7、-------- 当前区域完成日志
+ msg = string.Format("搜索区【{0}】,索引{1}完成;{2}数:{3},删除数:{4},错误数:{5},共用时:{6}。", areaInfo.AreaName, tag, tag, updateFilePaths.Count, deleteFilePaths.Count, errorCount, singleTaskMark.ConsumeTime);
+ log.Info(msg);
+ ShowStatus(msg);
- // 5、-------- 创建索引方法
- int errorCount = IndexCore.CreateIndex(updateFilePaths, deleteFilePaths, isRebuild, ShowStatus);
- msg = string.Format("索引{0}完成,{1}总数:{2},删除数:{3},错误数:{4},共用时:{5}。", tag, tag, updateFilePaths.Count, deleteFilePaths.Count, errorCount, taskMark.ConsumeTime);
- log.Info(msg);
- // 显示状态
- ShowStatus(msg);
+ Dispatcher.BeginInvoke(new Action(() =>
+ {
+ MessageCore.ShowSuccess(msg);
+ }));
- Dispatcher.BeginInvoke(new Action(() =>
- {
- MessageCore.ShowSuccess(msg);
- }));
- // 标记索引文件数量 和 最后更新时间
- AppUtil.WriteValue("AppConfig", "IndexFileCount", allFilePaths.Count + "");
+ // 2.8、-------- 记录文件总数、更新总数、删除总数、错误总数
+ fileTotalCount = fileTotalCount + allFilePaths.Count;
+ updateTotalCount = updateTotalCount + updateFilePaths.Count;
+ deleteTotalCount = deleteTotalCount + deleteFilePaths.Count;
+ errorTotalCount = errorTotalCount + errorCount;
+ }
+
+ // 3、-------- 完成日志
+ string message = string.Format("索引{0}完成。区域数:{1},{2}数:{3},删除数:{4},错误数:{5},共用时:{6}。", tag, areaInfos.Count, tag, updateTotalCount, deleteTotalCount, errorTotalCount, totalTaskMark.ConsumeTime);
+ log.Info(message);
+ ShowStatus(message);
+
+ // 4、-------- 标记索引文件数量 和 最后更新时间
+ AppUtil.WriteValue("AppConfig", "FileTotalCount", fileTotalCount + "");
AppUtil.WriteValue("AppConfig", "LastIndexTime", DateTime.Now.ToString());
- // 6、-------- 构建结束
+ // 5、-------- 构建结束
build = false;
}
catch (Exception ex)
{
log.Error("构建索引错误:" + ex.Message, ex);
+
+ build = false;
}
}
@@ -1274,6 +1262,7 @@ namespace TextLocator
// 预览搜索关键词高亮
PreviewSearchTextHighlighted();
}
+
///
/// 预览搜索关键词高亮
///
@@ -1332,6 +1321,7 @@ namespace TextLocator
private List GetSearchTextKeywords()
{
string searchText = SearchText.Text.Trim();
+
// 清理特殊字符
// 申明关键词列表
@@ -1380,6 +1370,7 @@ namespace TextLocator
/// 指定页
private void BeforeSearch(int page = 1)
{
+ // 1、---- 搜索信息预处理
// 还原分页count
if (page != PageNow)
{
@@ -1392,25 +1383,15 @@ namespace TextLocator
}));
}
- object filter = FileTypeFilter.Tag;
- if (filter == null || filter.Equals("全部"))
- {
- filter = null;
- }
-
// 获取搜索关键词列表
List keywords = GetSearchTextKeywords();
-
if (keywords.Count <= 0)
{
return;
}
- /*if (build)
- {
- MessageCore.ShowWarning("索引构建中,请稍等。");
- return;
- }*/
+
+ // 2、---- 预览信息还原
// 预览区打开文件和文件夹标记清空
OpenFile.Tag = null;
OpenFolder.Tag = null;
@@ -1430,17 +1411,27 @@ namespace TextLocator
// 预览切换标记清空
SwitchPreview.Tag = null;
- // 记录时间戳
+
+ // 3、---- 生成本次搜索时间戳
_timestamp = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds);
- // 搜索
+
+ // 4、---- 构造搜索条件并保存(保存的搜索条件需要用于数据导出)
+ _searchParam = new Entity.SearchParam()
+ {
+ Keywords = keywords,
+ FileType = (FileType)SearchFileType.Tag,
+ SortType = (SortType)SortOptions.SelectedValue,
+ IsMatchWords = (bool)MatchWords.IsChecked,
+ SearchRegion = (SearchRegion)SearchScope.SelectedValue,
+ PageSize = PageSize,
+ PageIndex = PageNow
+ };
+
+ // 5、---- 搜索
Search(
_timestamp,
- keywords,
- filter == null ? null : filter + "",
- (SortType)SortOptions.SelectedValue,
- (bool)OnlyFileName.IsChecked,
- (bool)MatchWords.IsChecked
+ _searchParam
);
}
#endregion
diff --git a/TextLocator/Properties/AssemblyInfo.cs b/TextLocator/Properties/AssemblyInfo.cs
index 46b0b09d8ced3a543f72ababfd5bfdfab31513a6..74f692e36a4548318b4d94634efa6d00a127ac93 100644
--- a/TextLocator/Properties/AssemblyInfo.cs
+++ b/TextLocator/Properties/AssemblyInfo.cs
@@ -49,8 +49,8 @@ using System.Windows;
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.2.16")]
-[assembly: AssemblyFileVersion("1.2.16.0")]
+[assembly: AssemblyVersion("2.0.10.0")]
+[assembly: AssemblyFileVersion("2.0.10.0")]
// log4net
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
\ No newline at end of file
diff --git a/TextLocator/Service/PdfFileService.cs b/TextLocator/Service/PdfFileService.cs
index 2f3a1059037a681d833e54e59b9052520cf0a4d7..62dd2438d2ab371b4f6cf9cf5174eea99f0b3754 100644
--- a/TextLocator/Service/PdfFileService.cs
+++ b/TextLocator/Service/PdfFileService.cs
@@ -1,9 +1,11 @@
-using log4net;
+using java.io;
+using log4net;
using org.apache.pdfbox.pdmodel;
using org.apache.pdfbox.util;
using System;
using System.IO;
using System.Text;
+using TextLocator.Factory;
namespace TextLocator.Service
{
diff --git a/TextLocator/SettingWindow.xaml b/TextLocator/SettingWindow.xaml
index 17adfa39a29ef1ea6f38cde75a77e0e944c0f0d1..81b6b5a3baea0270e2f4c04df20972d48a0a8b2e 100644
--- a/TextLocator/SettingWindow.xaml
+++ b/TextLocator/SettingWindow.xaml
@@ -7,7 +7,7 @@
xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore"
mc:Ignorable="d"
x:Name="hotkey"
- Title="设置" Height="380" Width="520" WindowStartupLocation="CenterOwner" WindowStyle="ToolWindow" ResizeMode="CanMinimize" Icon="/Resource/App.ico" Loaded="Window_Loaded" Closed="Window_Closed" >
+ Title="设置" Height="380" Width="520" WindowStartupLocation="CenterScreen" WindowStyle="ToolWindow" ResizeMode="CanMinimize" Icon="/Resource/App.ico" Loaded="Window_Loaded" Closed="Window_Closed" >
diff --git a/TextLocator/TextLocator.csproj b/TextLocator/TextLocator.csproj
index c126728641eae0262fcfd946bb6fff8daad4c75c..6d1712a48917b90115d6d866954252d2d4803b2a 100644
--- a/TextLocator/TextLocator.csproj
+++ b/TextLocator/TextLocator.csproj
@@ -264,10 +264,21 @@
MSBuild:Compile
Designer
+
+ AreaEditWindow.xaml
+
+
+ AreaInfoItem.xaml
+
+
+ AreaWindow.xaml
+
+
+
@@ -300,9 +311,6 @@
-
- AreaWindow.xaml
-
@@ -323,12 +331,25 @@
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+ Designer
+
MSBuild:Compile
Designer
@@ -357,10 +378,6 @@
MainWindow.xaml
Code
-
- Designer
- MSBuild:Compile
-
Designer
MSBuild:Compile
@@ -385,22 +402,22 @@
Settings.Designer.cs
- PreserveNewest
+ Always
- PreserveNewest
+ Always
- PreserveNewest
+ Always
- PreserveNewest
+ Always
- PreserveNewest
+ Always
- PreserveNewest
+ Always
@@ -429,16 +446,16 @@
- PreserveNewest
+ Always
- PreserveNewest
+ Always
- PreserveNewest
+ Always
- PreserveNewest
+ Always
diff --git a/TextLocator/Util/AppUtil.cs b/TextLocator/Util/AppUtil.cs
index d257e781f3268981db328d7db0707f9f95dc5084..f6b2b43926a0d3663670864a4ed9f5165daf71b9 100644
--- a/TextLocator/Util/AppUtil.cs
+++ b/TextLocator/Util/AppUtil.cs
@@ -7,6 +7,7 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
+using TextLocator.Core;
namespace TextLocator.Util
{
@@ -48,8 +49,23 @@ namespace TextLocator.Util
// ini文件初始化
Initialize();
- // 加载节点下全部Key-Value
- LoadAllKeyValue("FileIndex");
+ Thread t = new Thread(() =>
+ {
+ // 加载区域配置
+ LoadAllKeyValue(AppConst.AREA_CONFIG_KEY);
+
+ List areaList = ReadSectionList(AppConst.AREA_CONFIG_KEY);
+ foreach (string areaId in areaList)
+ {
+ LoadAllKeyValue(areaId);
+ }
+ });
+ t.Priority = ThreadPriority.AboveNormal;
+ t.Start();
+
+
+
+
}
///
@@ -103,15 +119,16 @@ namespace TextLocator.Util
if (sectionDic.ContainsKey(key))
{
if (string.IsNullOrEmpty(value))
- {
sectionDic.Remove(key);
- }
else
- {
sectionDic[key] = value;
- }
}
- _AppIniCache[section] = sectionDic;
+ else
+ sectionDic.Add(key, value);
+ if (_AppIniCache.ContainsKey(section))
+ _AppIniCache[section] = sectionDic;
+ else
+ _AppIniCache.Add(section, sectionDic);
WritePrivateProfileString(section, key, value, _AppIniFile);
}
@@ -159,8 +176,15 @@ namespace TextLocator.Util
lock(locker)
{
Dictionary sectionDic = _AppIniCache.ContainsKey(section) ? _AppIniCache[section] : new Dictionary();
- sectionDic[key] = def;
- _AppIniCache[section] = sectionDic;
+ if (sectionDic.ContainsKey(key))
+ sectionDic[key] = def;
+ else
+ sectionDic.Add(key, def);
+
+ if (_AppIniCache.ContainsKey(section))
+ _AppIniCache[section] = sectionDic;
+ else
+ _AppIniCache.Add(section, sectionDic);
}
}
return def;
@@ -230,46 +254,47 @@ namespace TextLocator.Util
///
private static void LoadAllKeyValue(string section)
{
- Thread t = new Thread(() =>
+ try
{
- try
- {
- // 默认为32767(32.767KB),设置为128000000(128MB)
- uint MAX_BUFFER = 256000000;
- // 返回值[返回值形式为 key=value,例如 Color=Red]
- string[] items = new string[0];
+ // 默认为32767(32.767KB),设置为128000000(128MB)
+ uint MAX_BUFFER = 256000000;
+ // 返回值[返回值形式为 key=value,例如 Color=Red]
+ string[] items = new string[0];
- //分配内存
- IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char));
+ //分配内存
+ IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char));
- uint bytesReturned = GetPrivateProfileSection(section, pReturnedString, MAX_BUFFER, _AppIniFile);
+ uint bytesReturned = GetPrivateProfileSection(section, pReturnedString, MAX_BUFFER, _AppIniFile);
- if (!(bytesReturned == MAX_BUFFER - 2) || (bytesReturned == 0))
- {
- string returnedString = Marshal.PtrToStringAuto(pReturnedString, (int)bytesReturned);
- items = returnedString.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
- }
+ if (!(bytesReturned == MAX_BUFFER - 2) || (bytesReturned == 0))
+ {
+ string returnedString = Marshal.PtrToStringAuto(pReturnedString, (int)bytesReturned);
+ items = returnedString.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
+ }
- // 释放内存
- Marshal.FreeCoTaskMem(pReturnedString);
+ // 释放内存
+ Marshal.FreeCoTaskMem(pReturnedString);
- foreach (string entry in items)
- {
- string[] v = entry.Split('=');
+ foreach (string entry in items)
+ {
+ string[] v = entry.Split('=');
- // 获取 section 节点
- Dictionary sectionDic = _AppIniCache.ContainsKey(section) ? _AppIniCache[section] : new Dictionary();
- // 设置 section 节点子项
+ // 获取 section 节点
+ Dictionary sectionDic = _AppIniCache.ContainsKey(section) ? _AppIniCache[section] : new Dictionary();
+ // 设置 section 节点子项
+ if (sectionDic.ContainsKey(v[0]))
sectionDic[v[0]] = v[1];
- // 回写 section 节点
+ else
+ sectionDic.Add(v[0], v[1]);
+ // 回写 section 节点
+ if (_AppIniCache.ContainsKey(section))
_AppIniCache[section] = sectionDic;
- }
- log.Debug("加载" + section + "节点下全部键值,总数:" + _AppIniCache.Count);
+ else
+ _AppIniCache.Add(section, sectionDic);
}
- catch { }
- });
- t.Priority = ThreadPriority.AboveNormal;
- t.Start();
+ log.Debug("加载" + section + "节点下全部键值,总数:" + _AppIniCache.Count);
+ }
+ catch { }
}
#endregion
diff --git a/TextLocator/Util/AreaUtil.cs b/TextLocator/Util/AreaUtil.cs
new file mode 100644
index 0000000000000000000000000000000000000000..06a41675b3850e435cc1b3d73726817d24cbe99e
--- /dev/null
+++ b/TextLocator/Util/AreaUtil.cs
@@ -0,0 +1,223 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using TextLocator.Core;
+using TextLocator.Entity;
+
+namespace TextLocator.Util
+{
+ ///
+ /// 区域工具类
+ ///
+ public class AreaUtil
+ {
+ ///
+ /// 区域配置
+ ///
+ private static string AreaConfig = AppConst.AREA_CONFIG_KEY;
+ ///
+ /// 区域名称
+ ///
+ private static string AreaName = "AreaName";
+ ///
+ /// 区域文件夹
+ ///
+ private static string AreaFolders = "AreaFolders";
+ ///
+ /// 区域文件类型
+ ///
+ private static string AreaFileTypes = "AreaFileTypes";
+
+ ///
+ /// 私有构造方法
+ ///
+ private AreaUtil() { }
+
+ ///
+ /// 获取区域信息列表
+ ///
+ ///
+ public static List GetAreaInfoList()
+ {
+ List areaInfoList = new List();
+
+ List areaList = AppUtil.ReadSectionList(AreaConfig);
+ if (areaList != null)
+ {
+ foreach (string areaId in areaList)
+ {
+ // 根据区域获取明细配置
+ bool isEnable = bool.Parse(AppUtil.ReadValue(AreaConfig, areaId, "False"));
+ // 区域显示名称
+ string areaName = AppUtil.ReadValue(areaId, AreaName, "区域名称");
+ // 区域文件夹
+ string folders = AppUtil.ReadValue(areaId, AreaFolders, "");
+ // 区域文件类型
+ string fileTypeNames = AppUtil.ReadValue(areaId, AreaFileTypes, "");
+
+ // 区域文件夹解析
+ List areaFolders = new List();
+ if (!string.IsNullOrEmpty(folders))
+ {
+ areaFolders = folders.Split(',').ToList();
+ }
+ // 区域文件类型解析
+ List areaFileTypes = new List();
+ if (!string.IsNullOrEmpty(fileTypeNames))
+ {
+ List tmps = fileTypeNames.Split(',').ToList();
+ foreach (string tmp in tmps)
+ {
+ areaFileTypes.Add((Enums.FileType)System.Enum.Parse(typeof(Enums.FileType), tmp));
+ }
+ }
+
+ // 构造数据对象
+ AreaInfo areaInfo = new AreaInfo()
+ {
+ IsEnable = isEnable,
+ AreaId = areaId,
+ AreaName = areaName,
+ AreaFolders = areaFolders,
+ AreaFileTypes = areaFileTypes
+ };
+ // 全部搜索区
+ areaInfoList.Add(areaInfo);
+ }
+ }
+ // 区域信息列表为空(填充默认区域信息列表)
+ if (areaInfoList.Count <= 0)
+ {
+ AreaInfo areaInfo = new AreaInfo()
+ {
+ IsEnable = true,
+ AreaId = "AreaDefault",
+ AreaName = "默认区域",
+ AreaFolders = new string[] { Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), Environment.GetFolderPath(Environment.SpecialFolder.Desktop) }.ToList(),
+ AreaFileTypes = FileTypeUtil.GetFileTypesNotAll()
+ };
+ areaInfoList.Add(areaInfo);
+ }
+ // 保存信息
+ foreach (AreaInfo areaInfo in areaInfoList)
+ {
+ // 区域根信息
+ AppUtil.WriteValue(AreaConfig, areaInfo.AreaId, areaInfo.IsEnable + "");
+
+ // 区域配置
+ AppUtil.WriteValue(areaInfo.AreaId, AreaName, areaInfo.AreaName);
+ AppUtil.WriteValue(areaInfo.AreaId, AreaFolders, string.Join(",", areaInfo.AreaFolders.ToArray()));
+ }
+ return areaInfoList;
+ }
+
+ ///
+ /// 获取启用的区域信息列表
+ ///
+ ///
+ public static List GetEnableAreaInfoList()
+ {
+ // 获取全部区域信息列表
+ List allAreaInfoList = GetAreaInfoList();
+ return allAreaInfoList.Where(areaInfo => areaInfo.IsEnable).ToList();
+ }
+
+ ///
+ /// 获取禁用的区域信息列表
+ ///
+ ///
+ public static List GetDisableAreaInfoList()
+ {
+ // 获取全部区域信息列表
+ List allAreaInfoList = GetAreaInfoList();
+ return allAreaInfoList.Where(areaInfo => !areaInfo.IsEnable).ToList();
+ }
+
+ ///
+ /// 保存区域信息
+ ///
+ ///
+ public static void SaveAreaInfo(AreaInfo areaInfo)
+ {
+ // 区域名称
+ AppUtil.WriteValue(areaInfo.AreaId, AreaName, areaInfo.AreaName);
+ // 区域文件夹
+ AppUtil.WriteValue(areaInfo.AreaId, AreaFolders, areaInfo.AreaFolders != null ? string.Join(",", areaInfo.AreaFolders.ToArray()) : null);
+ // 区域文件类型
+ AppUtil.WriteValue(areaInfo.AreaId, AreaFileTypes, areaInfo.AreaFileTypes != null ? string.Join(",", areaInfo.AreaFileTypes.ToArray()) : null);
+
+ // 区域列表
+ AppUtil.WriteValue(AreaConfig, areaInfo.AreaId, areaInfo.IsEnable + "");
+ }
+
+ ///
+ /// 删除区域信息
+ ///
+ ///
+ public static void DeleteAreaInfo(AreaInfo areaInfo)
+ {
+ // 区域名称
+ AppUtil.WriteValue(areaInfo.AreaId, AreaName, null);
+ // 区域文件夹
+ AppUtil.WriteValue(areaInfo.AreaId, AreaFolders, null);
+ // 区域文件类型
+ AppUtil.WriteValue(areaInfo.AreaId, AreaFileTypes, null);
+
+ // 区域列表
+ AppUtil.WriteValue(AreaConfig, areaInfo.AreaId, null);
+ }
+
+ ///
+ /// 获取全部区域文件夹列表
+ ///
+ ///
+ public static List GetAreaFolderList()
+ {
+ List areaFolderList = new List();
+
+ List areaList = AppUtil.ReadSectionList(AreaConfig);
+ if (areaList != null)
+ {
+ foreach (string areaId in areaList)
+ {
+ // 区域文件夹
+ string folders = AppUtil.ReadValue(areaId, AreaFolders, "");
+ List areaFolders = new List();
+ if (!string.IsNullOrEmpty(folders))
+ {
+ areaFolders = folders.Split(',').ToList();
+ }
+ areaFolderList.AddRange(areaFolders);
+ }
+ }
+ return areaFolderList;
+ }
+
+ ///
+ /// 获取不包含自己的区域名称列表
+ ///
+ /// 区域信息
+ ///
+ public static List GetAreaNameListRuleOut(AreaInfo areaInfo)
+ {
+ List areaNameList = new List();
+ List areaList = AppUtil.ReadSectionList(AreaConfig);
+ if (areaList != null)
+ {
+ foreach (string areaId in areaList)
+ {
+ // 跳过区域ID相同的
+ if (areaId.Equals(areaInfo.AreaId))
+ {
+ continue;
+ }
+ // 区域显示名称
+ string areaName = AppUtil.ReadValue(areaId, AreaName, "区域名称");
+ // 加入区域名称列表
+ areaNameList.Add(areaName);
+ }
+ }
+ return areaNameList;
+ }
+ }
+}
diff --git a/TextLocator/Util/FileTypeUtil.cs b/TextLocator/Util/FileTypeUtil.cs
index c9a0d5b87134f8c6e30250139997e827b58e84fe..3ba5a95b04e1584a1132771d3404cb94954b1a07 100644
--- a/TextLocator/Util/FileTypeUtil.cs
+++ b/TextLocator/Util/FileTypeUtil.cs
@@ -1,5 +1,7 @@
using System;
+using System.Collections.Generic;
using System.IO;
+using System.Text;
using TextLocator.Enums;
namespace TextLocator.Util
@@ -55,21 +57,39 @@ namespace TextLocator.Util
///
/// 文件类型后缀列表(ext1,ext2...)
///
+ /// 文件类型列表
/// 分隔符,默认【,】
///
- public static string GetFileTypeExts(string separator = ",")
+ public static string ConvertToFileTypeExts(List fileTypes, string separator = ",")
{
- string fileTypeExts = "";
+ string exts = "";
// 遍历文件类型,根据后缀查找文件类型
- foreach (FileType ft in Enum.GetValues(typeof(FileType)))
+ foreach (FileType ft in fileTypes)
{
- // 获取描述
string description = ft.GetDescription();
if (!string.IsNullOrEmpty(description)) {
- fileTypeExts += description + separator;
+ exts += description + separator;
+ }
+ }
+ return exts.Substring(0, exts.Length - 1).Replace(",", separator);
+ }
+
+ ///
+ /// 获取不包含全部的文件类型列表
+ ///
+ ///
+ public static List GetFileTypesNotAll()
+ {
+ List fileTypes = new List();
+ foreach(FileType ft in Enum.GetValues(typeof(FileType)))
+ {
+ if (ft == FileType.全部)
+ {
+ continue;
}
+ fileTypes.Add(ft);
}
- return fileTypeExts.Substring(0, fileTypeExts.Length - 1).Replace(",", separator);
+ return fileTypes;
}
}
}
diff --git a/TextLocator/Util/FileUtil.cs b/TextLocator/Util/FileUtil.cs
index 323e7ad5d1c213eef238f4c575bdf6047bb1c5e8..e1e0337a66c5fcceef77718865ab39b99dc795b0 100644
--- a/TextLocator/Util/FileUtil.cs
+++ b/TextLocator/Util/FileUtil.cs
@@ -125,8 +125,8 @@ namespace TextLocator.Util
///
/// 文档列表
/// 根目录路径
- /// 过滤列表
- public static void GetAllFiles(List filePaths, string rootPath, Regex regexExclude = null)
+ /// 文件后缀正则
+ public static void GetAllFiles(List filePaths, string rootPath, Regex fileExtRegex)
{
// 根目录
DirectoryInfo rootDir = new DirectoryInfo(rootPath);
@@ -144,12 +144,12 @@ namespace TextLocator.Util
string dirPath = dir.FullName;
// 系统过滤:$RECYCLE|360REC|SYSTEM|TEMP|SYSTEM VOLUME INFOMATION
// 自定义过滤:
- if (AppConst.REGEX_EXCLUDE_KEYWORD.IsMatch(dirPath.ToUpper()) || (regexExclude != null && regexExclude.IsMatch(dirPath)))
+ if (AppConst.REGEX_EXCLUDE_KEYWORD.IsMatch(dirPath.ToUpper()))
{
continue;
}
// 递归调用
- GetAllFiles(filePaths, dirPath, regexExclude);
+ GetAllFiles(filePaths, dirPath, fileExtRegex);
}
}
catch (UnauthorizedAccessException ex) {
@@ -165,7 +165,7 @@ namespace TextLocator.Util
{
// 查找word文件
string[] paths = Directory.GetFiles(rootPath)
- .Where(file => AppConst.REGEX_FILE_EXT.IsMatch(file))
+ .Where(file => fileExtRegex.IsMatch(file))
.ToArray();
// 遍历每个文档
foreach (string path in paths)