Compare commits

...

66 Commits

Author SHA1 Message Date
iaom 7e296c325a 解决文件搜索接口在使用索引搜索根目录时无法搜到文件的问题 2023-06-16 09:27:48 +08:00
iaom d1bf50859a 解决当搜索UI关闭后未正确停止插件搜索线程的问题;解决遍历搜索时文件搜索插件长时间cpu占用较高的问题。 2023-06-14 06:21:18 +00:00
JunjieBai 3d13080b4c Add Tibetan translation of ukcc plugin. 2023-06-12 15:03:44 +08:00
JunjieBai a128cfb5b7 Add translations files of app widget. 2023-06-07 14:15:44 +08:00
iaom c871929ef1 同步子项目改动 2023-06-06 15:16:21 +08:00
JunjieBai 3b8c35c2c2 optimize global-settings;
Fix the problem that the search window cannot show because it was hidden by something while create-index-dialog is showing.
2023-06-02 17:17:54 +08:00
JunjieBai 5157a6be6c Modify the ts file of the ukcc plugin. 2023-05-23 10:59:00 +08:00
JunjieBai 322e8d95ee Increase the filtering of the unauthorized folders while add search dirs. 2023-05-22 08:39:43 +00:00
iaom 255518c245 搜索接口增加搜索结果通知机制和状态查询功能 2023-05-19 16:51:33 +08:00
iaom ed768ff48f 修复添加索引目录后索引状态未更新的问题 2023-05-15 11:35:06 +08:00
JunjieBai e52bc8ca76 Use json to optimize the config file of user's block dir. 2023-05-08 06:53:49 +00:00
iaom 02dfef8627 修复刚开机时应用搜索插件导致偶现卡死问题;优化搜索服务插件接口;优化搜索结果队列处理逻辑。 2023-05-06 17:26:20 +08:00
JunjieBai c91a74c66d Fix the problem that online applications can not jump to the description page in software center. 2023-05-05 17:25:57 +08:00
iaom df3332046f 修复搜索插件生命周期管理内存泄漏问题 2023-05-04 14:11:01 +08:00
iaom f5eaf99f6f 解决一处潜在的崩溃问题 2023-04-28 16:51:51 +08:00
JunjieBai 35818d321e Fix the problem that path witch is hidden dir or is not exists can be choosen as search&block dir. 2023-04-25 11:02:02 +08:00
iaom 94ea037203 解决一些编译问题 2023-04-24 18:40:47 +08:00
iaom d9db5ff896 Revert "增加索引目录时采用增量更新检验操作,避免重复索引"
This reverts commit 031ce8bbd8.
2023-04-24 18:33:30 +08:00
iaom e7676c887a 解决索引提示弹窗会挡住模态窗口的问题 2023-04-24 17:36:37 +08:00
iaom e5e62cd3f7 解决一些编译警告,删除一些无用代码,更新README 2023-04-24 14:07:56 +08:00
JunjieBai c5304dfe94 Remove some compilation warnings. 2023-04-24 09:28:42 +08:00
jixiaoxu 12d5e76cc5 修复文件内容索引更新时文件过滤判断逻辑的问题; 2023-04-21 17:20:31 +08:00
iaom 37e3de3cee 解决全局搜索中遍历搜索不能搜索到顶层文件夹的问题 2023-04-21 11:22:41 +08:00
iaom 80320ab9f2 补充编译依赖 2023-04-21 11:08:08 +08:00
iaom 543b766351 解决一些编译警告 2023-04-19 15:14:36 +08:00
iaom b172baca45 整理一些头文件引用,解决打包编译问题 2023-04-19 02:42:47 +00:00
JunjieBai 0e7d204f11 Fix the problem that the app search results contatins the auto-start apps. 2023-04-18 11:38:00 +08:00
JunjieBai b59d0a57d8 Add AUTO_START field.
Add a interface to get desktop file path by desktop file name.
2023-04-17 09:27:54 +00:00
iaom 65060337de 优化日志打印机制;删除部分无用代码. 2023-04-14 18:01:19 +08:00
JunjieBai 8f03c44ef4 Add a interface to set launched state.
Add a method to set value of field in database.
2023-04-14 15:57:39 +08:00
JunjieBai fbd391d110 Fix the proble that can not add '/' to the block dirs in ukcc plugin. 2023-04-12 17:16:30 +08:00
iaom 5481dd7ed8 搜索目录配置文件改为使用json存储. 2023-04-12 01:59:28 +00:00
JunjieBai eb0b77035d 修复没有默认打开方式时弹窗按钮为是而不是确定的问题。 2023-04-11 05:52:44 +00:00
iaom b03fb44f6c 更新README 2023-04-11 11:12:40 +08:00
iaom ff0dd3384a 补充部分文件copyright. 2023-04-11 10:21:51 +08:00
baijunjie 29e5ee6767 Optimize Dir Watcher. 2023-04-08 23:10:22 +08:00
iaom 6911e159ad 增加dirWatcher中部分兼容老版本的逻辑 2023-04-08 14:26:04 +08:00
iaom a2514a1d98 修复搜索接口当设置搜索目录为‘/’时无法搜到内容的问题 2023-04-07 10:21:07 +08:00
JunjieBai 5f4e172c0d Modify the trigger logic of app widget. 2023-04-06 09:50:04 +00:00
iaom 7babaf3147 增加重构的dirWatcher部分接口定义 2023-04-06 10:39:10 +08:00
iaom 031ce8bbd8 增加索引目录时采用增量更新检验操作,避免重复索引 2023-04-04 09:07:49 +00:00
iaom 7e670163fa
!81 修复移动位置时更新信号应用信息残缺的问题
Merge pull request !81 from 白俊杰/0404upstream
2023-04-04 09:02:32 +00:00
JunjieBai 610210a9a3 Fix the problem that the infos of update signal are incomplete. 2023-04-04 17:00:16 +08:00
iaom 993c8e30ea 增加volume manager用于获取设备挂载信息 2023-04-04 15:20:57 +08:00
JunjieBai e09044dfee Optimize the logic which change position and set state of favorites/top.
Optimize the logic of the database transaction.
2023-04-04 14:31:39 +08:00
iaom 366201ddf9 删除多余日志打印 2023-03-24 11:24:30 +08:00
iaom 6a96a0e2f0 同步子项目进度 2023-03-23 10:12:33 +08:00
iaom 87f4170a5e 增加UI针对屏幕尺寸变化时的自动更新位置操作 2023-03-23 10:02:25 +08:00
JunjieBai ea3913cb5b Fix the problem that the DONT_DISPLAY field is null in database. 2023-03-22 15:47:27 +08:00
JunjieBai 91b455341d Optimize the handle of subvolume while add index dir. 2023-03-21 17:12:40 +08:00
jixiaoxu 2760b30a2a 修复中文分词接口编译问题; 2023-03-20 15:34:05 +08:00
jixiaoxu 0725b5b097 中文分词接口统一处理; 2023-03-20 15:21:58 +08:00
iaom 308b9b642f 解决文件搜索插件判断索引状态有误的问题和文件图标获取失败的问题 2023-03-16 17:49:12 +08:00
JunjieBai 4a98056c06 Solve the problem that the database will delete all info while install desktop files. 2023-03-16 02:52:03 +00:00
iaom d354773177 更新搜索服务接口,完善应用搜索和文件搜索机制 2023-03-15 16:46:00 +08:00
JunjieBai bf22f0e150 Optimize the search app interface. 2023-03-14 16:13:11 +08:00
JunjieBai 0e267ac29c Optimize the interfaces which help to get apps' data. 2023-03-14 14:01:28 +08:00
JunjieBai f9a638c05b Add app infos in autostart dir.
Add DONT_DISPLAY field to database.

Use ApplicationInfoMap instead of the previous structure to transform apps' data.
2023-03-14 13:51:55 +08:00
iaom b1a8486bd1 更新应用数据服务的接口定义(未完成) 2023-03-09 11:16:05 +08:00
iaom 498147414d 手动删除索引顶层目录时更新监听目录缓存 2023-02-28 15:04:30 +08:00
iaom e53d13c54b 修改应用搜索插件接口图标返回格式 2023-02-27 13:49:46 +08:00
iaom 9b835b9686 优化inotify信号处理,解决若干由于信号处理不当导致的索引不正确问题 2023-02-27 05:48:08 +00:00
JunjieBai 04a9cb487e Add a method which can find the desktop file for the process by pid. 2023-02-23 03:44:32 +00:00
JunjieBai 68a1fc4f43 Fix the problem that the changePos interface cannot change top&favorites pos successful. 2023-02-20 10:02:49 +08:00
JunjieBai 7f2267d72a Fix the problem that the top and favorite state cannot be set to 0. 2023-02-15 09:45:21 +08:00
JunjieBai 738f116b83 optimize the signal transformer, modify the data struct of the signals. 2023-02-06 11:46:07 +08:00
187 changed files with 7340 additions and 4964 deletions

102
README.md
View File

@ -3,23 +3,26 @@
[dWIP] UKUI Search is a user-wide desktop search feature of UKUI desktop environment.
## 简介
狭义上的ukui-search指ukui桌面环境中的全局搜索应用目前最新版本为3.22.x.x。全局搜索应用提供了本地文件、文本内容、应用、设置项、便签等聚合搜索功能基于其文件索引功能可以为用户提供快速准确的搜索体验。
狭义上的ukui-search指ukui桌面环境中的全局搜索应用目前最新版本为4.0.x.x。全局搜索应用提供了本地文件、文本内容、应用、设置项、便签等聚合搜索功能基于其文件索引功能可以为用户提供快速准确的搜索体验。
广义的ukui-search除了包括全局搜索应用还包括在ukui桌面环境中的本地搜索服务以及其开发接口。基于文建索引服务应用搜索数据服务等基础数据源服务可以提供基于C++接口的搜索功能应用开发者可以通过引用动态库的形式直接使用其搜索功能。除此之外ukui桌面环境搜索服务还提供了一组基于Qt插件框架的插件接口用户可以通过继承接口以实现搜索功能的扩展。
以下提到的ukui-search如无说明均指后者。
ukui-search 目前被打包成6个包openkylin
ukui-search 目前被打包成9个包openkylin
+ ukui-search_xxxxxx.deb
+ ukui-search-service_xxxx.deb
+ libukui-search-dev_xxxxx.deb
+ libukui-search2_xxxxx.deb
+ libukui-search-common_xxxxx.deb
+ libchinese-segmentation1_xxxx.deb
+ libchinese-segmentation-dev_xxxx.deb
+ libchinese-segmentation-common_xxxx.deb
+ ukui-search-systemdbus_xxxxx.deb
xxx代表版本号。其中ukui-search 为全局搜索应用本体libukui-search包提供了搜索服务基本功能以及扩展接口libukui-search-dev为其开发包。libchinese-segmentation包为搜索服务提供了NLP能力如中文分词等。ukui-search-systemdbus包提供了一些systemdbus提权操作。
xxx代表版本号。其中ukui-search 为全局搜索应用本体,ukui-search-service为搜索数据服务相关进程libukui-search包提供了搜索服务基本功能以及扩展接口libukui-search-dev为其开发包。libchinese-segmentation包为搜索服务提供了NLP能力如中文分词等。ukui-search-systemdbus包提供了一些systemdbus提权操作。
## 运行
搜索服务相关的进程共有5个包括ukui-search(全局搜索GUI界面)ukui-search-service(文件搜索服务)ukui-search-service-dir-manager(文件搜索目录管理), ukui-search-app-data-service(应用数据服务),ukuisearch-systemdbus(systembus)。
搜索服务相关的进程共有5个包括ukui-search(全局搜索GUI界面)ukui-search-service(文件搜索服务)ukui-search-service-dir-manager(文件搜索目录管理模块), ukui-search-app-data-service(应用数据服务),ukuisearch-systemdbus(systembus)。
所有进程默认开机自启。
@ -70,9 +73,16 @@ interface: com.ukui.search.service
搜索的功能有一部分依赖于其他桌面环境组件:
设置项搜索依赖ukui-control-center提供的配置文件,安装路径为
设置项搜索依赖ukui-control-center提供的dbus接口
> /usr/share/ukui-control-center/shell/res/search.xml
```
service:org.ukui.ukcc.session
path:/
interface:org.ukui.ukcc.session.interface
method:getSearchItems () ↦ (Dict of {String, Variant} arg_0)
signal:searchItemsAdd(Dict of{String, Variant})
searchItemsDelete(Dict of{String, Variant})
```
跳转到搜索结果对应的控制面板页面使用了ukui-control-center的命令行
@ -91,7 +101,7 @@ Options:
service: com.kylin.softwarecenter.getsearchresults
path: /com/kylin/softwarecenter/getsearchresults
interface: com.kylin.getsearchresults
get_search_result (String keyword) ↦ (Boolean arg_1)
method:get_search_result (String keyword) ↦ (Boolean arg_1)
```
跳转到软件商店安装页面的使用了以下dbus接口
@ -129,7 +139,7 @@ interface: org.freedesktop.FileManager1
## 原理与功能特点
全局搜索支持控制面板设置项搜索,应用搜索,文件搜索,便签本搜索。支持名称,拼音,或拼音首字母搜索(文本内容搜索和便签本搜索不支持拼音搜索)。其中,设置项搜索通过读取控制面板提供的配置文件实现,打开对应的控制面板页面也依赖与控制面板提供的命令行;应用搜索分为本地已安装应用(包括安卓兼容应用)和软件商店已上架的在线应用,在线应用的搜索和跳转安装通过软件商店提供的接口实现。所以,当怀疑搜索的设置搜索或应用搜索有问题时,可以直接测试控制面板或软件商店对应的接口。
全局搜索支持控制面板设置项搜索,应用搜索,文件搜索,便签本搜索。支持名称,拼音,或拼音首字母搜索(文本内容搜索和便签本搜索不支持拼音搜索)。其中,设置项搜索通过控制面板提供dbus接口获取数据,打开对应的控制面板页面也依赖与控制面板提供的命令行;应用搜索分为本地已安装应用(包括安卓兼容应用)和软件商店已上架的在线应用,在线应用的搜索和跳转安装通过软件商店提供的接口实现。所以,当怀疑搜索的设置搜索或应用搜索有问题时,可以直接测试控制面板或软件商店对应的接口。
文件搜索分为文件名(文件夹名)搜索和文本内容搜索。文件搜索有两种模式:`直接搜索`和`建立索引搜索`。
@ -138,6 +148,7 @@ interface: org.freedesktop.FileManager1
+ 索引搜索:搜索通过遍历文件系统建立数据库(需要消耗一定的时间和资源),搜索时直接对数据库进行搜索,可以实现毫秒级的搜索响应,建立索引的过程中,搜索结果可能不全或者搜不出结果。
首次打开索引时ukui-search-service进程会新建两个数据库分别存储基础索引信息用于文件名搜索和文本内容索引信息用于文本内容搜索完成首次索引后索引服务会依赖inotify机制进行实时监听更新。索引关闭再打开或重启服务时索引服务会对遍历文件并对数据库进行校验以增量更新。
索引数据库会基于文件系统监听进行实时更新。但是由于解析文本需要时间,所以大文件的索引新可能会有短暂的延迟。由于各种意外原因,比如索引更新过程中掉电关机,可能会导致索引损坏,此时搜索在下次开机时会重新建立索引来保证正常的文件搜索功能。基于机器配置和本地文件的数量,大小以及种类,索引重建的时间可以从几秒到数分钟不等。
搜索目录可以在控制面板中手动配置,目前索引已经支持外接设备。
索引搜索支持文本内容搜索,基本原理可以参考 [倒排索引与优麒麟的文件搜索](https://docs.qq.com/doc/DU0p0S1lRelp2aW1y) 。建立索引时,搜索会对常用的文本文件进行解析,提取关键词存入数据库。搜索时,用户输入的文本也会被提取关键词,和数据库中的关键词进行匹配, 所以文本索引并不能保证你搜索一个文本文件里的任意内容都能搜出这个文件这也不是普遍的应用场景。搜索输入的文本中必须要包含【关键词】才可以。比如你搜索一个由于并不是任何文件的关键词所以并不会有搜索到任何文件。事实上我们有一个停用词词库专门用来排除于是等等基本上在每个文档都会出现的一些无用词。目前搜索支持解析的文件格式有docxpptx, xlsx, txt(大部分编码格式), doc, dot, wps, ppt, pps, dps, et, xls, pdfuofuotuosuopofd以上格式均不支持加密文件的解析此外文件索引支持图片ocr提取文字所以你也可以通过图片中的文字搜索到图片就像文档一样支持的图片格式pngbmpgiftiftiffwebpjpejpgjpeg。
> 注意:应用的.desktop文件并不是应用本身或者“快捷方式”对于搜索来说它只是一个文件所以搜索desktop文件的名字并不能搜出这个应用除非它恰好和应用重名。另外在文件搜索中显示的dekstop文件并不会以应用的形式显示而是显示它本来的样子——一个文件。
@ -150,11 +161,13 @@ ukui-search应用和ukui-search-service、ukui-search-app-data-service的配置
文件说明:
+ ukui-search.conf ------------------------------------全局搜索GUI配置文件。
+ ukui-search-block-dirs.conf ---------------------文件搜索黑名单,在控制面板中设置
+ ukui-search-index-status.conf ------------------文件索引服务状态记录
+ index_data ---------------------------------------------文件索引数据库
+ content_index_data ---------------------------------文本内容数据库
+ ukui-search.conf -------------------------------------全局搜索GUI配置文件。
+ ukui-search-plugin-order.conf -------------------搜索插件显示顺序
+ ukui-search-block-dirs.conf ----------------------文件搜索黑名单,在控制面板中设置
+ ukui-search-index-status.conf -------------------文件索引服务状态记录
+ ukui-search-current-indexable-dir.conf -------搜索目录配置文件
+ index_data --------------------------------------------文件索引数据库
+ content_index_data --------------------------------文本内容数据库
## 编译
@ -181,11 +194,11 @@ mkdir build;cd build;qmake ..;make
## 调试
ukui-search目前并未采用ukui-log4qt模块的日志功能。如需调试可在以下目录新建`ukui-search.log`、`ukui-search-service.log`以及`ukui-search-app-data-service.log`文件分别对应全局搜索GUI应用全局搜索文件索引服务和应用数据服务。新建日志文件后日志会自动打印到对应文件中,但目前日志没有自动备份或删除机制。
ukui-search目前并未采用ukui-log4qt模块的日志功能。如需调试可在~/.config/org.ukui/目录新建`ukui-search.log`、`ukui-search-service.log`以及`ukui-search-app-data-service.log`文件分别对应全局搜索GUI应用全局搜索文件索引服务和应用数据服务。新建日志文件后日志会自动打印到对应文件中但目前日志没有自动备份或删除机制。
## 开发接口
### 搜索服务接口(此接口目前处于快速更新,请以代码为准)
### 搜索服务接口(此接口目前快速更新,请以代码为准)
#### Use with CMake:
@ -210,20 +223,33 @@ PKGCONFIG += ukui-search
......
//初始化一个搜索实例
UkuiSearch::UkuiSearchTask ukst;
//初始化需要用到的搜索插件
ukst.initSearchPlugin(UkuiSearch::SearchProperty::SearchType::File);
//初始化队列
UkuiSearch::DataQueue<UkuiSearch::ResultItem> *queue = ukst.init();
//加载想要使用的搜索插件
ukst.initSearchPlugin(UkuiSearch::SearchType::File);
//设置最大结果数量默认为100
ukst.setMaxResultNum(999999);
//添加搜索文件夹
QString path = "/home/usr/下载";
ukst.addSearchDir("path");
//设置需要的信息,将被储存在 UkuiSearch::ResultItem中
ukst.setResultProperties(UkuiSearch::SearchProperty::SearchType::File,
UkuiSearch::SearchResultProperties{UkuiSearch::SearchProperty::FilePath,
UkuiSearch::SearchProperty::FileIconName});
//添加关键词,支持添加多个关键词,用 ‘与’的关系搜索,注意当需要重新添加关键词时需要调用clearKeyWords清空关键词
ukst.addKeyword(searchText);
//添加搜索条件
ukst.setOnlySearchFile(true);
ukst.addKeyword(m_keyword);
//启动搜索(异步)
ukst.startSearch(UkuiSearch::SearchType::File);
//执行搜索,参数表示执行搜索的搜索插件,注意每次搜索之前可以调用‘’
ukst.startSearch(UkuiSearch::SearchProperty::SearchType::File);
//接收结果(示例)
while(true) {
if(!queue->isEmpty()) {
qDebug() << queue->dequeue().getItemKey();
}
while(!queue->isEmpty()) {
auto result = queue->dequeue();
//通过属性取值
qDebug() << result.getValue(UkuiSearch::SearchProperty::FilePath);
//直接获取所有值
UkuiSearch::SearchResultPropertyMap map = result.getAllValue();
qDebug() << map;
}
```
@ -267,24 +293,30 @@ Q_DECLARE_INTERFACE(UkuiSearch::SearchTaskPluginIface, SearchTaskPluginIface_iid
表示加载用户插件
```c++
ukst.initSearchPlugin(UkuiSearch::SearchType::Custom);
ukst.initSearchPlugin(UkuiSearch::SearchType::Custom, "<用户自定义的名称>");
```
启动搜索
```c++
ukst.startSearch(UkuiSearch::SearchType::<用户自定义的名称>);
ukst.startSearch(UkuiSearch::SearchType::Custom, "<用户自定义的名称>";
```
### 搜索应用插件接口
搜索应用本身也提供了一个插件接口,可以通过加载用户实现的插件以实现额外搜索功能:
搜索应用本身也提供了一个插件接口,可以通过加载用户实现的插件以实现额外搜索以及详情页定制功能:
```c++
namespace UkuiSearch {
class SearchPluginIface : public PluginInterface
{
public:
enum InvokableAction
{
None = 1u << 0,
HideUI = 1u << 1
};
Q_DECLARE_FLAGS(InvokableActions, InvokableAction)
struct DescriptionInfo
{
QString key;
@ -305,6 +337,15 @@ public:
QVector<DescriptionInfo> description;
QString actionKey;
int type;
ResultInfo(const QIcon &iconToSet = QIcon(), const QString &nameToSet = QString(),
const QVector<DescriptionInfo> &descriptionToSet = QVector<DescriptionInfo>(),
const QString &actionKeyToSet = QString(), const int &typeToSet = 0) {
icon = iconToSet;
name = nameToSet;
description = descriptionToSet;
actionKey = actionKeyToSet;
type = typeToSet;
}
};
virtual ~SearchPluginIface() {}
@ -313,9 +354,12 @@ public:
virtual void stopSearch() = 0;
virtual QList<Actioninfo> getActioninfo(int type) = 0;
virtual void openAction(int actionkey, QString key, int type) = 0;
// virtual bool isPreviewEnable(QString key, int type) = 0;
// virtual QWidget *previewPage(QString key, int type, QWidget *parent = nullptr) = 0;
virtual QWidget *detailPage(const ResultInfo &ri) = 0;
void invokeActions(InvokableActions actions);
};
}
```
> 接口使用注意事项:

View File

@ -20,6 +20,7 @@
*/
#include "search-line-edit.h"
#include <KWindowEffects>
#include <QApplication>
#include <QPainterPath>
QT_BEGIN_NAMESPACE
@ -91,7 +92,7 @@ void SearchLineEdit::paintEvent(QPaintEvent *e)
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing); // 反锯齿;
p.setBrush(palette().base());
p.setOpacity(GlobalSettings::getInstance()->getValue(TRANSPARENCY_KEY).toDouble());
p.setOpacity(GlobalSettings::getInstance().getValue(TRANSPARENCY_KEY).toDouble());
p.setPen(Qt::NoPen);
p.drawRoundedRect(this->rect(), 12, 12);
return QLineEdit::paintEvent(e);
@ -99,6 +100,7 @@ void SearchLineEdit::paintEvent(QPaintEvent *e)
void SearchLineEdit::focusOutEvent(QFocusEvent *e)
{
Q_UNUSED(e)
this->setFocus();
}

View File

@ -630,49 +630,6 @@ QString escapeHtml(const QString & str) {
return temp;
}
void DetailWidget::setWidgetInfo(const QString &plugin_name, const SearchPluginIface::ResultInfo &info)
{
// clearLayout(m_descFrameLyt);
// clearLayout(m_previewFrameLyt);
// if(SearchPluginManager::getInstance()->getPlugin(plugin_name)->isPreviewEnable(info.actionKey,info.type)) {
// m_iconLabel->hide();
// m_previewFrameLyt->addWidget(SearchPluginManager::getInstance()->getPlugin(plugin_name)->previewPage(info.actionKey,info.type, m_previewFrame), 0 , Qt::AlignHCenter);
// m_previewFrameLyt->setContentsMargins(0,0,0,0);
// m_previewFrame->show();
// } else {
// m_previewFrame->hide();
// m_iconLabel->setPixmap(info.icon.pixmap(info.icon.actualSize(ICON_SIZE)));
// m_iconLabel->show();
// }
// QFontMetrics fontMetrics = m_nameLabel->fontMetrics();
// QString name = fontMetrics.elidedText(info.name, Qt::ElideRight, NAME_LABEL_WIDTH - 8);
// m_nameLabel->setText(QString("<h3 style=\"font-weight:normal;\">%1</h3>").arg(escapeHtml(name)));
// m_nameLabel->setToolTip(info.name);
// m_pluginLabel->setText(plugin_name);
// m_nameFrame->show();
// m_line_1->show();
// if (info.description.length() > 0) {
// //NEW_TODO 样式待优化
// clearLayout(m_descFrameLyt);
// Q_FOREACH (SearchPluginIface::DescriptionInfo desc, info.description) {
// QLabel * descLabel = new QLabel(m_descFrame);
// descLabel->setTextFormat(Qt::PlainText);
// descLabel->setWordWrap(true);
// QString show_desc = desc.key + " " + desc.value;
// descLabel->setText(show_desc);
// m_descFrameLyt->addWidget(descLabel);
// }
// m_descFrame->show();
// m_line_2->show();
// }
// clearLayout(m_actionFrameLyt);
// Q_FOREACH (SearchPluginIface::Actioninfo actioninfo, SearchPluginManager::getInstance()->getPlugin(plugin_name)->getActioninfo(info.type)) {
// ActionLabel * actionLabel = new ActionLabel(actioninfo.displayName, info.actionKey, actioninfo.actionkey, plugin_name, info.type, m_actionFrame);
// m_actionFrameLyt->addWidget(actionLabel);
// }
// m_actionFrame->show();
}
void DetailWidget::updateDetailPage(const QString &plugin_name, const SearchPluginIface::ResultInfo &info)
{
@ -697,71 +654,6 @@ void DetailWidget::updateDetailPage(const QString &plugin_name, const SearchPlug
m_currentPluginId = plugin_name;
}
void DetailWidget::clear()
{
// m_iconLabel->hide();
// m_nameFrame->hide();
// m_line_1->hide();
// m_descFrame->hide();
// m_line_2->hide();
// m_actionFrame->hide();
}
void DetailWidget::initUi()
{
// this->setFixedSize(368, 516);
// m_mainLyt = new QVBoxLayout(this);
// this->setLayout(m_mainLyt);
// m_mainLyt->setContentsMargins(DETAIL_WIDGET_MARGINS);
// m_mainLyt->setAlignment(Qt::AlignHCenter);
// m_iconLabel = new QLabel(this);
// m_iconLabel->setFixedHeight(DETAIL_ICON_HEIGHT);
// m_iconLabel->setAlignment(Qt::AlignCenter);
// m_previewFrame = new QFrame(this);
// m_previewFrameLyt = new QHBoxLayout(m_previewFrame);
// m_nameFrame = new QFrame(this);
// m_nameFrameLyt = new QHBoxLayout(m_nameFrame);
// m_nameFrame->setLayout(m_nameFrameLyt);
// m_nameFrameLyt->setContentsMargins(DETAIL_FRAME_MARGINS);
// m_nameLabel = new QLabel(m_nameFrame);
// m_nameLabel->setMaximumWidth(NAME_LABEL_WIDTH);
// m_pluginLabel = new QLabel(m_nameFrame);
// m_pluginLabel->setEnabled(false);
// m_nameFrameLyt->addWidget(m_nameLabel);
// m_nameFrameLyt->addStretch();
// m_nameFrameLyt->addWidget(m_pluginLabel);
// m_line_1 = new QFrame(this);
// m_line_1->setFixedHeight(1);
// m_line_1->setLineWidth(0);
// m_line_1->setStyleSheet(LINE_STYLE);
// m_line_2 = new QFrame(this);
// m_line_2->setFixedHeight(1);
// m_line_2->setLineWidth(0);
// m_line_2->setStyleSheet(LINE_STYLE);
// m_descFrame = new QFrame(this);
// m_descFrameLyt = new QVBoxLayout(m_descFrame);
// m_descFrame->setLayout(m_descFrameLyt);
// m_descFrameLyt->setContentsMargins(DETAIL_FRAME_MARGINS);
// m_actionFrame = new QFrame(this);
// m_actionFrameLyt = new QVBoxLayout(m_actionFrame);
// m_actionFrame->setLayout(m_actionFrameLyt);
// m_actionFrameLyt->setContentsMargins(DETAIL_FRAME_MARGINS);
// m_mainLyt->addWidget(m_iconLabel);
// m_mainLyt->addWidget(m_previewFrame, 0, Qt::AlignHCenter);
// m_mainLyt->addWidget(m_nameFrame);
// m_mainLyt->addWidget(m_line_1);
// m_mainLyt->addWidget(m_descFrame);
// m_mainLyt->addWidget(m_line_2);
// m_mainLyt->addWidget(m_actionFrame);
// m_mainLyt->addStretch();
}
void DetailWidget::paintEvent(QPaintEvent *event)
{
QStyleOption opt;
@ -791,53 +683,6 @@ void DetailWidget::clearLayout(QLayout *layout)
child = NULL;
}
//ActionLabel::ActionLabel(const QString &action, const QString &key, const int &ActionKey, const QString &pluginId, const int type, QWidget *parent) : QLabel(parent)
//{
// m_action = action;
// m_key = key;
// m_actionKey = ActionKey;
// m_type = type;
// m_pluginId = pluginId;
// this->initUi();
// this->installEventFilter(this);
//}
//void ActionLabel::initUi()
//{
// this->setText(m_action);
// QPalette pal = palette();
// pal.setColor(QPalette::WindowText, ACTION_NORMAL_COLOR);
// pal.setColor(QPalette::Light, ACTION_HOVER_COLOR);
// pal.setColor(QPalette::Dark, ACTION_PRESS_COLOR);
// this->setPalette(pal);
// this->setForegroundRole(QPalette::WindowText);
// this->setCursor(QCursor(Qt::PointingHandCursor));
//}
//bool ActionLabel::eventFilter(QObject *watched, QEvent *event)
//{
// if (watched == this) {
// if(event->type() == QEvent::MouseButtonPress) {
// this->setForegroundRole(QPalette::Dark);
// return true;
// } else if(event->type() == QEvent::MouseButtonRelease) {
// SearchPluginIface *plugin = SearchPluginManager::getInstance()->getPlugin(m_pluginId);
// if (plugin)
// plugin->openAction(m_actionKey, m_key, m_type);
// else
// qWarning()<<"Get plugin failed!";
// this->setForegroundRole(QPalette::Light);
// return true;
// } else if(event->type() == QEvent::Enter) {
// this->setForegroundRole(QPalette::Light);
// return true;
// } else if(event->type() == QEvent::Leave) {
// this->setForegroundRole(QPalette::WindowText);
// return true;
// }
// }
//}
ResultScrollBar::ResultScrollBar(QWidget *parent) : QScrollBar(parent)
{

View File

@ -28,7 +28,6 @@
#include "result-view.h"
#include "search-plugin-iface.h"
#include "best-list-view.h"
#include "web-search-view.h"
namespace UkuiSearch {
class ResultScrollBar : public QScrollBar
@ -115,32 +114,16 @@ class DetailWidget : public QWidget
public:
DetailWidget(QWidget *parent = nullptr);
~DetailWidget() = default;
void clear();
public Q_SLOTS:
void setWidgetInfo(const QString &plugin_name, const SearchPluginIface::ResultInfo &info);
void updateDetailPage(const QString &plugin_name, const SearchPluginIface::ResultInfo &info);
protected:
void paintEvent(QPaintEvent *event);
private:
void initUi();
void clearLayout(QLayout *);
QVBoxLayout * m_mainLyt = nullptr;
QString m_currentPluginId;
QWidget *m_detailPage = nullptr;
// QLabel * m_iconLabel = nullptr;
// QFrame *m_previewFrame = nullptr;
// QHBoxLayout *m_previewFrameLyt = nullptr;
// QFrame * m_nameFrame = nullptr;
// QHBoxLayout * m_nameFrameLyt = nullptr;
// QLabel * m_nameLabel = nullptr;
// QLabel * m_pluginLabel = nullptr;
// QFrame * m_line_1 = nullptr;
// QFrame * m_descFrame = nullptr;
// QVBoxLayout * m_descFrameLyt = nullptr;
// QFrame * m_line_2 = nullptr;
// QFrame * m_actionFrame = nullptr;
// QVBoxLayout * m_actionFrameLyt = nullptr;
};
class DetailArea : public QScrollArea
@ -156,24 +139,6 @@ private:
Q_SIGNALS:
void setWidgetInfo(const QString&, const SearchPluginIface::ResultInfo&);
};
//class ActionLabel : public QLabel
//{
// Q_OBJECT
//public:
// ActionLabel(const QString &action, const QString &key, const int &ActionKey, const QString &pluginId, const int type = 0, QWidget *parent = nullptr);
// ~ActionLabel() = default;
//private:
// void initUi();
// QString m_action;
// QString m_key;
// int m_actionKey;
// int m_type = 0;
// QString m_pluginId;
//protected:
// bool eventFilter(QObject *, QEvent *);
//};
}
#endif // SEARCHPAGESECTION_H

View File

@ -19,6 +19,7 @@
*
*/
#include "search-result-page.h"
#include "global-settings.h"
#include <QPainterPath>
QT_BEGIN_NAMESPACE
extern void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed);
@ -35,11 +36,6 @@ SearchResultPage::SearchResultPage(QWidget *parent) : QWidget(parent)
setInternalPlugins();
}
void SearchResultPage::setSize(const int&width, const int&height)
{
// m_splitter->setFixedSize(width, height);
}
void SearchResultPage::setInternalPlugins()
{
QList<PluginInfo> infoList = SearchPluginManager::getInstance()->getPluginIds();
@ -129,10 +125,11 @@ void SearchResultPage::setWidth(int width)
void SearchResultPage::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
p.setBrush(palette().base());
p.setOpacity(GlobalSettings::getInstance()->getValue(TRANSPARENCY_KEY).toDouble());
p.setOpacity(GlobalSettings::getInstance().getValue(TRANSPARENCY_KEY).toDouble());
p.setPen(Qt::NoPen);
p.drawRoundedRect(this->rect().adjusted(10,10,-10,-10), 12, 12);

View File

@ -31,7 +31,6 @@ class SearchResultPage : public QWidget
public:
explicit SearchResultPage(QWidget *parent = nullptr);
~SearchResultPage() = default;
void setSize(const int&, const int&);
void setInternalPlugins();
void appendPlugin(const QString &plugin_id);
void movePlugin(const QString &plugin_id, int index);

View File

@ -10,6 +10,7 @@ TEMPLATE = app
PKGCONFIG += gio-2.0 glib-2.0 gio-unix-2.0 kysdk-waylandhelper
CONFIG += c++11 link_pkgconfig no_keywords lrelease
LIBS += -lxapian -lgsettings-qt -lquazip5 -lX11
LIBS += -lukui-appwidget-manager -lukui-appwidget-provider
#LIBS += -lukui-log4qt
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
@ -27,6 +28,7 @@ include(model/model.pri)
include(xatom/xatom.pri)
include(../3rd-parties/qtsingleapplication/qtsingleapplication.pri)
include(view/view.pri)
include(search-app-widget-plugin/search-app-widget-plugin.pri)
SOURCES += \
@ -54,20 +56,44 @@ data.files += ../data/ukui-search.desktop
INSTALLS += data data-menu
RESOURCES += \
resource.qrc
resource.qrc \
search-app-widget-plugin/provider/src.qrc
TRANSLATIONS += \
../translations/ukui-search/zh_CN.ts \
../translations/ukui-search/tr.ts \
../translations/ukui-search/bo_CN.ts
../translations/ukui-search/bo_CN.ts \
../translations/ukui-search/appwidget/search_zh_CN.ts \
../translations/ukui-search/appwidget/search_bo_CN.ts
qm_files.path = /usr/share/ukui-search/translations/
qm_files.files = $$OUT_PWD/.qm/*.qm
qm_files.files = $$OUT_PWD/.qm/zh_CN.qm \
$$OUT_PWD/.qm/bo_CN.qm \
$$OUT_PWD/.qm/tr.qm \
schemes.path = /usr/share/glib-2.0/schemas/
schemes.files += ../data/org.ukui.log4qt.ukui-search.gschema.xml
INSTALLS += qm_files schemes
appwidget_qm_files.files = $$OUT_PWD/.qm/search_bo_CN.qm \
$$OUT_PWD/.qm/search_zh_CN.qm
appwidget_qm_files.path = /usr/share/appwidget/translations/
qml.files += search-app-widget-plugin/provider/data/search.qml
qml.path = /usr/share/appwidget/qml/
appwidgetconf.files += search-app-widget-plugin/provider/data/search.conf
appwidgetconf.path = /usr/share/appwidget/config/
service.files += search-app-widget-plugin/provider/org.ukui.appwidget.provider.search.service
service.path += /usr/share/dbus-1/services/
preview.files += search-app-widget-plugin/provider/data/search.png
preview.path = /usr/share/appwidget/search/
svg.files += search-app-widget-plugin/provider/data/ukui-search.svg
svg.path = /usr/share/appwidget/search/
INSTALLS += qm_files schemes qml appwidget_qm_files appwidgetconf service preview svg
LIBS += -L$$OUT_PWD/../libchinese-segmentation -lchinese-segmentation \
-L$$OUT_PWD/../libsearch -lukui-search

View File

@ -21,76 +21,17 @@
*
*/
#include <QDesktopWidget>
#include <QFile>
#include <QDir>
#include <unistd.h>
#include <syslog.h>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
#include <ukui-log4qt.h>
#endif
#include <QObject>
#include <QApplication>
#include <QX11Info>
#include <KWindowSystem>
#include "ukui-search-gui.h"
#include "log-utils.h"
using namespace UkuiSearch;
void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
QByteArray currentTime = QTime::currentTime().toString().toLocal8Bit();
bool showDebug = true;
// QString logFilePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/ukui-search.log";
// QString logFilePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + "/.config/org.ukui/ukui-search/ukui-search.log";
QString logFilePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + "/.config/org.ukui/ukui-search.log";
if (!QFile::exists(logFilePath)) {
showDebug = false;
}
FILE *log_file = nullptr;
if (showDebug) {
log_file = fopen(logFilePath.toLocal8Bit().constData(), "a+");
}
const char *file = context.file ? context.file : "";
const char *function = context.function ? context.function : "";
switch (type) {
case QtDebugMsg:
if (!log_file) {
break;
}
fprintf(log_file, "Debug: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function);
break;
case QtInfoMsg:
fprintf(log_file? log_file: stdout, "Info: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function);
break;
case QtWarningMsg:
fprintf(log_file? log_file: stderr, "Warning: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function);
break;
case QtCriticalMsg:
fprintf(log_file? log_file: stderr, "Critical: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function);
break;
case QtFatalMsg:
fprintf(log_file? log_file: stderr, "Fatal: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function);
break;
}
if (log_file)
fclose(log_file);
}
int main(int argc, char *argv[]) {
//v101日志模块
//#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
// //Init log module
// initUkuiLog4qt("ukui-search");
//#endif
// Determine whether the home directory has been created, and if not, keep waiting.
char *p_home = NULL;
unsigned int i = 0;
while(p_home == NULL) {
::sleep(1);
@ -111,14 +52,8 @@ int main(int argc, char *argv[]) {
}
// Output log to file
qInstallMessageHandler(messageOutput);
//若使用v101日志模块可以解放如下判断条件
//#if (QT_VERSION < QT_VERSION_CHECK(5, 12, 0))
// // Output log to file
// qInstallMessageHandler(messageOutput);
//#endif
// Register meta type
LogUtils::initLogFile("ukui-search");
qInstallMessageHandler(LogUtils::messageOutput);
qDebug() << "ukui-search main start";
// If qt version bigger than 5.12, enable high dpi scaling and use high dpi pixmaps?
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
@ -128,7 +63,13 @@ int main(int argc, char *argv[]) {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
UkuiSearchGui app(argc, argv, QString("ukui-search-gui-%1").arg(QX11Info::appScreen()));
QString display;
if(KWindowSystem::isPlatformWayland()) {
display = getenv("WAYLAND_DISPLAY");
} else if (KWindowSystem::isPlatformX11()) {
display = getenv("DISPLAY");
}
UkuiSearchGui app(argc, argv, QString("ukui-search-gui-%1").arg(display));
if (app.isRunning())
return 0;

View File

@ -50,7 +50,7 @@
#define MAIN_SETTINGS QDir::homePath() + "/.config/org.ukui/ukui-search/ukui-search.conf"
#define ENABLE_CREATE_INDEX_ASK_DIALOG "enable_create_index_ask_dialog"
const static QString FILE_INDEX_ENABLE_KEY = "fileIndexEnable";
using namespace UkuiSearch;
extern void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed);
@ -81,7 +81,6 @@ MainWindow::MainWindow(QWidget *parent) :
installEventFilter(this);
initConnections();
// connect(KWindowSystem::self(), &KWindowSystem::activeWindowChanged, this,[&](WId activeWindowId){
// qDebug() << "activeWindowChanged!!!" << activeWindowId;
// if (activeWindowId != this->winId()) {
@ -91,9 +90,12 @@ MainWindow::MainWindow(QWidget *parent) :
m_appWidgetPlugin = new AppWidgetPlugin;
connect(m_appWidgetPlugin, &AppWidgetPlugin::startSearch, this, [ & ] (QString keyword){
// connect(m_appWidgetPlugin, &AppWidgetPlugin::startSearch, this, [ & ] (QString keyword){
// this->bootOptionsFilter("-s");
// this->setText(keyword);
// });
connect(m_appWidgetPlugin, &AppWidgetPlugin::start, this, [&] {
this->bootOptionsFilter("-s");
this->setText(keyword);
});
connect(ActionTransmiter::getInstance(), &ActionTransmiter::hideUIAction, this, &MainWindow::tryHideMainwindow);
}
@ -103,10 +105,10 @@ MainWindow::~MainWindow() {
delete m_askDialog;
m_askDialog = NULL;
}
if(m_askTimer) {
delete m_askTimer;
m_askTimer = NULL;
}
// if(m_askTimer) {
// delete m_askTimer;
// m_askTimer = NULL;
// }
if(m_searchGsettings) {
delete m_searchGsettings;
m_searchGsettings = NULL;
@ -134,8 +136,7 @@ void MainWindow::initUi() {
void MainWindow::initConnections()
{
connect(m_sys_tray_icon, &QSystemTrayIcon::activated, this, &MainWindow::trayIconActivatedSlot);
connect(QApplication::primaryScreen(), &QScreen::geometryChanged, this, &MainWindow::monitorResolutionChange);
connect(qApp, &QApplication::primaryScreenChanged, this, &MainWindow::primaryScreenChangedSlot);
connect(QApplication::primaryScreen(), &QScreen::geometryChanged, this, &MainWindow::ScreenGeometryChanged);
connect(m_askDialog, &CreateIndexAskDialog::closed, this, [ = ]() {
m_isAskDialogVisible = false;
});
@ -163,8 +164,8 @@ void MainWindow::bootOptionsFilter(QString opt) {
clearSearchResult();
centerToScreen(this);
this->m_searchBarWidget->setFocus();
this->activateWindow();
}
this->activateWindow();
}
}
@ -235,7 +236,7 @@ void MainWindow::searchKeywordSlot(const QString &keyword)
//允许弹窗且当前次搜索(为关闭主界面,算一次搜索过程)未询问且当前为暴力搜索
if(m_settings->value(ENABLE_CREATE_INDEX_ASK_DIALOG).toBool()
&& !m_currentSearchAsked
&& GlobalSettings::getInstance()->getValue(FILE_INDEX_ENABLE_KEY).toBool() == false) {
&& !m_isIndexSearch) {
m_askTimer->start();
}
Q_EMIT m_searchResultPage->startSearch(keyword);
@ -258,73 +259,10 @@ void MainWindow::tryHide()
this->tryHideMainwindow();
}
/**
* @brief monitorResolutionChange
* @param rect
*/
void MainWindow::monitorResolutionChange(QRect rect) {
void MainWindow::ScreenGeometryChanged(QRect rect) {
Q_UNUSED(rect);
}
/**
* @brief primaryScreenChangedSlot
* @param screen
*/
void MainWindow::primaryScreenChangedSlot(QScreen *screen) {
Q_UNUSED(screen);
}
/**
* @brief MainWindow::moveToPanel
*/
void MainWindow::moveToPanel() {
QRect availableGeometry = qApp->primaryScreen()->availableGeometry();
QRect screenGeometry = qApp->primaryScreen()->geometry();
QDBusInterface primaryScreenInterface("org.ukui.SettingsDaemon",
"/org/ukui/SettingsDaemon/wayland",
"org.ukui.SettingsDaemon.wayland",
QDBusConnection::sessionBus());
if(QDBusReply<int>(primaryScreenInterface.call("x")).isValid()) {
QDBusReply<int> x = primaryScreenInterface.call("x");
QDBusReply<int> y = primaryScreenInterface.call("y");
QDBusReply<int> width = primaryScreenInterface.call("width");
QDBusReply<int> height = primaryScreenInterface.call("height");
screenGeometry.setX(x);
screenGeometry.setY(y);
screenGeometry.setWidth(width);
screenGeometry.setHeight(height);
availableGeometry.setX(x);
availableGeometry.setY(y);
availableGeometry.setWidth(width);
availableGeometry.setHeight(height);
}
QDesktopWidget * desktopWidget = QApplication::desktop();
QRect screenMainRect = desktopWidget->screenGeometry(0);//获取设备屏幕大小
QDBusInterface interface("com.ukui.panel.desktop",
"/",
"com.ukui.panel.desktop",
QDBusConnection::sessionBus());
int position = QDBusReply<int>(interface.call("GetPanelPosition", "position"));
int height = QDBusReply<int>(interface.call("GetPanelSize", "height"));
int d = 8; //窗口边沿到任务栏距离
if(position == 0) {
//任务栏在下侧
this->move(availableGeometry.x() + availableGeometry.width() - this->width() - d, screenGeometry.y() + screenGeometry.height() - this->height() - height - d);
} else if(position == 1) {
//任务栏在上侧
this->move(availableGeometry.x() + availableGeometry.width() - this->width() - d, screenGeometry.y() + height + d);
} else if(position == 2) {
//任务栏在左侧
this->move(screenGeometry.x() + height + d, screenGeometry.y() + screenGeometry.height() - this->height() - d);
} else if(position == 3) {
//任务栏在右侧
this->move(screenGeometry.x() + screenGeometry.width() - this->width() - height - d, screenGeometry.y() + screenGeometry.height() - this->height() - d);
if(this->isVisible()) {
centerToScreen(this);
}
}
@ -336,12 +274,10 @@ void MainWindow::centerToScreen(QWidget* widget) {
if(!widget)
return;
KWindowSystem::setState(this->winId(),NET::SkipTaskbar | NET::SkipPager);
QDesktopWidget* m = QApplication::desktop();
QRect desk_rect = m->screenGeometry(m->screenNumber(QCursor::pos()));
QRect desk_rect = qApp->screenAt(QCursor::pos())->geometry();
int desk_x = desk_rect.width();
int desk_y = desk_rect.height();
int x = widget->width();
int y = widget->height();
widget->show();
kdk::WindowManager::setGeometry(this->windowHandle(),QRect(desk_x / 2 - x / 2 + desk_rect.left(),
desk_y / 3 + desk_rect.top(),
@ -358,10 +294,13 @@ void MainWindow::initSettings() {
const QByteArray id(UKUI_SEARCH_SCHEMAS);
if(QGSettings::isSchemaInstalled(id)) {
m_searchGsettings = new QGSettings(id);
if (m_searchGsettings->keys().contains(FILE_INDEX_ENABLE_KEY)) {
m_isIndexSearch = m_searchGsettings->get(FILE_INDEX_ENABLE_KEY).toBool();
}
connect(m_searchGsettings, &QGSettings::changed, this, [ = ](const QString & key) {
if(key == FILE_INDEX_ENABLE_KEY) {
bool isIndexSearch = m_searchGsettings->get(FILE_INDEX_ENABLE_KEY).toBool();
if(m_researchTimer->isActive() && !isIndexSearch) {
m_isIndexSearch = m_searchGsettings->get(FILE_INDEX_ENABLE_KEY).toBool();
if(m_researchTimer->isActive() && !m_isIndexSearch) {
m_researchTimer->stop();
}
}
@ -372,14 +311,24 @@ void MainWindow::initSettings() {
//使用GSetting获取当前窗口应该使用的透明度
double MainWindow::getTransparentData() {
return GlobalSettings::getInstance()->getValue(TRANSPARENCY_KEY).toDouble();
return GlobalSettings::getInstance().getValue(TRANSPARENCY_KEY).toDouble();
}
void MainWindow::initTimer() {
m_askTimer = new QTimer;
m_askTimer = new QTimer(this);
m_askTimer->setInterval(ASK_INDEX_TIME);
connect(m_askTimer, &QTimer::timeout, this, [ = ]() {
if(this->isVisible()) {
QWindow *modal = QGuiApplication::modalWindow();
if(modal) {
m_askTimer->stop();
connect(modal, &QWindow::visibleChanged, this, [ & ](bool visible){
if(!visible) {
m_askTimer->start();
}
}, Qt::UniqueConnection);
return;
}
if(this->isVisible() && !m_isIndexSearch) {
m_isAskDialogVisible = true;
kdk::UkuiStyleHelper::self()->removeHeader(m_askDialog);
m_askDialog->show();
@ -404,9 +353,10 @@ void MainWindow::initTimer() {
m_askTimer->stop();
} else {
//允许弹窗且当前次搜索(为关闭主界面,算一次搜索过程)未询问且当前为暴力搜索
if(m_settings->value(ENABLE_CREATE_INDEX_ASK_DIALOG, true).toBool() && !m_currentSearchAsked && GlobalSettings::getInstance()->getValue(FILE_INDEX_ENABLE_KEY).toBool() == false)
if(m_settings->value(ENABLE_CREATE_INDEX_ASK_DIALOG, true).toBool() && !m_currentSearchAsked && !m_isIndexSearch) {
m_askTimer->start();
}
}
});
}
@ -468,8 +418,9 @@ void MainWindow::keyPressEvent(QKeyEvent *event)
return QWidget::keyPressEvent(event);
}
void MainWindow::paintEvent(QPaintEvent *event) {
void MainWindow::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainterPath path;
path.addRoundedRect(m_searchBarWidget->x()+10, m_searchBarWidget->y()+10, m_searchBarWidget->width()-20, m_searchBarWidget->height()-20, 12, 12);

View File

@ -67,11 +67,6 @@ class MainWindow : public QMainWindow {
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
/**
* @brief Load the main window
* The position which mainwindow shows follow the ukui-panel.
*/
void moveToPanel();
// The position which mainwindow shows in the center of screen where the cursor in.
void centerToScreen(QWidget* widget);
@ -87,16 +82,8 @@ public:
bool eventFilter(QObject *watched, QEvent *event) override;
public Q_SLOTS:
/**
* @brief Monitor screen resolution
* @param rect: Screen resolution
*/
void monitorResolutionChange(QRect rect);
/**
* @brief Monitor primary screen changes
* @param screen: Primary screen
*/
void primaryScreenChangedSlot(QScreen *screen);
void ScreenGeometryChanged(QRect rect);
void bootOptionsFilter(QString opt); // 过滤终端命令
void clearSearchResult(); //清空搜索结果
void trayIconActivatedSlot(QSystemTrayIcon::ActivationReason reason);
@ -127,7 +114,7 @@ private:
QGSettings *m_searchGsettings = nullptr;
QSettings *m_settings = nullptr;
AppWidgetPlugin *m_appWidgetPlugin = nullptr;
bool m_isIndexSearch = false;
};
}

View File

@ -31,6 +31,7 @@ BestListModel::BestListModel(QObject *parent)
QModelIndex BestListModel::index(int row, int column, const QModelIndex &parent) const
{
Q_UNUSED(parent)
if(row < 0 || row > m_item->m_result_info_list.length() - 1)
return QModelIndex();
return createIndex(row, column, m_item);
@ -38,6 +39,7 @@ QModelIndex BestListModel::index(int row, int column, const QModelIndex &parent)
QModelIndex BestListModel::parent(const QModelIndex &index) const
{
Q_UNUSED(index)
return QModelIndex();
}
@ -96,6 +98,7 @@ QStringList BestListModel::getActions(const QModelIndex &index)
{
// if (m_item->m_result_info_list.length() > index.row() && index.row() >= 0)
// return m_item->m_result_info_list.at(index.row()).actionList;
Q_UNUSED(index)
return QStringList();
}
@ -200,6 +203,7 @@ void BestListModel::moveInfo(const QString &pluginName, const int pos)
void BestListModel::startSearch(const QString &keyword)
{
Q_UNUSED(keyword)
if (!m_item->m_result_info_list.isEmpty()) {
this->beginResetModel();
m_plugin_id_list.clear();

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
*/
#ifndef BESTLISTMODEL_H
#define BESTLISTMODEL_H

View File

@ -19,6 +19,7 @@
*
*/
#include "search-result-manager.h"
#include <QDeadlineTimer>
using namespace UkuiSearch;
SearchResultManager::SearchResultManager(const QString& plugin_id, QObject *parent) : QObject(parent)
@ -47,11 +48,11 @@ void SearchResultManager::stopSearch()
{
if(m_getResultThread->isRunning()) {
m_getResultThread->stop();
}
SearchPluginIface *plugin = SearchPluginManager::getInstance()->getPlugin(m_pluginId);
plugin->stopSearch();
qDebug() << m_pluginId << "stopped";
}
}
void SearchResultManager::initConnections()
{
@ -71,24 +72,18 @@ void ReceiveResultThread::stop()
void ReceiveResultThread::run()
{
QTimer *timer = new QTimer;
timer->setInterval(3000);
QDeadlineTimer deadline(3000);
while(!isInterruptionRequested()) {
SearchPluginIface::ResultInfo oneResult = m_resultQueue->tryDequeue();
if(oneResult.name.isEmpty()) {
if(!timer->isActive()) {
timer->start();
}
if(deadline.remainingTime()) {
msleep(100);
} else {
timer->stop();
Q_EMIT gotResultInfo(oneResult);
}
if(timer->isActive() && timer->remainingTime() < 0.01 && m_resultQueue->isEmpty()) {
this->requestInterruption();
}
} else {
deadline.setRemainingTime(3000);
Q_EMIT gotResultInfo(oneResult);
}
}
delete m_timer;
}

View File

@ -33,6 +33,7 @@ SearchResultModel::SearchResultModel(const QString &plugin_id)
QModelIndex SearchResultModel::index(int row, int column, const QModelIndex &parent) const
{
Q_UNUSED(parent)
if(row < 0 || row > m_item->m_result_info_list.length() - 1)
return QModelIndex();
// QVector<SearchPluginIface::ResultInfo> * m_info = &m_result_info_list;
@ -41,6 +42,7 @@ QModelIndex SearchResultModel::index(int row, int column, const QModelIndex &par
QModelIndex SearchResultModel::parent(const QModelIndex &child) const
{
Q_UNUSED(child)
return QModelIndex();
}
@ -135,25 +137,6 @@ const bool &SearchResultModel::isExpanded()
return m_isExpanded;
}
/**
* @brief SearchResultModel::getActions
* @param index
* @return
*/
QStringList SearchResultModel::getActions(const QModelIndex &index)
{
if (m_item->m_result_info_list.length() > index.row() && index.row() >= 0)
// return m_item->m_result_info_list.at(index.row()).actionList;
return QStringList();
}
QString SearchResultModel::getKey(const QModelIndex &index)
{
if (m_item->m_result_info_list.length() > index.row() && index.row() >= 0)
// return m_item->m_result_info_list.at(index.row()).key;
return NULL;
}
void SearchResultModel::refresh()
{
this->beginResetModel();

View File

@ -54,8 +54,6 @@ public:
const SearchPluginIface::ResultInfo & getInfo(const QModelIndex&);
void setExpanded(const bool&);
const bool &isExpanded();
QStringList getActions(const QModelIndex &);
QString getKey(const QModelIndex &);
void refresh();
public Q_SLOTS:

View File

@ -30,6 +30,7 @@ WebSearchModel::WebSearchModel(QObject *parent)
QModelIndex WebSearchModel::index(int row, int column, const QModelIndex &parent) const
{
Q_UNUSED(parent)
if(row < 0 || row > m_item->m_result_info_list.length() - 1)
return QModelIndex();
return createIndex(row, column, m_item);
@ -37,6 +38,7 @@ QModelIndex WebSearchModel::index(int row, int column, const QModelIndex &parent
QModelIndex WebSearchModel::parent(const QModelIndex &index) const
{
Q_UNUSED(index)
return QModelIndex();
}

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
*/
#ifndef WEBSEARCHMODEL_H
#define WEBSEARCHMODEL_H

View File

@ -12,3 +12,6 @@ targetCellWidth = 2
targetCellHeight = 1
updatePeriodMillis = 0
describe = ukui-search app widget
[LanguageFiles]
zh_CN = /usr/share/appwidget/translations/search_zh_CN.qm
bo_CN = /usr/share/appwidget/translations/search_bo_CN.qm

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -4,7 +4,7 @@ import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0
import org.ukui.appwidget 1.0
import org.ukui.qqc2style.private 1.0 as StylePrivate
//import org.ukui.qqc2style.private 1.0 as StylePrivate
AppWidget {
visible: true
@ -41,6 +41,14 @@ AppWidget {
onDatavalueChanged: updateSearchBarColor();
onUserStatusChangedSignal: {
if (status === "Normal") {
mouseArea.enabled = true;
} else if (status === "Editable") {
mouseArea.enabled = false;
}
}
Rectangle {
id:searchBar
anchors.centerIn: parent
@ -48,10 +56,23 @@ AppWidget {
height: 64 * scaling
radius: searchBar.height / 2
MouseArea {
id: mouseArea
anchors.fill: parent;
propagateComposedEvents: true;
onClicked: {
window.qmldefineeventchangedsignal("clicked", "search", "");
}
onPressAndHold: {
mouse.accepted = false;
}
}
RowLayout {
id: layout
anchors.fill: parent
spacing: 0
anchors.fill: parent;
spacing: 0;
Image {
id: image_search
@ -60,46 +81,46 @@ AppWidget {
Layout.preferredWidth: 32 * scaling;
Layout.preferredHeight: 32 * scaling;
Layout.alignment: Qt.AlignVCenter
source: "file:///usr/share/appwidget/search/ukui-search.svg"
Layout.alignment: Qt.AlignVCenter;
source: "file:///usr/share/appwidget/search/ukui-search.svg";
}
Item {
clip: true;
Layout.fillWidth: true
Layout.fillWidth: true;
Layout.fillHeight: true;
Layout.rightMargin: 32 * scaling;
TextInput {
Label {
id: searchtext
anchors.fill: parent;
Keys.enabled: true
Keys.onEnterPressed: {
window.qmldefineeventchangedsignal("enter", "search", searchtext.text);
searchtext.remove(0, searchtext.length);
}
Keys.onReturnPressed: {
window.qmldefineeventchangedsignal("return", "search", searchtext.text);
searchtext.remove(0, searchtext.length);
}
// Keys.enabled: true;
// Keys.onEnterPressed: {
// window.qmldefineeventchangedsignal("enter", "search", searchtext.text);
// searchtext.remove(0, searchtext.length);
// }
// Keys.onReturnPressed: {
// window.qmldefineeventchangedsignal("return", "search", searchtext.text);
// searchtext.remove(0, searchtext.length);
// }
focus: true
color: StylePrivate.StyleHelper.windowtextcolorrole
maximumLength: 100 * scaling
selectByMouse: true
verticalAlignment: Qt.AlignVCenter
font.pixelSize: 21 * scaling
// focus: true;
// color: StylePrivate.StyleHelper.windowtextcolorrole;
// maximumLength: 100 * scaling;
// selectByMouse: true;
// verticalAlignment: Qt.AlignVCenter;
// font.pixelSize: 21 * scaling;
property string placeholderText: /*qsTr("search")*/"全局搜索"
property string placeholderText: qsTr("search")/*"全局搜索"*/
Text {
id: placeholderText
text: searchtext.placeholderText
font.pixelSize: 21 * scaling
visible: !searchtext.text
anchors.verticalCenter: parent.verticalCenter
visible: !searchtext.text;
anchors.verticalCenter: parent.verticalCenter;
}
}
}

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#include "search.h"
#include <QDBusPendingCall>
@ -9,11 +28,6 @@
#include <QApplication>
#include <QVariantMap>
#define CONTROL_CENTER_PERSONALISE_GSETTINGS_ID "org.ukui.control-center.personalise"
#define TRANSPARENCY_KEY "transparency"
#define THEME_GSETTINGS_ID "org.ukui.style"
#define STYLE_NAME_KEY "styleName"
using namespace UkuiSearch;
AppWidgetPlugin::AppWidgetPlugin(QString providername, QObject *parent) : KAppWidgetProvider(providername, parent)
@ -30,23 +44,23 @@ AppWidgetPlugin::AppWidgetPlugin(QString providername, QObject *parent) : KAppWi
m_manager = new AppWidget::KAppWidgetManager(this);
connect(GlobalSettings::getInstance(), &GlobalSettings::transparencyChanged, [ & ] {
qDebug() << "transparency changed";
this->appWidgetUpdate();
});
connect(GlobalSettings::getInstance(), &GlobalSettings::styleChanged, [ & ] {
qDebug() << "style changed";
connect(&GlobalSettings::getInstance(), &GlobalSettings::valueChanged, [ & ] (const QString& key, QVariant value) {
if (key == TRANSPARENCY_KEY || key == STYLE_NAME_KEY) {
this->appWidgetUpdate();
qDebug() << key << " has changed to" << value;
}
});
}
void AppWidgetPlugin::appWidgetRecevie(const QString &eventname, const QString &widgetname, const QDBusVariant &value)
{
qDebug() << widgetname << value.variant();
if (eventname == "enter" or eventname == "return") {
QString keyword = value.variant().toString();
Q_EMIT this->startSearch(keyword);
// if (eventname == "enter" or eventname == "return") {
// QString keyword = value.variant().toString();
// Q_EMIT this->startSearch(keyword);
// } else
if (eventname == "clicked") {
Q_EMIT this->start();
} else {
qWarning() << "event:" << eventname << "has no trigger now.";
}
@ -54,7 +68,7 @@ void AppWidgetPlugin::appWidgetRecevie(const QString &eventname, const QString &
void AppWidgetPlugin::appWidgetUpdate()
{
QString theme = GlobalSettings::getInstance()->getValue(STYLE_NAME_KEY).toString();
QString theme = GlobalSettings::getInstance().getValue(STYLE_NAME_KEY).toString();
QJsonObject obj;
if (theme == "ukui-dark") {
obj.insert("red", QJsonValue(0));
@ -68,7 +82,7 @@ void AppWidgetPlugin::appWidgetUpdate()
obj.insert("placeHolderTextColor", QJsonValue("#72000000"));
}
obj.insert("alpha", QJsonValue(GlobalSettings::getInstance()->getValue(TRANSPARENCY_KEY).toDouble()));
obj.insert("alpha", QJsonValue(GlobalSettings::getInstance().getValue(TRANSPARENCY_KEY).toDouble()));
QString jsonData = QString(QJsonDocument(obj).toJson());
QVariantMap dataMap;

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
*/
#ifndef SEARCH_H
#define SEARCH_H
@ -27,6 +46,7 @@ public:
Q_SIGNALS:
void startSearch(QString);
void start();
private:
QDBusInterface* m_interface = nullptr;

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
*/
#include "ukui-search-dbus-service.h"
using namespace UkuiSearch;

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
*/
#ifndef UKUISEARCHDBUSSERVICE_H
#define UKUISEARCHDBUSSERVICE_H

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#include "ukui-search-gui.h"
#include <QScreen>
#include <QTranslator>

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#ifndef UKUISEARCHGUI_H
#define UKUISEARCHGUI_H

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
*/
#include "best-list-view.h"
#define MAIN_MARGINS 0,0,0,0
#define MAIN_SPACING 0
@ -148,21 +167,6 @@ const bool &BestListView::isExpanded()
return m_model->isExpanded();
}
/**
* @brief BestListView::onMenuTriggered
* @param action
*/
void BestListView::onMenuTriggered(QAction *action)
{
//NEW_TODO 接口调整后需要修改
// SearchPluginIface *plugin = SearchPluginManager::getInstance()->getPlugin(m_plugin_id);
// if (plugin) {
//// plugin->openAction(action->text(), m_model->getKey(this->currentIndex()));
// } else {
// qWarning()<<"Get plugin failed!";
// }
}
void BestListView::mousePressEvent(QMouseEvent *event)
{
m_tmpCurrentIndex = this->currentIndex();

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
*/
#ifndef BESTLISTVIEW_H
#define BESTLISTVIEW_H
#include <QTreeView>
@ -34,7 +53,6 @@ public Q_SLOTS:
void onItemListChanged(const int &);
void setExpanded(const bool &);
const bool &isExpanded();
void onMenuTriggered(QAction *);
protected:
void mousePressEvent(QMouseEvent *event);

View File

@ -1,5 +1,25 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
*/
#include "result-view-delegate.h"
#include <QPainterPath>
#include <QApplication>
using namespace UkuiSearch;
static ResultItemStyle *global_instance_of_item_style = nullptr;

View File

@ -30,7 +30,6 @@
#include <QSyntaxHighlighter>
#include <QTextCharFormat>
#include <QRegExp>
#include "global-settings.h"
namespace UkuiSearch {
class HightLightEffectHelper : public QSyntaxHighlighter

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
*/
#include "result-view.h"
#define MAIN_MARGINS 0,0,0,0
#define MAIN_SPACING 0
@ -306,6 +325,7 @@ const bool &ResultView::isExpanded()
*/
void ResultView::onMenuTriggered(QAction *action)
{
Q_UNUSED(action)
//NEW_TODO 接口调整后需要修改
SearchPluginIface *plugin = SearchPluginManager::getInstance()->getPlugin(m_plugin_id);
if (plugin) {

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
*/
#ifndef RESULTVIEW_H
#define RESULTVIEW_H
#include <QTreeView>

View File

@ -3,11 +3,9 @@ INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/best-list-view.h \
$$PWD/result-view-delegate.h \
$$PWD/result-view.h \
$$PWD/web-search-view.h
$$PWD/result-view.h
SOURCES += \
$$PWD/best-list-view.cpp \
$$PWD/result-view-delegate.cpp \
$$PWD/result-view.cpp \
$$PWD/web-search-view.cpp
$$PWD/result-view.cpp

View File

@ -1,195 +0,0 @@
/*
*
* Copyright (C) 2021, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: jixiaoxu <jixiaoxu@kylinos.cn>
*
*/
#include <QDBusReply>
#include "web-search-view.h"
#define MAIN_MARGINS 0,0,0,0
#define MAIN_SPACING 0
#define TITLE_HEIGHT 30
#define VIEW_ICON_SIZE 24
using namespace UkuiSearch;
WebSearchView::WebSearchView(QWidget *parent) : QTreeView(parent)
{
setStyle(ResultItemStyle::getStyle());
this->setFrameShape(QFrame::NoFrame);
this->viewport()->setAutoFillBackground(false);
this->setRootIsDecorated(false);
this->setIconSize(QSize(VIEW_ICON_SIZE, VIEW_ICON_SIZE));
this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
this->setSelectionBehavior(QAbstractItemView::SelectRows);
this->setSelectionMode(QAbstractItemView::SingleSelection);
this->setHeaderHidden(true);
m_model = new WebSearchModel(this);
this->setModel(m_model);
m_styleDelegate = new ResultViewDelegate(this);
this->setItemDelegate(m_styleDelegate);
}
bool WebSearchView::isSelected()
{
return m_is_selected;
}
int WebSearchView::showHeight()
{
return this->rowHeight(this->model()->index(0, 0, QModelIndex()));
}
QModelIndex WebSearchView::getModlIndex(int row, int column)
{
return this->m_model->index(row, column);
}
void WebSearchView::clearSelectedRow()
{
if (!m_is_selected) {
this->blockSignals(true);
//this->clearSelection();
this->setCurrentIndex(QModelIndex());
this->blockSignals(false);
}
}
void WebSearchView::startSearch(const QString & keyword)
{
this->m_styleDelegate->setSearchKeyword(keyword);
this->m_model->startSearch(keyword);
m_keyWord = keyword;
}
void WebSearchView::mouseReleaseEvent(QMouseEvent *event)
{
QModelIndex index = indexAt(event->pos());
if (!index.isValid()) {
this->clearSelection();
}
return QTreeView::mouseReleaseEvent(event);
}
void WebSearchView::LaunchBrowser()
{
QString address;
QString engine = GlobalSettings::getInstance()->getValue("web_engine").toString();
if(!engine.isEmpty()) {
if(engine == "360") {
address = "https://so.com/s?q=" + m_keyWord; //360
} else if(engine == "sougou") {
address = "https://www.sogou.com/web?query=" + m_keyWord; //搜狗
} else {
address = "http://baidu.com/s?word=" + m_keyWord; //百度
}
} else { //默认值
address = "http://baidu.com/s?word=" + m_keyWord ; //百度
}
bool res(false);
QDBusInterface * appLaunchInterface = new QDBusInterface("com.kylin.AppManager",
"/com/kylin/AppManager",
"com.kylin.AppManager",
QDBusConnection::sessionBus());
if(!appLaunchInterface->isValid()) {
qWarning() << qPrintable(QDBusConnection::sessionBus().lastError().message());
res = false;
} else {
appLaunchInterface->setTimeout(10000);
QDBusReply<bool> reply = appLaunchInterface->call("LaunchDefaultAppWithUrl", address);
if(reply.isValid()) {
res = reply;
} else {
qWarning() << "SoftWareCenter dbus called failed!";
res = false;
}
}
if(appLaunchInterface) {
delete appLaunchInterface;
}
appLaunchInterface = NULL;
if (res)
return;
QDesktopServices::openUrl(address);
}
void WebSearchView::initConnections()
{
}
WebSearchWidget::WebSearchWidget(QWidget *parent) : QWidget(parent)
{
this->initUi();
initConnections();
}
QString WebSearchWidget::getWidgetName()
{
return m_titleLabel->text();
}
void WebSearchWidget::setEnabled(const bool &enabled)
{
m_enabled = enabled;
}
void WebSearchWidget::clearResultSelection()
{
this->m_webSearchView->setCurrentIndex(QModelIndex());
}
QModelIndex WebSearchWidget::getModlIndex(int row, int column)
{
return this->m_webSearchView->getModlIndex(row, column);
}
void WebSearchWidget::setResultSelection(const QModelIndex &index)
{
this->m_webSearchView->setCurrentIndex(index);
}
void WebSearchWidget::LaunchBrowser()
{
this->m_webSearchView->LaunchBrowser();
}
void WebSearchWidget::initUi()
{
m_mainLyt = new QVBoxLayout(this);
this->setLayout(m_mainLyt);
m_mainLyt->setContentsMargins(MAIN_MARGINS);
m_mainLyt->setSpacing(MAIN_SPACING);
m_titleLabel = new TitleLabel(this);
m_titleLabel->setText(tr("Web Page"));
m_titleLabel->setFixedHeight(TITLE_HEIGHT);
m_webSearchView = new WebSearchView(this);
m_mainLyt->addWidget(m_titleLabel);
m_mainLyt->addWidget(m_webSearchView);
this->setFixedHeight(m_webSearchView->height() + TITLE_HEIGHT);
this->setFixedWidth(656);
}
void WebSearchWidget::initConnections()
{
connect(this, &WebSearchWidget::startSearch, m_webSearchView, &WebSearchView::startSearch);
connect(m_webSearchView, &WebSearchView::clicked, this, [=] () {
this->LaunchBrowser();
});
}

View File

@ -1,72 +0,0 @@
#ifndef WEBSEARCHVIEW_H
#define WEBSEARCHVIEW_H
#include <QTreeView>
#include <QListView>
#include <QMouseEvent>
#include "web-search-model.h"
#include "result-view-delegate.h"
#include "title-label.h"
namespace UkuiSearch {
class WebSearchView : public QTreeView
{
Q_OBJECT
public:
WebSearchView(QWidget *parent = nullptr);
~WebSearchView() = default;
bool isSelected();
int showHeight();
QModelIndex getModlIndex(int row, int column);
void LaunchBrowser();
public Q_SLOTS:
void clearSelectedRow();
void startSearch(const QString &);
protected:
void mouseReleaseEvent(QMouseEvent *event);
private:
void initConnections();
WebSearchModel * m_model = nullptr;
bool m_is_selected = false;
ResultViewDelegate * m_styleDelegate = nullptr;
QString m_keyWord;
};
class WebSearchWidget : public QWidget
{
Q_OBJECT
public:
WebSearchWidget(QWidget *parent = nullptr);
~WebSearchWidget() = default;
QString getWidgetName();
void setEnabled(const bool&);
void clearResultSelection();
QModelIndex getModlIndex(int row, int column);
void setResultSelection(const QModelIndex &index);
void LaunchBrowser();
private:
void initUi();
void initConnections();
bool m_enabled = true;
QVBoxLayout * m_mainLyt = nullptr;
QHBoxLayout * m_resultLyt = nullptr;
TitleLabel * m_titleLabel = nullptr;
WebSearchView * m_webSearchView = nullptr;
QLabel * m_queryIcon = nullptr;
Q_SIGNALS:
void startSearch(const QString &);
void clearSelectedRow();
void rowClicked();
};
}
#endif // WEBSEARCHVIEW_H

@ -1 +1 @@
Subproject commit 124c661581e0f2e10a47d3cc237f7ade404f1bec
Subproject commit 4734827d7c31936f1485e4513316b05cb7c8714f

View File

@ -1,30 +0,0 @@
#ifndef APPDBCOMMON_H
#define APPDBCOMMON_H
#include <QDir>
namespace UkuiSearch {
#define APP_DATABASE_PATH QDir::homePath()+"/.config/org.ukui/ukui-search/appdata/"
#define APP_DATABASE_NAME "app-info.db"
struct AppInfoResult
{
public:
QString desktopPath;
QString iconName;
QString appLocalName;
QString firstLetter;
QString category;
int top;
int favorite;
int launchTimes;
int lock;
AppInfoResult() : top(0), favorite(0), launchTimes(0), lock(0) {}
};
}
Q_DECLARE_METATYPE(UkuiSearch::AppInfoResult)
#endif // APPDBCOMMON_H

View File

@ -1,31 +0,0 @@
#ifndef APPINFODBUSARGUMENT_H
#define APPINFODBUSARGUMENT_H
#include <QDBusArgument>
#include "app-db-common.h"
namespace UkuiSearch {
QDBusArgument &operator << (QDBusArgument &argument, const AppInfoResult &infoResult)
{
argument.beginStructure();
argument << infoResult.desktopPath << infoResult.iconName << infoResult.appLocalName << infoResult.firstLetter
<< infoResult.category << infoResult.top << infoResult.favorite << infoResult.launchTimes << infoResult.lock;
argument.endStructure();
return argument;
}
const QDBusArgument &operator >> (const QDBusArgument &argument, AppInfoResult &infoResult)
{
argument.beginStructure();
argument >> infoResult.desktopPath >> infoResult.iconName >> infoResult.appLocalName >> infoResult.firstLetter
>> infoResult.category >> infoResult.top >> infoResult.favorite >> infoResult.launchTimes >> infoResult.lock;
argument.endStructure();
return argument;
}
}
#endif // APPINFODBUSARGUMENT_H

View File

@ -0,0 +1,100 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef APPINFODBUSARGUMENT_H
#define APPINFODBUSARGUMENT_H
#include <QDBusArgument>
#include "application-property.h"
namespace UkuiSearch {
QDBusArgument &operator << (QDBusArgument &argument, const ApplicationProperty::Property &property) {
argument.beginStructure();
argument << static_cast<int>(property);
argument.endStructure();
return argument;
}
const QDBusArgument &operator >> (const QDBusArgument &argument, ApplicationProperty::Property &property) {
int value;
argument.beginStructure();
argument >> value;
argument.endStructure();
property = static_cast<ApplicationProperty::Property>(value);
return argument;
}
QDBusArgument &operator << (QDBusArgument &argument, const ApplicationPropertyMap &appPropertyInfo)
{
argument.beginMap(/*qMetaTypeId<ApplicationProperty::Property>()*/QVariant::Int, qMetaTypeId<QDBusVariant>());
for (auto i = appPropertyInfo.constBegin(); i != appPropertyInfo.constEnd(); ++i) {
QDBusVariant dbusVariant(i.value());
argument.beginMapEntry();
argument << static_cast<int>(i.key()) << dbusVariant;
argument.endMapEntry();
}
argument.endMap();
return argument;
}
const QDBusArgument &operator >> (const QDBusArgument &argument, ApplicationPropertyMap &appPropertyInfo)
{
argument.beginMap();
while (!argument.atEnd()) {
int key;
QVariant value;
argument.beginMapEntry();
argument >> key >> value;
argument.endMapEntry();
appPropertyInfo.insert(static_cast<ApplicationProperty::Property>(key), value);
}
argument.endMap();
return argument;
}
QDBusArgument &operator << (QDBusArgument &argument, const ApplicationInfoMap &appInfo)
{
argument.beginMap(QVariant::String, qMetaTypeId<ApplicationPropertyMap>());
for (auto i = appInfo.constBegin(); i != appInfo.constEnd(); ++i) {
argument.beginMapEntry();
argument << i.key() << i.value();
argument.endMapEntry();
}
argument.endMap();
return argument;
}
const QDBusArgument &operator >> (const QDBusArgument &argument, ApplicationInfoMap &appInfo)
{
argument.beginMap();
while (!argument.atEnd()) {
QString key;
ApplicationPropertyMap value;
argument.beginMapEntry();
argument >> key >> value;
argument.endMapEntry();
appInfo.insert(key, value);
}
argument.endMap();
return argument;
}
}
#endif // APPINFODBUSARGUMENT_H

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#ifndef APPINFOTABLEPRIVATE_H
#define APPINFOTABLEPRIVATE_H
@ -11,51 +30,35 @@ namespace UkuiSearch {
class AppInfoTablePrivate : public QObject
{
Q_OBJECT
friend class AppInfoTable;
public:
explicit AppInfoTablePrivate(AppInfoTable *parent = nullptr);
AppInfoTablePrivate(AppInfoTablePrivate &) = delete;
AppInfoTablePrivate &operator =(const AppInfoTablePrivate &) = delete;
//设置应用的置顶和收藏
void setAppFavoritesState(QString &desktopfp, int num);
void setAppTopState(QString &desktopfp, int num);
//改变置顶和收藏应用位置
bool changeFavoriteAppPos(const QString &desktopfp, int pos);
bool changeTopAppPos(const QString &desktopfp, int pos);
//获取所有应用信息
bool getAppInfoResults(QVector<AppInfoResult> &appInfoResults);
//获取单个应用的某个状态(锁定,置顶,打开状态,收藏)
bool getAppLockState(QString &desktopfp, size_t &num);
bool getAppTopState(QString &desktopfp, size_t &num);
bool getAppLaunchedState(QString &desktopfp, size_t &num);
bool getAppFavoriteState(QString &desktopfp, size_t &num);
bool getAppCategory(QString &desktopfp, QString &category);
//添加快捷方式
bool addAppShortcut2Desktop(QString &desktopfp);
bool addAppShortcut2Panel(QString &desktopfp);
void setAppFavoritesState(const QString &desktopfp);
void setAppFavoritesState(const QString &desktopfp, uint num);
void setAppTopState(const QString &desktopfp);
void setAppTopState(const QString &desktopfp, uint num);
void setAppLaunchedState(const QString &desktopFilePath, bool launched);
//搜索接口
bool searchInstallApp(QString &keyWord, QStringList &installAppInfoRes);
bool searchInstallApp(QStringList &keyWord, QStringList &installAppInfoRes);
//卸载应用
bool uninstallApp(QString &desktopfp);
//数据库错误信息
QString lastError(void) const;
//通过pid查找desktop文件
bool tranPidToDesktopFp(uint pid, QString &desktopfp);
bool desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath);
//下面的接口都不外放,暂时没啥用
bool setAppLaunchTimes(QString &desktopfp, size_t num);
bool updateAppLaunchTimes(QString &desktopfp);
bool setAppLockState(QString &desktopfp, size_t num);
bool getAllAppDesktopList(QStringList &list);
bool getFavoritesAppList(QStringList &list);
bool getTopAppList(QStringList &list);
bool getLaunchTimesAppList(QStringList &list);
bool setAppLaunchTimes(const QString &desktopfp, size_t num);
bool updateAppLaunchTimes(const QString &desktopfp);
bool setAppLockState(const QString &desktopfp, size_t num);
private:
~AppInfoTablePrivate();
@ -71,9 +74,10 @@ private:
QString m_ConnectionName;
public Q_SLOTS:
void sendAppDBItemsUpdate(QVector<AppInfoResult> results);
void sendAppDBItemsAdd(QVector<AppInfoResult> results);
void sendAppDBItemsDelete(QStringList desktopfps);
void sendAppDBItemsUpdate(ApplicationInfoMap results);
void sendAppDBItemsUpdateAll(QStringList desktopFilePaths);
void sendAppDBItemsAdd(QStringList desktopFilePaths);
void sendAppDBItemsDelete(QStringList desktopFilePaths);
};

View File

@ -14,20 +14,23 @@
#include <QTime>
#include <QSqlQuery>
#include <QSqlError>
#include <QApplication>
#include <qt5xdg/XdgDesktopFile>
#include <mutex>
#include <QFile>
#include <application-property-helper.h>
using namespace UkuiSearch;
static std::once_flag flag;
static AppInfoTable *global_intance = nullptr;
AppInfoTablePrivate::AppInfoTablePrivate(AppInfoTable *parent) : QObject(parent), q(parent), m_database(new QSqlDatabase())
{
//dbus接收数据库信号
qRegisterMetaType<ApplicationPropertyMap>("ApplicationPropertyMap");
qDBusRegisterMetaType<ApplicationPropertyMap>();
qRegisterMetaType<AppInfoResult>("AppInfoResult");
qRegisterMetaType<QVector<AppInfoResult>>("QVector<AppInfoResult>");
qRegisterMetaType<ApplicationInfoMap>("ApplicationInfoMap");
qDBusRegisterMetaType<ApplicationInfoMap>();
qDBusRegisterMetaType<AppInfoResult>();
qDBusRegisterMetaType<QVector<AppInfoResult>>();
m_signalTransInterface = new QDBusInterface("com.ukui.search.appdb.service",
"/org/ukui/search/appDataBase/signalTransformer",
"org.ukui.search.signalTransformer");
@ -36,8 +39,9 @@ AppInfoTablePrivate::AppInfoTablePrivate(AppInfoTable *parent) : QObject(parent)
qCritical() << "Create privateDirWatcher Interface Failed Because: " << QDBusConnection::sessionBus().lastError();
return;
} else {
connect(m_signalTransInterface, SIGNAL(appDBItemsAdd(QVector<AppInfoResult>)), this, SLOT(sendAppDBItemsAdd(QVector<AppInfoResult>)));
connect(m_signalTransInterface, SIGNAL(appDBItemsUpdate(QVector<AppInfoResult>)), this, SLOT(sendAppDBItemsUpdate(QVector<AppInfoResult>)));
connect(m_signalTransInterface, SIGNAL(appDBItemsUpdate(ApplicationInfoMap)), this, SLOT(sendAppDBItemsUpdate(ApplicationInfoMap)));
connect(m_signalTransInterface, SIGNAL(appDBItemsUpdateAll(QStringList)), this, SLOT(sendAppDBItemsUpdateAll(QStringList)));
connect(m_signalTransInterface, SIGNAL(appDBItemsAdd(QStringList)), this, SLOT(sendAppDBItemsAdd(QStringList)));
connect(m_signalTransInterface, SIGNAL(appDBItemsDelete(QStringList)), this, SLOT(sendAppDBItemsDelete(QStringList)));
}
@ -59,166 +63,33 @@ AppInfoTablePrivate::AppInfoTablePrivate(AppInfoTable *parent) : QObject(parent)
}
}
void AppInfoTablePrivate::setAppFavoritesState(QString &desktopfp, int num)
void AppInfoTablePrivate::setAppFavoritesState(const QString &desktopfp)
{
m_appDBInterface->call("updateFavoritesState", desktopfp);
}
void AppInfoTablePrivate::setAppFavoritesState(const QString &desktopfp, uint num)
{
m_appDBInterface->call("updateFavoritesState", desktopfp, num);
}
void AppInfoTablePrivate::setAppTopState(QString &desktopfp, int num)
void AppInfoTablePrivate::setAppTopState(const QString &desktopfp)
{
m_appDBInterface->call("updateTopState", desktopfp);
}
void AppInfoTablePrivate::setAppTopState(const QString &desktopfp, uint num)
{
m_appDBInterface->call("updateTopState", desktopfp, num);
}
bool AppInfoTablePrivate::changeFavoriteAppPos(const QString &desktopfp, int pos)
void AppInfoTablePrivate::setAppLaunchedState(const QString &desktopFilePath, bool launched)
{
QDBusReply<bool> reply = m_appDBInterface->call("changeFavoriteAppPos", desktopfp, pos);
if (reply.isValid()) {
return reply.value();
} else {
qDebug() << m_appDBInterface->lastError();
return false;
}
}
bool AppInfoTablePrivate::changeTopAppPos(const QString &desktopfp, int pos)
{
QDBusReply<bool> reply = m_appDBInterface->call("changeTopAppPos", desktopfp, pos);
if (reply.isValid()) {
return reply.value();
} else {
qDebug() << m_appDBInterface->lastError();
return false;
}
}
bool AppInfoTablePrivate::getAppInfoResults(QVector<AppInfoResult> &appInfoResults)
{
QDBusReply<QVector<AppInfoResult>> reply = m_appDBInterface->call("getAppInfoResults");
if (reply.isValid()) {
appInfoResults = reply.value();
return true;
} else {
return false;
}
}
bool AppInfoTablePrivate::getAppLockState(QString &desktopfp, size_t &num)
{
QDBusReply<int> reply = m_appDBInterface->call("getAppLockState", desktopfp);
if (!reply.isValid()) {
qWarning() << m_appDBInterface->lastError();
return false;
} else {
num = reply.value();
if (num == -1) {
qWarning() << "There's something wrong while using database";
return false;
}
return true;
}
}
bool AppInfoTablePrivate::getAppTopState(QString &desktopfp, size_t &num)
{
QDBusReply<int> reply = m_appDBInterface->call("getAppTopState", desktopfp);
if (!reply.isValid()) {
qWarning() << m_appDBInterface->lastError();
return false;
} else {
num = reply.value();
if (num == -1) {
qWarning() << "There's something wrong while using database";
return false;
}
return true;
}
}
bool AppInfoTablePrivate::getAppLaunchedState(QString &desktopfp, size_t &num)
{
QDBusReply<int> reply = m_appDBInterface->call("getAppLaunchedState", desktopfp);
if (!reply.isValid()) {
qWarning() << m_appDBInterface->lastError();
return false;
} else {
num = reply.value();
if (num == -1) {
qWarning() << "There's something wrong while using database";
return false;
}
return true;
}
}
bool AppInfoTablePrivate::getAppFavoriteState(QString &desktopfp, size_t &num)
{
QDBusReply<int> reply = m_appDBInterface->call("getAppFavoriteState", desktopfp);
if (!reply.isValid()) {
qWarning() << m_appDBInterface->lastError();
return false;
} else {
num = reply.value();
if (num == -1) {
qWarning() << "There's something wrong while using database";
return false;
}
return true;
}
}
bool AppInfoTablePrivate::getAppCategory(QString &desktopfp, QString &category)
{
QDBusReply<QString> reply = m_appDBInterface->call("getAppCategory", desktopfp);
if (reply.isValid()) {
category = reply.value();
return true;
} else {
qDebug() << m_appDBInterface->lastError();
return false;
}
}
bool AppInfoTablePrivate::addAppShortcut2Desktop(QString &desktopfp)
{
bool res(true);
QString dirpath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
QFileInfo fileInfo(desktopfp);
QString desktopfn = fileInfo.fileName();
QFile file(desktopfp);
QString newName = QString(dirpath + "/" + desktopfn);
if(file.copy(QString(dirpath + "/" + desktopfn))) {
QProcess process;
process.startDetached(QString("chmod a+x %1").arg(newName));
} else {
res = false;
}
return res;
}
bool AppInfoTablePrivate::addAppShortcut2Panel(QString &desktopfp)
{
bool res(true);
QDBusInterface iface("com.ukui.panel.desktop",
"/",
"com.ukui.panel.desktop",
QDBusConnection::sessionBus());
if(iface.isValid()) {
QDBusReply<bool> isExist = iface.call("CheckIfExist", desktopfp);
if(isExist) {
qWarning() << "Add shortcut to panel failed, because it is already existed!";
} else {
QDBusReply<bool> ret = iface.call("AddToTaskbar", desktopfp);
if (ret.value()) {
qDebug() << "Add shortcut to panel success.";
} else {
qWarning() << "Add shortcut to panel failed, reply:" << ret.error();
res = false;
}
}
} else {
res = false;
}
return res;
ApplicationInfoMap infoMap;
infoMap[desktopFilePath].insert(ApplicationProperty::Launched, launched);
QVariant var;
var.setValue(infoMap);
m_appDBInterface->call("setValue", var);
}
bool AppInfoTablePrivate::searchInstallApp(QString &keyWord, QStringList &installAppInfoRes)
@ -300,54 +171,36 @@ bool AppInfoTablePrivate::searchInstallApp(QStringList &keyWord, QStringList &in
return res;
}
bool AppInfoTablePrivate::uninstallApp(QString &desktopfp)
{
bool res(false);
QString cmd = QString("kylin-uninstaller %1")
.arg(desktopfp.toLocal8Bit().data());
res = QProcess::startDetached(cmd);
qDebug() << "kylin-uninstaller uninstall" << cmd << res;
return res;
/*
bool isOsReleaseUbuntu(false);
QFile file("/etc/os-release");
if (file.open(QFile::ReadOnly)) {
QByteArray line = file.readLine();
file.close();
if (QString(line).contains("Ubuntu")) { //目前已无效
isOsReleaseUbuntu = true;
}
}
QString cmd;
QProcess process;
if (!isOsReleaseUbuntu) {
cmd = QString("kylin-uninstaller %1")
.arg(desktopfp.toLocal8Bit().data());
res = QProcess::startDetached(cmd);
qDebug() << "kylin-uninstaller uninstall" << cmd << res;
} else {
cmd = QString("dpkg -S " + desktopfp);
process.start("sh", QStringList() << "-c" << cmd);
process.waitForFinished();
QString output = process.readAllStandardOutput().trimmed();
QString packageName = output.split(":").at(0);
cmd = QString("kylin-installer -remove %0")
.arg(packageName.toLocal8Bit().data());
res = QProcess::startDetached(cmd);
qDebug() << "dpkg -S uninstall" << cmd << res;
}
return res;
*/
}
QString AppInfoTablePrivate::lastError() const
{
return m_database->lastError().text();
}
bool AppInfoTablePrivate::setAppLaunchTimes(QString &desktopfp, size_t num)
bool AppInfoTablePrivate::tranPidToDesktopFp(uint pid, QString &desktopfp)
{
QDBusReply<QString> reply = m_appDBInterface->call("tranPidToDesktopFp", pid);
if (reply.isValid()) {
desktopfp = reply.value();
return true;
} else {
qDebug() << m_appDBInterface->lastError();
return false;
}
}
bool AppInfoTablePrivate::desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath)
{
QDBusReply<QString> reply = m_appDBInterface->call("desktopFilePathFromName", desktopFileName);
if (reply.isValid()) {
desktopFilePath = reply.value();
return true;
} else {
qDebug() << m_appDBInterface->lastError();
return false;
}
}
bool AppInfoTablePrivate::setAppLaunchTimes(const QString &desktopfp, size_t num)
{
bool res(true);
if (m_database->transaction()) {
@ -373,7 +226,7 @@ bool AppInfoTablePrivate::setAppLaunchTimes(QString &desktopfp, size_t num)
return res;
}
bool AppInfoTablePrivate::updateAppLaunchTimes(QString &desktopfp)
bool AppInfoTablePrivate::updateAppLaunchTimes(const QString &desktopfp)
{
bool res(true);
if (m_database->transaction()) {
@ -410,7 +263,7 @@ bool AppInfoTablePrivate::updateAppLaunchTimes(QString &desktopfp)
return res;
}
bool AppInfoTablePrivate::setAppLockState(QString &desktopfp, size_t num)
bool AppInfoTablePrivate::setAppLockState(const QString &desktopfp, size_t num)
{
bool res(true);
if (m_database->transaction()) {
@ -435,94 +288,6 @@ bool AppInfoTablePrivate::setAppLockState(QString &desktopfp, size_t num)
return res;
}
bool AppInfoTablePrivate::getAllAppDesktopList(QStringList &list)
{
bool res(true);
QSqlQuery sql(*m_database);
QString cmd = QString("SELECT DESKTOP_FILE_PATH FROM APPINFO");
if (sql.exec(cmd)) {
while (sql.next()) {
list.append(sql.value(0).toString());
}
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database->lastError();
res = false;
}
return res;
}
bool AppInfoTablePrivate::getFavoritesAppList(QStringList &list)
{
bool res(true);
QSqlQuery sql(*m_database);
QString cmd = QString("SELECT DESKTOP_FILE_PATH FROM APPINFO WHERE FAVORITES!=0 ORDER BY FAVORITES");
if (sql.exec(cmd)) {
while (sql.next()) {
list.append(sql.value(0).toString());
}
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database->lastError();
res = false;
}
return res;
}
bool AppInfoTablePrivate::getTopAppList(QStringList &list)
{
bool res(true);
QSqlQuery sql(*m_database);
QString cmd = QString("SELECT DESKTOP_FILE_PATH FROM APPINFO WHERE TOP!=0 ORDER BY TOP");
if (sql.exec(cmd)) {
while (sql.next()) {
list.append(sql.value(0).toString());
}
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database->lastError();
res = false;
}
return res;
}
bool AppInfoTablePrivate::getLaunchTimesAppList(QStringList &list)
{
bool res(true);
if (m_database->transaction()) {
QSqlQuery sql(*m_database);
QSqlQuery sqlque(*m_database);
QString cmd = QString("SELECT DESKTOP_FILE_PATH FROM APPINFO ORDER BY LAUNCH_TIMES");
int count = 0;
if (sql.exec(cmd)) {
while (sql.next()) {
list.append(sql.value(0).toString());
cmd = QString("UPDATE appInfo SET TOP=%1 WHERE DESKTOP_FILE_PATH='%2'")
.arg(++count)
.arg(sql.value(0).toString());
if (!sqlque.exec(cmd)) {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database->lastError();
res = false;
break;
}
}
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database->lastError();
res = false;
}
if (!m_database->commit()) {
qWarning() << "Failed to commit !" << cmd;
m_database->rollback();
res = false;
}
} else {
qWarning() << "Failed to start transaction mode!!!";
res = false;
}
return res;
}
AppInfoTablePrivate::~AppInfoTablePrivate()
{
this->closeDataBase();
@ -564,83 +329,228 @@ void AppInfoTablePrivate::closeDataBase()
QSqlDatabase::removeDatabase(m_ConnectionName);
}
void AppInfoTablePrivate::sendAppDBItemsUpdate(QVector<AppInfoResult> results)
void AppInfoTablePrivate::sendAppDBItemsUpdate(ApplicationInfoMap results)
{
Q_EMIT q->appDBItems2BUpdate(results);
}
void AppInfoTablePrivate::sendAppDBItemsAdd(QVector<AppInfoResult> results)
void AppInfoTablePrivate::sendAppDBItemsUpdateAll(QStringList desktopFilePaths)
{
Q_EMIT q->appDBItems2BAdd(results);
Q_EMIT q->appDBItems2BUpdateAll(desktopFilePaths);
}
void AppInfoTablePrivate::sendAppDBItemsDelete(QStringList desktopfps)
void AppInfoTablePrivate::sendAppDBItemsAdd(QStringList desktopFilePaths)
{
Q_EMIT q->appDBItems2BDelete(desktopfps);
Q_EMIT q->appDBItems2BAdd(desktopFilePaths);
}
void AppInfoTablePrivate::sendAppDBItemsDelete(QStringList desktopFilePaths)
{
Q_EMIT q->appDBItems2BDelete(desktopFilePaths);
}
AppInfoTable *AppInfoTable::self()
{
std::call_once(flag, [ & ] {
global_intance = new AppInfoTable();
});
return global_intance;
}
AppInfoTable::AppInfoTable(QObject *parent) : QObject(parent), d(new AppInfoTablePrivate(this))
{
}
void AppInfoTable::setAppFavoritesState(QString &desktopfp, size_t num)
bool AppInfoTable::query(ApplicationPropertyMap &propertyMap, const QString &desktopFile, ApplicationProperties properties)
{
QString field;
for(const ApplicationProperty::Property &pro : properties) {
field.append(ApplicationPropertyHelper(pro).dataBaseField() + ",");
}
field.remove(field.length() - 1, 1);
if(field.isEmpty()) {
return true;
}
QSqlQuery query(*d->m_database);
query.setForwardOnly(true);
query.prepare(QString("SELECT %0 FROM APPINFO WHERE DESKTOP_FILE_PATH=:desktopFile").arg(field));
query.bindValue(":desktopFile", desktopFile);
if (!query.exec()) {
qWarning() << d->m_database->lastError() << query.lastError();
return false;
}
while (query.next()) {
for(int i = 0; i< properties.size(); i++) {
propertyMap.insert(properties.at(i), query.value(i));
}
}
return true;
}
bool AppInfoTable::query(ApplicationInfoMap &infoMap, ApplicationProperties properties)
{
QString field;
for(const ApplicationProperty::Property &pro : properties) {
field.append(ApplicationPropertyHelper(pro).dataBaseField() + ",");
}
if(!properties.contains(ApplicationProperty::Property::DesktopFilePath)) {
field.append(ApplicationPropertyHelper(ApplicationProperty::Property::DesktopFilePath).dataBaseField());
} else if(!field.isEmpty()) {
field.remove(field.length() - 1, 1);
}
QString sql = QString("SELECT %0 FROM APPINFO").arg(field);
QSqlQuery query(*d->m_database);
query.setForwardOnly(true);
if (!query.exec(sql)) {
qWarning() << d->m_database->lastError() << sql;
return false;
}
while (query.next()) {
ApplicationPropertyMap propertyMap;
for(const ApplicationProperty::Property &pro : properties) {
propertyMap.insert(pro, query.value(ApplicationPropertyHelper(pro).dataBaseField()));
}
infoMap.insert(query.value(ApplicationPropertyHelper(ApplicationProperty::Property::DesktopFilePath).dataBaseField()).toString(), propertyMap);
}
return true;
}
bool AppInfoTable::query(ApplicationInfoMap &infoMap, ApplicationProperties properties, ApplicationPropertyMap restrictions)
{
QString field;
for(const ApplicationProperty::Property &pro : properties) {
field.append(ApplicationPropertyHelper(pro).dataBaseField() + ",");
}
if(!properties.contains(ApplicationProperty::Property::DesktopFilePath)) {
field.append(ApplicationPropertyHelper(ApplicationProperty::Property::DesktopFilePath).dataBaseField());
} else if(!field.isEmpty()) {
field.remove(field.length() - 1, 1);
}
QString condition;
for (const ApplicationProperty::Property prop: restrictions.keys()) {
condition.append(ApplicationPropertyHelper(prop).dataBaseField() + "=? AND ");
}
condition = condition.left(condition.lastIndexOf(" AND "));
QSqlQuery query(*d->m_database);
query.setForwardOnly(true);
query.prepare(QString("SELECT %0 FROM APPINFO WHERE %1")
.arg(field)
.arg(condition));
int i = 0;
for (const QVariant &conditionValue : restrictions) {
query.bindValue(i, conditionValue);
i++;
}
if (!query.exec()) {
qWarning() << d->m_database->lastError() << query.lastError();
return false;
}
while (query.next()) {
ApplicationPropertyMap propertyMap;
for(const ApplicationProperty::Property &pro : properties) {
propertyMap.insert(pro, query.value(ApplicationPropertyHelper(pro).dataBaseField()));
}
infoMap.insert(query.value(ApplicationPropertyHelper(ApplicationProperty::Property::DesktopFilePath).dataBaseField()).toString(), propertyMap);
}
return true;
}
bool AppInfoTable::query(ApplicationInfoMap &infoMap, ApplicationProperties properties, const QStringList &keywords, ApplicationPropertyMap restrictions)
{
QString field;
for(const ApplicationProperty::Property &pro : properties) {
field.append(ApplicationPropertyHelper(pro).dataBaseField() + ",");
}
if(!properties.contains(ApplicationProperty::Property::DesktopFilePath)) {
field.append(ApplicationPropertyHelper(ApplicationProperty::Property::DesktopFilePath).dataBaseField());
} else if(!field.isEmpty()) {
field.remove(field.length() - 1, 1);
}
QString condition;
for (const ApplicationProperty::Property prop: restrictions.keys()) {
condition.append(ApplicationPropertyHelper(prop).dataBaseField() + "=? AND ");
}
QString keywordCondition;
for(const QString& keyword : keywords) {
if(keyword.size() < 2) {
keywordCondition.append("(ifnull(LOCAL_NAME, '') like ? or ifnull(NAME_EN, '') like ? or ifnull(NAME_ZH, '') like ? or ifnull(FIRST_LETTER_OF_PINYIN, '') like ?) AND");
} else {
keywordCondition.append("(ifnull(LOCAL_NAME, '') like ? or ifnull(NAME_EN, '') like ? or ifnull(NAME_ZH, '') like ? or ifnull(FIRST_LETTER_OF_PINYIN, '') like ? or ifnull(PINYIN_NAME, '') like ?) AND");
}
}
if(!keywordCondition.isEmpty()) {
keywordCondition.remove(keywordCondition.length() - 3, 3);
}
QString sql = QString("SELECT %0 FROM APPINFO WHERE %1 %2 ORDER BY LENGTH(LOCAL_NAME)").arg(field).arg(condition).arg(keywordCondition);
QSqlQuery query(*d->m_database);
query.setForwardOnly(true);
query.prepare(sql);
int count = 0;
for (const QVariant &conditionValue : restrictions) {
query.bindValue(count, conditionValue);
count++;
}
for(const QString &keyword : keywords) {
int i = 5;
if(keyword.size() < 2) {
i--;
}
for (int bindCount = 0; bindCount < i; bindCount++) {
query.bindValue(count, "%" + keyword + "%");
count++;
}
}
if (!query.exec()) {
qWarning() << d->m_database->lastError() << query.lastError() << query.lastQuery() << query.boundValues();
return false;
}
while (query.next()) {
ApplicationPropertyMap propertyMap;
for(const ApplicationProperty::Property &pro : properties) {
propertyMap.insert(pro, query.value(ApplicationPropertyHelper(pro).dataBaseField()));
}
infoMap.insert(query.value(ApplicationPropertyHelper(ApplicationProperty::Property::DesktopFilePath).dataBaseField()).toString(), propertyMap);
}
return true;
}
void AppInfoTable::setAppFavoritesState(const QString &desktopfp)
{
return d->setAppFavoritesState(desktopfp);
}
void AppInfoTable::setAppFavoritesState(const QString &desktopfp, size_t num)
{
return d->setAppFavoritesState(desktopfp, num);
}
void AppInfoTable::setAppTopState(QString &desktopfp, size_t num)
void AppInfoTable::setAppTopState(const QString &desktopfp, size_t num)
{
return d->setAppTopState(desktopfp, num);
}
bool AppInfoTable::getAppCategory(QString &desktopfp, QString &category)
void AppInfoTable::setAppLaunchedState(const QString &desktopFilePath, bool launched)
{
return d->getAppCategory(desktopfp, category);
return d->setAppLaunchedState(desktopFilePath, launched);
}
bool AppInfoTable::changeFavoriteAppPos(const QString &desktopfp, size_t pos)
void AppInfoTable::setAppTopState(const QString &desktopfp)
{
return d->changeFavoriteAppPos(desktopfp, pos);
}
bool AppInfoTable::changeTopAppPos(const QString &desktopfp, size_t pos)
{
return d->changeTopAppPos(desktopfp, pos);
}
bool AppInfoTable::getAppInfoResults(QVector<AppInfoResult> &appInfoResults)
{
return d->getAppInfoResults(appInfoResults);
}
bool AppInfoTable::getAppLockState(QString &desktopfp, size_t &num)
{
return d->getAppLockState(desktopfp, num);
}
bool AppInfoTable::getAppTopState(QString &desktopfp, size_t &num)
{
return d->getAppTopState(desktopfp, num);
}
bool AppInfoTable::getAppLaunchedState(QString &desktopfp, size_t &num)
{
return d->getAppLaunchedState(desktopfp, num);
}
bool AppInfoTable::getAppFavoriteState(QString &desktopfp, size_t &num)
{
return d->getAppFavoriteState(desktopfp, num);
}
bool AppInfoTable::addAppShortcut2Desktop(QString &desktopfp)
{
return d->addAppShortcut2Desktop(desktopfp);
}
bool AppInfoTable::addAppShortcut2Panel(QString &desktopfp)
{
return d->addAppShortcut2Panel(desktopfp);
return d->setAppTopState(desktopfp);
}
bool AppInfoTable::searchInstallApp(QString &keyWord, QStringList &installAppInfoRes)
@ -653,48 +563,33 @@ bool AppInfoTable::searchInstallApp(QStringList &keyWord, QStringList &installAp
return d->searchInstallApp(keyWord, installAppInfoRes);
}
bool AppInfoTable::uninstallApp(QString &desktopfp)
{
return d->uninstallApp(desktopfp);
}
QString AppInfoTable::lastError() const
{
return d->lastError();
}
bool AppInfoTable::tranPidToDesktopFp(uint pid, QString &desktopfp)
{
return d->tranPidToDesktopFp(pid, desktopfp);
}
bool AppInfoTable::desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath)
{
return d->desktopFilePathFromName(desktopFileName, desktopFilePath);
}
//下面接口暂时没啥用,不外放。
bool AppInfoTable::setAppLaunchTimes(QString &desktopfp, size_t num)
bool AppInfoTable::setAppLaunchTimes(const QString &desktopfp, size_t num)
{
return d->setAppLaunchTimes(desktopfp, num);
}
bool AppInfoTable::updateAppLaunchTimes(QString &desktopfp)
bool AppInfoTable::updateAppLaunchTimes(const QString &desktopfp)
{
return d->updateAppLaunchTimes(desktopfp);
}
bool AppInfoTable::setAppLockState(QString &desktopfp, size_t num)
bool AppInfoTable::setAppLockState(const QString &desktopfp, size_t num)
{
return d->setAppLockState(desktopfp, num);
}
bool AppInfoTable::getAllAppDesktopList(QStringList &list)
{
return d->getAllAppDesktopList(list);
}
bool AppInfoTable::getFavoritesAppList(QStringList &list)
{
return d->getFavoritesAppList(list);
}
bool AppInfoTable::getTopAppList(QStringList &list)
{
return d->getTopAppList(list);
}
bool AppInfoTable::getLaunchTimesAppList(QStringList &list)
{
return d->getLaunchTimesAppList(list);
}

View File

@ -1,74 +1,85 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#ifndef APPINFOTABLE_H
#define APPINFOTABLE_H
#include <QObject>
#include "app-db-common.h"
#include <QSqlQuery>
#include <QDir>
#include "application-property.h"
namespace UkuiSearch {
const static QString APP_DATABASE_PATH = QDir::homePath()+"/.config/org.ukui/ukui-search/appdata/";
const static QString APP_DATABASE_NAME = "app-info.db";
class AppInfoTablePrivate;
class AppInfoTable : public QObject
{
Q_OBJECT
public:
explicit AppInfoTable(QObject *parent = nullptr);
static AppInfoTable* self();
AppInfoTable(AppInfoTable &) = delete;
AppInfoTable &operator =(const AppInfoTable &) = delete;
bool query(ApplicationPropertyMap &propertyMap, const QString &desktopFile, ApplicationProperties properties);
bool query(ApplicationInfoMap &infoMap, ApplicationProperties properties);
bool query(ApplicationInfoMap &infoMap, ApplicationProperties properties, ApplicationPropertyMap restrictions);
bool query(ApplicationInfoMap &infoMap, ApplicationProperties properties, const QStringList &keywords, ApplicationPropertyMap restrictions);
/**
* @brief AppInfoTable::setAppFavoritesState
* set the favorites state of the app
* set the app to favorites apps(default is at 1)
* @param desktopfp: the desktop file path of app
*/
void setAppFavoritesState(const QString &desktopfp);
/**
* @brief AppInfoTable::setAppFavoritesState
* set the favorites state of the app, you can also use to change the position of the app which is one of the Favorites Apps
* @param desktopfp: the desktop file path of app
* @param num: the favorites app's order(from 1)
*/
void setAppFavoritesState(QString &desktopfp, size_t num);
void setAppFavoritesState(const QString &desktopfp, size_t num);
/**
* @brief AppInfoTable::setAppTopState
* set the top state of the app
* set the app to top apps(default is at 1)
* @param desktopfp: desktop file path of app
*/
void setAppTopState(const QString &desktopfp);
/**
* @brief AppInfoTable::setAppTopState
* set the top state of the app, you can also use to change the position of the app which is one of the Top Apps
* @param desktopfp: the desktop file path of app
* @param num: the top app's order(from 1)
*/
void setAppTopState(QString &desktopfp, size_t num);
void setAppTopState(const QString &desktopfp, size_t num);
/**
* @brief AppInfoTable::changeFavoriteAppPos
* change the position of the app which is one of the Favorites Apps
* @param desktopfp: desktop file path of app
* @param pos: the position which the app will be changed into
*/
bool changeFavoriteAppPos(const QString &desktopfp, size_t pos);
/**
* @brief AppInfoTable::changeTopAppPos
* hange the position of the app which is one of the Top Apps
* @param desktopfp: desktop file path of app
* @param pos: the position which the app will be changed into
* @return bool: true if success, else false
*/
bool changeTopAppPos(const QString &desktopfp, size_t pos);
/**
* @brief AppInfoTable::getAppInfoResults
* Get all App infos by passing AppInforesult Vector.
* @param AppInfoResults: a struct which includes all infos of each application
* @return bool: true if success, else false
*/
bool getAppInfoResults(QVector<AppInfoResult> &appInfoResults);
bool getAppLockState(QString &desktopfp, size_t &num);
bool getAppTopState(QString &desktopfp, size_t &num);
bool getAppLaunchedState(QString &desktopfp, size_t &num);
bool getAppFavoriteState(QString &desktopfp, size_t &num);
bool getAppCategory(QString &desktopfp, QString &category);
bool addAppShortcut2Desktop(QString &desktopfp);
bool addAppShortcut2Panel(QString &desktopfp);
void setAppLaunchedState(const QString &desktopFilePath, bool launched);
bool searchInstallApp(QString &keyWord, QStringList &installAppInfoRes);
bool searchInstallApp(QStringList &keyWord, QStringList &installAppInfoRes);
bool uninstallApp(QString &desktopfp);
/**
* @brief AppInfoTable::lastError
@ -77,23 +88,32 @@ public:
*/
QString lastError(void) const;
private:
//暂不外放的接口
bool setAppLaunchTimes(QString &desktopfp, size_t num);
bool setAppLockState(QString &desktopfp, size_t num);
bool updateAppLaunchTimes(QString &desktopfp);
bool getAllAppDesktopList(QStringList &list);
bool getFavoritesAppList(QStringList &list);
bool getTopAppList(QStringList &list);
bool getLaunchTimesAppList(QStringList &list);
/**
* @brief AppInfoTable::tranPid2DesktopFp
* find the desktop file path of the process which corresponds to the pid
* @param pid: the pid of the process which need to get its desktop file path
* @param desktopfp: the desktop file path of the process corresponding to pid
* @return bool:true if success,else false
*/
bool tranPidToDesktopFp(uint pid, QString &desktopfp);
bool desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath);
private:
//暂不外放的接口
bool setAppLaunchTimes(const QString &desktopfp, size_t num);
bool setAppLockState(const QString &desktopfp, size_t num);
bool updateAppLaunchTimes(const QString &desktopfp);
private:
explicit AppInfoTable(QObject *parent = nullptr);
AppInfoTablePrivate *d;
Q_SIGNALS:
void DBOpenFailed();
void appDBItems2BUpdate(QVector<AppInfoResult>);
void appDBItems2BAdd(QVector<AppInfoResult>);
void appDBItems2BUpdate(ApplicationInfoMap);
void appDBItems2BUpdateAll(QStringList);
void appDBItems2BAdd(QStringList);
void appDBItems2BDelete(QStringList);
};
}

View File

@ -2,8 +2,16 @@ INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/app-info-table-private.h \
$$PWD/app-info-table.h
$$PWD/app-info-table.h \
# $$PWD/application-info-storage.h \
$$PWD/application-info.h \
$$PWD/application-property-helper.h \
$$PWD/application-property.h \
$$PWD/app-info-dbus-argument.h
SOURCES += \
$$PWD/app-info-table.cpp
$$PWD/app-info-table.cpp \
# $$PWD/application-info-storage.cpp \
$$PWD/application-info.cpp \
$$PWD/application-property-helper.cpp

View File

@ -0,0 +1,69 @@
#include "application-info-storage.h"
#include <QMap>
using namespace UkuiSearch;
namespace UkuiSearch {
class ApplicationInfoStoragePrivate
{
friend class ApplicationInfoStorage;
private:
Properties m_properties;
ApplicationInfoMap m_data;
};
}
ApplicationInfoStorage::ApplicationInfoStorage(): d(new ApplicationInfoStoragePrivate)
{
}
ApplicationInfoStorage::ApplicationInfoStorage(Properties properties): d(new ApplicationInfoStoragePrivate)
{
d->m_properties = properties;
}
ApplicationInfoStorage::ApplicationInfoStorage(const ApplicationInfoStorage &other): d(new ApplicationInfoStoragePrivate(*other.d))
{
}
ApplicationInfoStorage::~ApplicationInfoStorage()
{
if(d) {
delete d;
d = nullptr;
}
}
ApplicationInfoStorage &ApplicationInfoStorage::operator=(const ApplicationInfoStorage &rhs)
{
*d = *rhs.d;
return *this;
}
QStringList ApplicationInfoStorage::applicationKeys() const
{
return d->m_data.keys();
}
Properties &ApplicationInfoStorage::applicationInfoKeys() const
{
return d->m_properties;
}
QVariant ApplicationInfoStorage::ApplicationInfo(const QString &desktopFile, ApplicationProperty::Property property)
{
return d->m_data.value(desktopFile).value(property);
}
ApplicationInfoMap &ApplicationInfoStorage::allData()
{
return d->m_data;
}
void ApplicationInfoStorage::addData(const QString &desktopFile, ApplicationProperty::Property property, const QVariant &value)
{
if(d->m_data.contains(desktopFile)) {
QMap<ApplicationProperty::Property, QVariant> info = d->m_data.value(desktopFile);
info.insert(property, value);
d->m_data.insert(desktopFile, info);
} else {
d->m_data.insert(desktopFile, QMap<ApplicationProperty::Property, QVariant>{{property, value}});
}
}

View File

@ -0,0 +1,41 @@
#ifndef APPLICATIONINFOSTORAGE_H
#define APPLICATIONINFOSTORAGE_H
#include <QVariant>
#include "application-property.h"
namespace UkuiSearch {
class ApplicationInfoStoragePrivate;
class ApplicationInfoStorage
{
public:
ApplicationInfoStorage();
ApplicationInfoStorage(Properties properties);
ApplicationInfoStorage(const ApplicationInfoStorage &other);
~ApplicationInfoStorage();
ApplicationInfoStorage & operator=(const ApplicationInfoStorage &rhs);
/**
* @brief
* @return desktop路径的QStringlist
*/
QStringList applicationKeys() const;
/**
* @brief
* @return QVector<ApplicationProperty::Property>
*/
Properties &applicationInfoKeys() const;
/**
* @brief
* @param desktopFile
* @param info
* @return info的数据类型格式返回特定信息
*/
QVariant ApplicationInfo(const QString &desktopFile, ApplicationProperty::Property property);
ApplicationInfoMap &allData();
void addData(const QString &desktopFile, ApplicationProperty::Property property, const QVariant &value);
private:
ApplicationInfoStoragePrivate *d = nullptr;
};
}
#endif // APPLICATIONINFOSTORAGE_H

View File

@ -0,0 +1,108 @@
#include "application-info.h"
#include "app-info-table.h"
#include "application-property-helper.h"
using namespace UkuiSearch;
namespace UkuiSearch {
class ApplicationInfoPrivate
{
};
}
ApplicationInfo::ApplicationInfo(QObject *parent)
: QObject(parent), d(new ApplicationInfoPrivate)
{
connect(AppInfoTable::self(), &AppInfoTable::appDBItems2BUpdate, this, &ApplicationInfo::appDBItems2BUpdate);
connect(AppInfoTable::self(), &AppInfoTable::appDBItems2BUpdateAll, this, &ApplicationInfo::appDBItems2BUpdateAll);
connect(AppInfoTable::self(), &AppInfoTable::appDBItems2BAdd, this, &ApplicationInfo::appDBItems2BAdd);
connect(AppInfoTable::self(), &AppInfoTable::appDBItems2BDelete, this, &ApplicationInfo::appDBItems2BDelete);
}
ApplicationInfo::~ApplicationInfo()
{
if(d) {
delete d;
d = nullptr;
}
}
QVariant UkuiSearch::ApplicationInfo::getInfo(const QString &desktopFile, ApplicationProperty::Property property)
{
ApplicationPropertyMap map;
AppInfoTable::self()->query(map, desktopFile, ApplicationProperties{property});
return map.value(property);
}
ApplicationPropertyMap ApplicationInfo::getInfo(const QString &desktopFile, ApplicationProperties properties)
{
ApplicationPropertyMap propertyMap;
AppInfoTable::self()->query(propertyMap, desktopFile, properties);
return propertyMap;
}
ApplicationInfoMap ApplicationInfo::getInfo(ApplicationProperties properties)
{
ApplicationInfoMap infoMap;
AppInfoTable::self()->query(infoMap, properties);
return infoMap;
}
ApplicationInfoMap ApplicationInfo::getInfo(ApplicationProperties properties, ApplicationPropertyMap restrictions)
{
ApplicationInfoMap infoMap;
AppInfoTable::self()->query(infoMap, properties, restrictions);
return infoMap;
}
ApplicationInfoMap ApplicationInfo::searchApp(ApplicationProperties properties, const QString &keyword, ApplicationPropertyMap restrictions)
{
ApplicationInfoMap infoMap;
AppInfoTable::self()->query(infoMap, properties, QStringList{keyword}, restrictions);
return infoMap;
}
ApplicationInfoMap ApplicationInfo::searchApp(ApplicationProperties properties, const QStringList &keywords, ApplicationPropertyMap restrictions)
{
ApplicationInfoMap infoMap;
AppInfoTable::self()->query(infoMap, properties, keywords, restrictions);
return infoMap;
}
void ApplicationInfo::setAppToFavorites(const QString &desktopFilePath)
{
AppInfoTable::self()->setAppFavoritesState(desktopFilePath);
}
void ApplicationInfo::setFavoritesOfApp(const QString &desktopFilePath, size_t num)
{
AppInfoTable::self()->setAppFavoritesState(desktopFilePath, num);
}
void ApplicationInfo::setAppToTop(const QString &desktopFilePath)
{
AppInfoTable::self()->setAppTopState(desktopFilePath);
}
void ApplicationInfo::setTopOfApp(const QString &desktopFilePath, size_t num)
{
AppInfoTable::self()->setAppTopState(desktopFilePath, num);
}
void ApplicationInfo::setAppLaunchedState(const QString &desktopFilePath, bool launched)
{
AppInfoTable::self()->setAppLaunchedState(desktopFilePath, launched);
}
bool ApplicationInfo::tranPidToDesktopFp(int pid, QString &desktopFilePath)
{
return AppInfoTable::self()->tranPidToDesktopFp(pid, desktopFilePath);
}
bool ApplicationInfo::tranPidToDesktopFp(uint pid, QString &desktopFilePath)
{
return AppInfoTable::self()->tranPidToDesktopFp(pid, desktopFilePath);
}
bool ApplicationInfo::desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath)
{
return AppInfoTable::self()->desktopFilePathFromName(desktopFileName, desktopFilePath);
}

View File

@ -0,0 +1,137 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#ifndef APPLICATIONINFO_H
#define APPLICATIONINFO_H
#include <QObject>
#include "application-property.h"
namespace UkuiSearch {
class ApplicationInfoPrivate;
class ApplicationInfo : public QObject
{
Q_OBJECT
public:
explicit ApplicationInfo(QObject *parent = nullptr);
~ApplicationInfo();
/**
* @brief getInfo
* @param desktopFile
* @param property
* @return
*/
QVariant getInfo(const QString &desktopFile, ApplicationProperty::Property property);
/**
* @brief getInfo
* @param desktopFile
* @param properties
* @return
*/
ApplicationPropertyMap getInfo(const QString &desktopFile, ApplicationProperties properties);
/**
* @brief getInfo
* @param property
* @return
*/
ApplicationInfoMap getInfo(ApplicationProperties properties);
/**
* @brief ApplicationInfo::getInfo
* get the application info that meets the restrictions
* @param restrictions: The restrictions that the search results should meet(e.g. u want get the app infos whose top state is 0)
* @param properties: Each application's information should contain these properties
* @return ApplicationInfoMap: the search result
*/
ApplicationInfoMap getInfo(ApplicationProperties properties, ApplicationPropertyMap restrictions);
/**
* @brief ApplicationInfo::searchApp
* @param keyWord: the keyword of this search for applications
* @param installAppInfoRes: the search results of applications
* @return ApplicationInfoMap: the search result
*/
ApplicationInfoMap searchApp(ApplicationProperties properties, const QString &keyword, ApplicationPropertyMap restrictions);
ApplicationInfoMap searchApp(ApplicationProperties properties, const QStringList &keywords, ApplicationPropertyMap restrictions);
/**
* @brief AppInfoTable::setAppToFavorites
* set the app to favorites apps(default is at 1)
* @param desktopfp: the desktop file path of app
*/
void setAppToFavorites(const QString &desktopFilePath);
/**
* @brief AppInfoTable::setFavoritesTo
* set the favorites state of the app to num, you can also use to change the position of the app which is one of the Favorites Apps
* @param desktopfp: the desktop file path of app
* @param num: the favorites app's position(from 1). If num is 0, it will remove the app from the favorites apps
*/
void setFavoritesOfApp(const QString &desktopFilePath, size_t num);
/**
* @brief AppInfoTable::setAppToTop
* set the app to top apps(default is at 1)
* @param desktopfp: desktop file path of app
*/
void setAppToTop(const QString &desktopFilePath);
/**
* @brief AppInfoTable::setAppTopTo
* set the top state of the app to num, you can also use to change the position of the app which is one of the Top Apps
* @param desktopfp: the desktop file path of app
* @param num: the top app's position(from 1). If num is 0, it will remove the app from the top apps
*/
void setTopOfApp(const QString &desktopFilePath, size_t num);
void setAppLaunchedState(const QString &desktopFilePath, bool launched = true);
/**
* @brief ApplicationInfo::tranPid2DesktopFp
* find the desktop file path of the process which corresponds to the pid
* @param pid: the pid of the process which need to get its desktop file path
* @param desktopFilePath: the desktop file path of the process corresponding to pid
* @return bool:true if success,else false
*/
bool tranPidToDesktopFp(int pid, QString &desktopFilePath);//obsolete
bool tranPidToDesktopFp(uint pid, QString &desktopFilePath);
/**
* @brief ApplicationInfo::desktopFilePathFromName
* find the desktop file path of the process which corresponds to the desktop file name (without .desktop)
* @param desktopFileName: the desktop file name of the process which need to get its desktop file path
* @param desktopFilePath: the desktop file path of the process corresponding to pid
* @return bool:true if success,else false
*/
bool desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath);
Q_SIGNALS:
void DBOpenFailed();
void appDBItems2BUpdate(ApplicationInfoMap);
void appDBItems2BUpdateAll(QStringList);
void appDBItems2BAdd(QStringList);
void appDBItems2BDelete(QStringList);
private:
ApplicationInfoPrivate *d = nullptr;
};
}
#endif // APPLICATIONINFO_H

View File

@ -0,0 +1,170 @@
#include "application-property-helper.h"
#include <QDateTime>
using namespace UkuiSearch;
namespace UkuiSearch {
class ApplicationPropertyHelperPrivate
{
friend class ApplicationPropertyHelper;
private:
ApplicationProperty::Property m_property;
QString m_databaseField;
QMetaType::Type m_valueType;
};
}
ApplicationPropertyHelper::ApplicationPropertyHelper(): d(new ApplicationPropertyHelperPrivate)
{
d->m_property = ApplicationProperty::Invalid;
d->m_valueType = QMetaType::UnknownType;
}
ApplicationPropertyHelper::ApplicationPropertyHelper(ApplicationProperty::Property property): d(new ApplicationPropertyHelperPrivate)
{
d->m_property = property;
switch (property) {
case ApplicationProperty::DesktopFilePath:
d->m_databaseField = "DESKTOP_FILE_PATH";
d->m_valueType = QMetaType::QString;
break;
case ApplicationProperty::ModifiedTime:
d->m_databaseField = "MODIFYED_TIME";
d->m_valueType = QMetaType::QDateTime;
break;
case ApplicationProperty::InsertTime:
d->m_databaseField = "INSERT_TIME";
d->m_valueType = QMetaType::QDateTime;
break;
case ApplicationProperty::LocalName:
d->m_databaseField = "LOCAL_NAME";
d->m_valueType = QMetaType::QString;
break;
case ApplicationProperty::NameEn:
d->m_databaseField = "NAME_EN";
d->m_valueType = QMetaType::QString;
break;
case ApplicationProperty::NameZh:
d->m_databaseField = "NAME_EN";
d->m_valueType = QMetaType::QString;
break;
case ApplicationProperty::PinyinName:
d->m_databaseField = "PINYIN_NAME";
d->m_valueType = QMetaType::QString;
break;
case ApplicationProperty::FirstLetterOfPinyin:
d->m_databaseField = "FIRST_LETTER_OF_PINYIN";
d->m_valueType = QMetaType::QString;
break;
case ApplicationProperty::FirstLetterAll:
d->m_databaseField = "FIRST_LETTER_ALL";
d->m_valueType = QMetaType::QString;
break;
case ApplicationProperty::Icon:
d->m_databaseField = "ICON";
d->m_valueType = QMetaType::QString;
break;
case ApplicationProperty::Type:
d->m_databaseField = "TYPE";
d->m_valueType = QMetaType::QString;
break;
case ApplicationProperty::Category:
d->m_databaseField = "CATEGORY";
d->m_valueType = QMetaType::QString;
break;
case ApplicationProperty::Exec:
d->m_databaseField = "EXEC";
d->m_valueType = QMetaType::QString;
break;
case ApplicationProperty::Comment:
d->m_databaseField = "CATEGORY";
d->m_valueType = QMetaType::QString;
break;
case ApplicationProperty::Md5:
d->m_databaseField = "MD5";
d->m_valueType = QMetaType::QString;
break;
case ApplicationProperty::LaunchTimes:
d->m_databaseField = "LAUNCH_TIMES";
d->m_valueType = QMetaType::Int;
break;
case ApplicationProperty::Favorites:
d->m_databaseField = "FAVORITES";
d->m_valueType = QMetaType::Int;
break;
case ApplicationProperty::Launched:
d->m_databaseField = "LAUNCHED";
d->m_valueType = QMetaType::Int;
break;
case ApplicationProperty::Top:
d->m_databaseField = "TOP";
d->m_valueType = QMetaType::Int;
break;
case ApplicationProperty::Lock:
d->m_databaseField = "LOCK";
d->m_valueType = QMetaType::Int;
break;
case ApplicationProperty::DontDisplay:
d->m_databaseField = "DONT_DISPLAY";
d->m_valueType = QMetaType::Int;
break;
case ApplicationProperty::AutoStart:
d->m_databaseField = "AUTO_START";
d->m_valueType = QMetaType::Int;
break;
default:
break;
}
}
ApplicationPropertyHelper::ApplicationPropertyHelper(const ApplicationPropertyHelper &other): d(new ApplicationPropertyHelperPrivate(*other.d))
{
}
ApplicationPropertyHelper::~ApplicationPropertyHelper()
{
if(d) {
delete d;
d = nullptr;
}
}
ApplicationPropertyHelper &ApplicationPropertyHelper::operator =(const ApplicationPropertyHelper &rhs)
{
*d = *rhs.d;
return *this;
}
bool ApplicationPropertyHelper::operator ==(const ApplicationPropertyHelper &rhs) const
{
return d->m_databaseField == rhs.d->m_databaseField && d->m_valueType == rhs.d->m_valueType;
}
ApplicationProperty::Property ApplicationPropertyHelper::info()
{
return d->m_property;
}
QString ApplicationPropertyHelper::dataBaseField()
{
return d->m_databaseField;
}
QMetaType::Type ApplicationPropertyHelper::valueType()
{
return d->m_valueType;
}
QString ApplicationPropertyHelper::toDataBaseString(QVariant &value)
{
switch (d->m_valueType) {
case QMetaType::Type::UnknownType:
return QString();
case QMetaType::Type::QString:
return value.toString();
case QMetaType::Type::QDateTime:
return value.toDateTime().toString("yyyy-MM-dd hh:mm:ss");
default:
return {};
break;
}
}

View File

@ -0,0 +1,49 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#ifndef APPLICATIONINFOHELPER_H
#define APPLICATIONINFOHELPER_H
#include "application-property.h"
#include <QMetaType>
#include <QVariant>
namespace UkuiSearch {
class ApplicationPropertyHelperPrivate;
class ApplicationPropertyHelper
{
public:
ApplicationPropertyHelper();
ApplicationPropertyHelper(ApplicationProperty::Property property);
ApplicationPropertyHelper(const ApplicationPropertyHelper &other);
~ApplicationPropertyHelper();
ApplicationPropertyHelper& operator=(const ApplicationPropertyHelper &rhs);
bool operator==(const ApplicationPropertyHelper &rhs) const;
ApplicationProperty::Property info();
QString dataBaseField();
QMetaType::Type valueType();
QString toDataBaseString(QVariant &value);
private:
ApplicationPropertyHelperPrivate *d = nullptr;
};
}
#endif // APPLICATIONINFOHELPER_H

View File

@ -0,0 +1,65 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#ifndef APPLICATIONPROPERTY_H
#define APPLICATIONPROPERTY_H
#include <QObject>
#include <QMap>
#include <QVector>
#include <QVariant>
namespace UkuiSearch {
namespace ApplicationProperty {
/**
* @brief
*/
enum Property {
Invalid = 0,
DesktopFilePath, //desktop文件路径
ModifiedTime, //数据修改时间
InsertTime, //数据插入时间
LocalName, //应用名(本地化)
NameEn, //应用英文名
NameZh, //应用中文名
PinyinName, //名称拼音
FirstLetterOfPinyin, //拼音首字母
FirstLetterAll, //名称首字母
Icon, //应用图标
Type, //种类Application等
Category, //分类AudioVideo等
Exec, //执行命令
Comment, //简介
Md5, //desktop文件的md5
LaunchTimes, //启动次数
Favorites, //收藏顺序0 未收藏)
Launched, //是否从开始菜单启动过
Top, //置顶顺序0 未置顶)
Lock, //是否锁定(不允许显示或打开)
DontDisplay, //是否不需要显示设置了Nodisplay等字段
AutoStart //是否自启动(位于自启动目录/etc/xdg/autostart下
};
} //namespace ApplicationProperty
typedef QVector<ApplicationProperty::Property> ApplicationProperties;
typedef QMap<ApplicationProperty::Property, QVariant> ApplicationPropertyMap;
typedef QMap<QString, ApplicationPropertyMap> ApplicationInfoMap; // desktopFile->ApplicationPropertyMap
}
Q_DECLARE_METATYPE(UkuiSearch::ApplicationProperty::Property)
Q_DECLARE_METATYPE(UkuiSearch::ApplicationInfoMap)
#endif // APPLICATIONPROPERTY_H

View File

@ -48,8 +48,6 @@ private:
void appNameMatch(QString keyWord, size_t uniqueSymbol, DataQueue<SearchPluginIface::ResultInfo> *searchResult);
void parseSoftWareCenterReturn(QList<QMap<QString, QString>> list, size_t uniqueSymbol, DataQueue<SearchPluginIface::ResultInfo> *searchResult);
//void creatResultInfo(SearchPluginIface::ResultInfo &ri, QMapIterator<UkuiSearch::NameString, QStringList> &iter, bool isInstalled = true);
AppInfoTable *m_appInfoTable = nullptr;
QString m_sourceText;
size_t m_uniqueSymbol;
DataQueue<SearchPluginIface::ResultInfo> *m_search_result = nullptr;

View File

@ -1,7 +1,28 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#include "app-search-plugin.h"
#include <gio/gdesktopappinfo.h>
#include <QWidget>
#include <QLabel>
#include <qt5xdg/XdgIcon>
#include <QDeadlineTimer>
#include "file-utils.h"
using namespace UkuiSearch;
@ -16,29 +37,21 @@ AppSearchPlugin::AppSearchPlugin(QObject *parent) : QThread(parent), m_appSearch
// m_pool.setMaxThreadCount(1);
// m_pool.setExpiryTimeout(1000);
initDetailPage();
m_timer = new QTimer;
m_timer->setInterval(3000);
m_timer->moveToThread(this);
m_appSearchResults = m_appSearchTask->init();
m_appSearchTask->initSearchPlugin(SearchType::Application);
m_appSearchTask->initSearchPlugin(SearchProperty::SearchType::Application);
m_appSearchTask->setSearchOnlineApps(true);
m_appSearchTask->setResultDataType(SearchType::Application, UkuiSearch::ApplicationDesktopPath |
UkuiSearch::ApplicationLocalName |
UkuiSearch::ApplicationIconName |
UkuiSearch::ApplicationDescription |
UkuiSearch::IsOnlineApplication);
m_appSearchTask->setResultProperties(SearchProperty::SearchType::Application,
SearchResultProperties{SearchProperty::SearchResultProperty::ApplicationDesktopPath,
SearchProperty::SearchResultProperty::ApplicationLocalName,
SearchProperty::SearchResultProperty::ApplicationIconName,
SearchProperty::SearchResultProperty::ApplicationDescription,
SearchProperty::SearchResultProperty::IsOnlineApplication,
SearchProperty::SearchResultProperty::ApplicationPkgName});
}
AppSearchPlugin::~AppSearchPlugin()
{
this->wait();
if (m_timer) {
delete m_timer;
m_timer = nullptr;
}
}
const QString AppSearchPlugin::name()
@ -64,7 +77,7 @@ void AppSearchPlugin::KeywordSearch(QString keyword, DataQueue<SearchPluginIface
m_searchResult = searchResult;
m_appSearchTask->clearKeyWords();
m_appSearchTask->addKeyword(keyword);
m_appSearchTask->startSearch(SearchType::Application);
m_appSearchTask->startSearch(SearchProperty::SearchType::Application);
// AppSearch *appsearch = new AppSearch(searchResult, m_appSearchResults, m_appSearchTask, keyword, uniqueSymbol);
// m_pool.start(appsearch);
@ -160,35 +173,34 @@ QWidget *AppSearchPlugin::detailPage(const ResultInfo &ri)
void AppSearchPlugin::run()
{
QDeadlineTimer deadline(3000);
while(!isInterruptionRequested()) {
ResultItem oneResult = m_appSearchResults->tryDequeue();
if(oneResult.getSearchId() == 0 && oneResult.getItemKey().isEmpty() && oneResult.getExtral().isEmpty()) {
if(!m_timer->isActive()) {
m_timer->start();
}
SearchResultPropertyMap data = oneResult.getAllValue();
if(oneResult.getSearchId() == 0 && oneResult.getItemKey().isEmpty() && data.isEmpty()) {
if(deadline.remainingTime()) {
msleep(100);
} else {
m_timer->stop();
SearchPluginIface::ResultInfo ri;
ri.actionKey = oneResult.getExtral().at(0).toString();
ri.name = oneResult.getExtral().at(1).toString();
QIcon icon = oneResult.getExtral().at(2).value<QIcon>();
if(icon.isNull()) {
ri.icon = QIcon(":/res/icons/unknown.svg");
} else {
ri.icon = icon;
this->requestInterruption();
}
} else {
deadline.setRemainingTime(3000);
SearchPluginIface::ResultInfo ri;
ri.name = data.value(SearchProperty::SearchResultProperty::ApplicationLocalName).toString();
ri.icon = XdgIcon::fromTheme(data.value(SearchProperty::SearchResultProperty::ApplicationIconName).toString(), QIcon(":/res/icons/unknown.svg"));
SearchPluginIface::DescriptionInfo description;
description.key = QString(tr("Application Description:"));
description.value = oneResult.getExtral().at(3).toString();
description.value = data.value(SearchProperty::SearchResultProperty::ApplicationDescription).toString();
ri.description.append(description);
ri.type = oneResult.getExtral().at(4).toInt();
m_searchResult->enqueue(ri);
ri.type = data.value(SearchProperty::SearchResultProperty::IsOnlineApplication).toInt();
if (ri.type == 1) {
ri.actionKey = data.value(SearchProperty::SearchResultProperty::ApplicationPkgName).toString();
} else {
ri.actionKey = data.value(SearchProperty::SearchResultProperty::ApplicationDesktopPath).toString();
}
if(m_timer->isActive() && m_timer->remainingTime() < 0.01 && m_appSearchResults->isEmpty()) {
this->requestInterruption();
m_searchResult->enqueue(ri);
}
}
}
@ -327,8 +339,7 @@ bool AppSearchPlugin::addDesktopShortcut(const QString& path) {
QString newName = QString(dirpath + "/" + desktopfn);
bool ret = file.copy(QString(dirpath + "/" + desktopfn));
if(ret) {
QProcess process;
process.startDetached(QString("chmod a+x %1").arg(newName));
QProcess::startDetached("chmod", {"a+x", newName});
return true;
}
return false;
@ -369,8 +380,7 @@ bool AppSearchPlugin::installAppAction(const QString & name) {
}
appLaunchInterface = nullptr;
if (!res) {
QProcess process;
res = process.startDetached(QString("kylin-software-center -find %1").arg(name));
res = QProcess::startDetached("kylin-software-center", {"-find", name});
}
}
if(interface) {

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#ifndef APPSEARCHPLUGIN_H
#define APPSEARCHPLUGIN_H
@ -40,7 +59,7 @@ public:
// bool isPreviewEnable(QString key, int type);
// QWidget *previewPage(QString key, int type, QWidget *parent);
QWidget *detailPage(const ResultInfo &ri);
void run() override;
void run();
private:
void initDetailPage();
bool launch(const QString &path);
@ -50,8 +69,6 @@ private:
bool m_enable = true;
QList<SearchPluginIface::Actioninfo> m_actionInfo_installed;
QList<SearchPluginIface::Actioninfo> m_actionInfo_not_installed;
// QThreadPool m_pool;
QTimer *m_timer;
UkuiSearchTask *m_appSearchTask = nullptr;
DataQueue<ResultItem>* m_appSearchResults = nullptr;

View File

@ -20,7 +20,10 @@ static const int OCR_MIN_SIZE = 200;
static const QByteArray UKUI_SEARCH_SCHEMAS = QByteArrayLiteral("org.ukui.search.settings");
static const QString SEARCH_METHOD_KEY = QStringLiteral("fileIndexEnable");
static const QString INDEX_DATABASE_VERSION = QStringLiteral("1.0.0");
static const QString CONTENT_DATABASE_VERSION = QStringLiteral("1.0.0");
/**
* changelog 1.1.0 value
*/
static const QString CONTENT_DATABASE_VERSION = QStringLiteral("1.1.0");

View File

@ -1 +0,0 @@
#include "app-info-table.h"

View File

@ -1 +0,0 @@
#include "search-controller.h"

View File

@ -1,6 +1,7 @@
#include "action-label.h"
#include "common-defines.h"
#include "action-transmiter.h"
#include "plugin-iface.h"
#include "data-queue.h"
#include "search-plugin-iface.h"
#include "search-task-plugin-iface.h"
#include "separation-line.h"

View File

@ -1,3 +1,21 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "dir-watcher.h"
#include <QDebug>
@ -81,6 +99,16 @@ QStringList DirWatcher::blackListOfDir(const QString &dirPath)
return reply.value();
}
QStringList DirWatcher::getBlockDirsOfUser()
{
QDBusReply<QStringList> reply = m_dbusInterface->call("blockDirsForUser");
if (!reply.isValid()) {
qCritical() << "blockDirsForUser call filed!";
return QStringList();
}
return reply.value();
}
QStringList DirWatcher::currentSearchableDir()
{
QDBusReply<QStringList> reply = m_dbusInterface->call("currentSearchableDir");
@ -101,9 +129,25 @@ QStringList DirWatcher::searchableDirForSearchApplication()
return reply.value();
}
void DirWatcher::appendSearchDir(const QString &path)
{
QDBusReply<int> reply = m_dbusInterface->call("appendSearchDir", path);
if (!reply.isValid()) {
qCritical() << "appendSearchDir call filed!";
}
}
void DirWatcher::removeSearchDir(const QString &path)
{
QDBusReply<void> reply = m_dbusInterface->call("removeSearchDir", path);
if (!reply.isValid()) {
qCritical() << "removeSearchDir call filed!";
}
}
void DirWatcher::appendIndexableListItem(const QString &path)
{
QDBusReply<void> reply = m_dbusInterface->call("appendIndexableListItem", path);
QDBusReply<int> reply = m_dbusInterface->call("appendIndexableListItem", path);
if (!reply.isValid()) {
qCritical() << "appendIndexableListItem call filed!";
}

View File

@ -1,3 +1,21 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef MOUNTDISKLISTENER_H
#define MOUNTDISKLISTENER_H
@ -21,6 +39,10 @@ public Q_SLOTS:
QStringList searchableDirForSearchApplication();
QStringList blackListOfDir(const QString &dirPath);
QStringList getBlockDirsOfUser();
void appendSearchDir(const QString &path);
void removeSearchDir(const QString &path);
void appendIndexableListItem(const QString &path);
void removeIndexableListItem(const QString &path);
void sendAppendSignal(const QString &path, const QStringList &blockList);

View File

@ -28,14 +28,180 @@
#include <QDomDocument>
#include <QDBusInterface>
#include <QDBusReply>
#include <QDesktopServices>
#include <QMimeDatabase>
#include <QCryptographicHash>
#include <QFileInfo>
#include <QFile>
#include <QApplication>
#include <QDir>
#include <QDebug>
#include <QUrl>
#include <QDomElement>
#include <QClipboard>
#include <QQueue>
#include <QFontMetrics>
#include <quazip5/quazipfile.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <quazip5/quazip.h>
#include <uchardet/uchardet.h>
#include <poppler/qt5/poppler-qt5.h>
#include "gobject-template.h"
#include "hanzi-to-pinyin.h"
#include "common.h"
using namespace UkuiSearch;
size_t FileUtils::maxIndexCount = 0;
unsigned short FileUtils::indexStatus = 0;
QMap<QString, QStringList> FileUtils::map_chinese2pinyin = QMap<QString, QStringList>();
#define MAX_CONTENT_LENGTH 20480000
static QMutex iconMutex;
/**
* @brief elem的子节点
* @param elem
* @param names
* @param nodes
*/
void findNodes(const QDomElement &elem, QQueue<QString> &names, QList<QDomElement> &nodes)
{
QString targetName = names.dequeue();
QDomNode node = elem.firstChild();
while (!node.isNull()) {
QDomElement e = node.toElement();
if (!e.isNull() && e.tagName() == targetName) {
if (names.empty()) {
nodes.append(e);
} else {
findNodes(e, names, nodes);
break;
}
}
node = node.nextSibling();
}
}
void findNodesByAttr(const QDomElement &elem, QQueue <QString> &names, QList <QDomElement> &nodes, const QString &attr, const QStringList &values)
{
findNodes(elem, names, nodes);
QList<QDomElement>::iterator it = nodes.begin();
while (it != nodes.end()) {
if ((*it).hasAttribute(attr) && values.contains((*it).attribute(attr))) {
it++;
} else {
it = nodes.erase(it);
}
}
}
bool findNodeText(const QDomElement &elem, QQueue<QString> &names, QString &content)
{
QList<QDomElement> nodes;
findNodes(elem, names, nodes);
for (const auto &node : nodes) {
content.append(node.text());
if (content.length() >= MAX_CONTENT_LENGTH / 3) {
return true;
}
}
return false;
}
void findNodeAttr(const QDomElement &elem, QQueue<QString> &names, const QString &attr, QStringList &attrs)
{
QList<QDomElement> nodes;
findNodes(elem, names, nodes);
for (const auto &node : nodes) {
if (node.hasAttribute(attr)) {
attrs.append(node.attribute(attr));
}
}
}
void processUOFPPT(const QDomDocument &doc, QString &content)
{
QDomElement rootElem = doc.documentElement();
QList<QDomElement> nodes;
QQueue<QString> names; //每个节点的名称
names << "uof:演示文稿" << "演:主体" << "演:幻灯片集" << "演:幻灯片";
findNodes(rootElem, names, nodes);
if (nodes.empty()) {
//TODO 在uof-ppt不存在锚点节点时直接查找文本节点
return;
}
QStringList objs;
//每一个 演:幻灯片 -> 锚点
for (const auto &node : nodes) {
names.clear();
names << "uof:锚点";
findNodeAttr(node, names, "uof:图形引用", objs);
}
nodes.clear();
names.clear();
names << "uof:对象集" << "图:图形";
findNodesByAttr(rootElem, names, nodes, "图:标识符", objs);
if (nodes.empty()) {
return;
}
QList<QDomElement> paraNodes; //全部段落节点
for (const auto &node : nodes) {
names.clear();
names << "图:文本内容" << "字:段落";
findNodes(node, names, paraNodes);
}
nodes.clear();
for (const auto &node : paraNodes) {
names.clear();
names << "字:句";
findNodes(node, names, nodes); //全部段落下的全部句节点
}
for (const auto &node : nodes) {
names.clear();
names << "字:文本串";
if (findNodeText(node, names, content)) {
break;
}
}
}
bool loadZipFileToDoc(QuaZip &zipFile, QDomDocument &doc, const QString &fileName)
{
if (!zipFile.isOpen() && !zipFile.open(QuaZip::mdUnzip)) {
return false;
}
if (!zipFile.setCurrentFile(fileName)) {
return false;
}
QuaZipFile file(&zipFile);
if (!file.open(QIODevice::ReadOnly)) {
return false;
}
doc.clear();
if (!doc.setContent(&file)) {
file.close();
return false;
}
file.close();
return true;
}
FileUtils::FileUtils() {
}
@ -51,6 +217,7 @@ std::string FileUtils::makeDocUterm(QString path) {
* @return
*/
QIcon FileUtils::getFileIcon(const QString &uri, bool checkValid) {
Q_UNUSED(checkValid)
QMutexLocker locker(&iconMutex);
auto file = wrapGFile(g_file_new_for_uri(uri.toUtf8().constData()));
auto info = wrapGFileInfo(g_file_query_info(file.get()->get(),
@ -185,10 +352,9 @@ QString FileUtils::getSettingName(const QString &setting) {
bool FileUtils::isOrUnder(QString pathA, QString pathB)
{
if(pathA[0] != "/")
pathA.prepend("/");
if(pathB[0] != "/")
pathB.prepend("/");
if (pathB == "/") {
return true;
}
if(pathA.length() < pathB.length())
return false;
@ -199,24 +365,6 @@ bool FileUtils::isOrUnder(QString pathA, QString pathB)
return false;
}
void FileUtils::loadHanziTable(const QString &fileName) {
QFile file(fileName);
if(!file.open(QFile::ReadOnly | QFile::Text)) {
qDebug("File: '%s' open failed!", file.fileName().toStdString().c_str());
return;
}
/* 读取汉字对照表文件并转换为QMap存储 */
while(!file.atEnd()) {
QString content = QString::fromUtf8(file.readLine());
FileUtils::map_chinese2pinyin[content.split(" ").last().trimmed()] = content.split(" ").first().split(",");
}
file.close();
return;
}
QMimeType FileUtils::getMimetype(const QString &path) {
QMimeDatabase mdb;
QMimeType type = mdb.mimeTypeForFile(path, QMimeDatabase::MatchContent);
@ -224,261 +372,8 @@ QMimeType FileUtils::getMimetype(const QString &path) {
return type;
}
//aborted
QString FileUtils::find(const QString &hanzi) {
// static QMap<QString, QStringList> map = loadHanziTable("://index/pinyinWithoutTone.txt");
// static QMap<QString, QStringList> map;
QString output;
QStringList stringList = hanzi.split("");
/* 遍历查找汉字-拼音对照表的内容并将汉字替换为拼音 */
for(const QString &str : stringList) {
if(FileUtils::map_chinese2pinyin.contains(str))
output += FileUtils::map_chinese2pinyin[str].first();
else
output += str;
}
return output;
}
//DFS多音字太多直接GG
void stitchMultiToneWordsDFS(const QString &hanzi, const QString &resultAllPinYin, const QString &resultFirst, QStringList &resultList) {
if(hanzi.size() == 0) {
resultList.append(resultAllPinYin);
resultList.append(resultFirst);
return;
}
if(FileUtils::map_chinese2pinyin.contains(hanzi.at(0))) {
for(auto i : FileUtils::map_chinese2pinyin[hanzi.at(0)]) {
stitchMultiToneWordsDFS(hanzi.right(hanzi.size() - 1), resultAllPinYin + i, resultFirst + i.at(0), resultList);
}
} else {
stitchMultiToneWordsDFS(hanzi.right(hanzi.size() - 1), resultAllPinYin + hanzi.at(0), resultFirst + hanzi.at(0), resultList);
}
}
//BFS+Stack多音字太多会爆栈
void stitchMultiToneWordsBFSStack(const QString &hanzi, QStringList &resultList) {
QString tempHanzi, resultAllPinYin, resultFirst;
QQueue<QString> tempQueue;
tempHanzi = hanzi;
int tempQueueSize = 0;
if(FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))) {
for(auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]) {
tempQueue.enqueue(i);
}
} else {
tempQueue.enqueue(tempHanzi.at(0));
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
while(tempHanzi.size() != 0) {
tempQueueSize = tempQueue.size();
if(FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))) {
for(int j = 0; j < tempQueueSize; ++j) {
for(auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]) {
tempQueue.enqueue(tempQueue.head() + i);
}
tempQueue.dequeue();
}
} else {
for(int j = 0; j < tempQueueSize; ++j) {
tempQueue.enqueue(tempQueue.head() + tempHanzi.at(0));
tempQueue.dequeue();
}
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
}
while(!tempQueue.empty()) {
resultList.append(tempQueue.dequeue());
}
}
//BFS+Heap多音字太多会耗尽内存
void stitchMultiToneWordsBFSHeap(const QString &hanzi, QStringList &resultList) {
QString tempHanzi, resultAllPinYin, resultFirst;
QQueue<QString>* tempQueue = new QQueue<QString>;
tempHanzi = hanzi;
int tempQueueSize = 0;
if(FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))) {
for(auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]) {
tempQueue->enqueue(i);
}
} else {
tempQueue->enqueue(tempHanzi.at(0));
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
while(tempHanzi.size() != 0) {
tempQueueSize = tempQueue->size();
if(FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))) {
for(int j = 0; j < tempQueueSize; ++j) {
for(auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]) {
tempQueue->enqueue(tempQueue->head() + i);
}
tempQueue->dequeue();
}
} else {
for(int j = 0; j < tempQueueSize; ++j) {
tempQueue->enqueue(tempQueue->head() + tempHanzi.at(0));
tempQueue->dequeue();
}
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
}
while(!tempQueue->empty()) {
resultList.append(tempQueue->dequeue());
}
delete tempQueue;
tempQueue = nullptr;
}
//BFS+Heap+超过3个多音字只建一个索引比较折中的方案
void stitchMultiToneWordsBFSHeapLess3(const QString &hanzi, QStringList &resultList) {
QString tempHanzi, resultAllPinYin, resultFirst;
QQueue<QString>* tempQueue = new QQueue<QString>;
QQueue<QString>* tempQueueFirst = new QQueue<QString>;
tempHanzi = hanzi;
int tempQueueSize = 0;
int multiToneWordNum = 0;
for(auto i : hanzi) {
if(FileUtils::map_chinese2pinyin.contains(i)) {
if(FileUtils::map_chinese2pinyin[i].size() > 1) {
++multiToneWordNum;
}
}
}
if(multiToneWordNum > 3) {
QString oneResult, oneResultFirst;
for(auto i : hanzi) {
if(FileUtils::map_chinese2pinyin.contains(i)) {
oneResult += FileUtils::map_chinese2pinyin[i].first();
oneResultFirst += FileUtils::map_chinese2pinyin[i].first().at(0);
} else {
oneResult += i;
oneResultFirst += i;
}
}
resultList.append(oneResult);
resultList.append(oneResultFirst);
return;
}
if(FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))) {
for(auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]) {
tempQueue->enqueue(i);
tempQueueFirst->enqueue(i.at(0));
}
} else {
tempQueue->enqueue(tempHanzi.at(0));
tempQueueFirst->enqueue(tempHanzi.at(0));
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
while(tempHanzi.size() != 0) {
tempQueueSize = tempQueue->size();
if(FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))) {
for(int j = 0; j < tempQueueSize; ++j) {
for(auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]) {
tempQueue->enqueue(tempQueue->head() + i);
tempQueueFirst->enqueue(tempQueueFirst->head() + i.at(0));
}
tempQueue->dequeue();
tempQueueFirst->dequeue();
}
} else {
for(int j = 0; j < tempQueueSize; ++j) {
tempQueue->enqueue(tempQueue->head() + tempHanzi.at(0));
tempQueueFirst->enqueue(tempQueueFirst->head() + tempHanzi.at(0));
tempQueue->dequeue();
tempQueueFirst->dequeue();
}
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
}
while(!tempQueue->empty()) {
resultList.append(tempQueue->dequeue());
resultList.append(tempQueueFirst->dequeue());
}
delete tempQueue;
delete tempQueueFirst;
tempQueue = nullptr;
tempQueueFirst = nullptr;
return;
}
//BFS+Stack+超过3个多音字只建一个索引比较折中的方案
void stitchMultiToneWordsBFSStackLess3(const QString &hanzi, QStringList &resultList) {
QString tempHanzi;
QQueue<QString> tempQueue;
QQueue<QString> tempQueueFirst;
tempHanzi = hanzi;
int tempQueueSize = 0;
int multiToneWordNum = 0;
for (auto i:hanzi) {
if (HanZiToPinYin::getInstance()->isMultiTone(QString(i).toStdString()))
++multiToneWordNum;
}
if(multiToneWordNum > 3) {
QString oneResult, oneResultFirst;
for(auto i : hanzi) {
QStringList results;
HanZiToPinYin::getInstance()->getResults(QString(i).toStdString(), results);
if(results.size()) {
oneResult += results.first();
oneResultFirst += results.first().at(0);
} else {
oneResult += i;
oneResultFirst += i;
}
}
resultList.append(oneResult);
resultList.append(oneResultFirst);
return;
}
QStringList results;
HanZiToPinYin::getInstance()->getResults(QString(tempHanzi.at(0)).toStdString(), results);
if(results.size()) {
for(auto i : results) {
tempQueue.enqueue(i);
tempQueueFirst.enqueue(i.at(0));
}
} else {
tempQueue.enqueue(tempHanzi.at(0));
tempQueueFirst.enqueue(tempHanzi.at(0));
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
while(tempHanzi.size() != 0) {
HanZiToPinYin::getInstance()->getResults(QString(tempHanzi.at(0)).toStdString(), results);
tempQueueSize = tempQueue.size();
if(results.size()) {
for(int j = 0; j < tempQueueSize; ++j) {
for(auto i : results) {
tempQueue.enqueue(tempQueue.head() + i);
tempQueueFirst.enqueue(tempQueueFirst.head() + i.at(0));
}
tempQueue.dequeue();
tempQueueFirst.dequeue();
}
} else {
for(int j = 0; j < tempQueueSize; ++j) {
tempQueue.enqueue(tempQueue.head() + tempHanzi.at(0));
tempQueueFirst.enqueue(tempQueueFirst.head() + tempHanzi.at(0));
tempQueue.dequeue();
tempQueueFirst.dequeue();
}
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
}
while(!tempQueue.empty()) {
resultList.append(tempQueue.dequeue());
resultList.append(tempQueueFirst.dequeue());
}
return;
}
QStringList FileUtils::findMultiToneWords(const QString &hanzi) {
QStringList output, results;
//stitchMultiToneWordsBFSStackLess3(hanzi, output);
HanZiToPinYin::getInstance()->getResults(hanzi.toStdString(), results);
QString oneResult(results.join(""));
QString firstLetter;
@ -887,21 +782,16 @@ QString FileUtils::escapeHtml(const QString &str)
return temp;
}
QString FileUtils::chineseSubString(const std::string &myStr, int start, int length)
QString FileUtils::chineseSubString(const std::string &myStr, uint start, uint length)
{
std::string afterSub = "";
//越界保护
if(start < 0 || length < 0){
return " ";
}
QString sub = QString::fromStdString(myStr);
QFont ft(QApplication::font().family(),QApplication::font().pointSize());
QFontMetrics fm (ft);
if (length >= myStr.length()) {
afterSub = myStr.substr(start,length); //截取;
if (fm.width(QString::fromStdString(afterSub)) >= 2*LABEL_MAX_WIDTH) {
if (fm.horizontalAdvance(QString::fromStdString(afterSub)) >= 2*LABEL_MAX_WIDTH) {
sub = fm.elidedText(sub, Qt::ElideRight, 2*LABEL_MAX_WIDTH); //超过两行则省略
} else {
sub = fm.elidedText(sub, Qt::ElideLeft, 2*LABEL_MAX_WIDTH); //超过两行则省略
@ -919,11 +809,11 @@ QString FileUtils::chineseSubString(const std::string &myStr, int start, int len
}
sub = fm.elidedText(sub, Qt::ElideRight, 2*LABEL_MAX_WIDTH); //超过两行则省略
} else {
int newStart = myStr.length()-length; //更新截取位置
uint newStart = myStr.length()-length; //更新截取位置
afterSub = myStr.substr(newStart, length);
sub=QString::fromStdString(afterSub);
if (fm.width(QString::fromStdString(myStr.substr(newStart, start))) >= 2*LABEL_MAX_WIDTH) {
if (fm.horizontalAdvance(QString::fromStdString(myStr.substr(newStart, start))) >= 2*LABEL_MAX_WIDTH) {
sub = fm.elidedText(sub, Qt::ElideLeft, 2*LABEL_MAX_WIDTH);
} else {
if (newStart + 3 < start) {
@ -956,7 +846,7 @@ bool FileUtils::isOpenXMLFileEncrypted(const QString &path)
return true;
}
//比较前四位是否为对应值来判断OpenXML类型文件是否加密
if (encrypt[0] == 0x50 && encrypt[1] == 0x4b && encrypt[2] == 0x03 && encrypt[3] == 0x04) {
if ((encrypt[0] & 0x50) && (encrypt[1] & 0x4b) && (encrypt[2] & 0x03) && (encrypt[3] & 0x04)) {
return false;
} else {
qDebug() << "Encrypt!" << path;
@ -1070,7 +960,7 @@ QString FileUtils::wrapData(QLabel *p_label, const QString &text)
QString wrapText = text;
QFontMetrics fontMetrics = p_label->fontMetrics();
int textSize = fontMetrics.width(wrapText);
int textSize = fontMetrics.horizontalAdvance(wrapText);
if(textSize > LABEL_MAX_WIDTH){
int lastIndex = 0;
@ -1078,11 +968,11 @@ QString FileUtils::wrapData(QLabel *p_label, const QString &text)
for(int i = lastIndex; i < wrapText.length(); i++) {
if(fontMetrics.width(wrapText.mid(lastIndex, i - lastIndex)) == LABEL_MAX_WIDTH) {
if(fontMetrics.horizontalAdvance(wrapText.mid(lastIndex, i - lastIndex)) == LABEL_MAX_WIDTH) {
lastIndex = i;
wrapText.insert(i, '\n');
count++;
} else if(fontMetrics.width(wrapText.mid(lastIndex, i - lastIndex)) > LABEL_MAX_WIDTH) {
} else if(fontMetrics.horizontalAdvance(wrapText.mid(lastIndex, i - lastIndex)) > LABEL_MAX_WIDTH) {
lastIndex = i;
wrapText.insert(i - 1, '\n');
count++;
@ -1163,124 +1053,9 @@ void FileUtils::getUOFTextContent(const QString &path, QString &textContent)
file.close();
}
void FileUtils::processUOFPPT(const QDomDocument &doc, QString &content)
{
QDomElement rootElem = doc.documentElement();
QList<QDomElement> nodes;
QQueue<QString> names; //每个节点的名称
names << "uof:演示文稿" << "演:主体" << "演:幻灯片集" << "演:幻灯片";
findNodes(rootElem, names, nodes);
if (nodes.empty()) {
//TODO 在uof-ppt不存在锚点节点时直接查找文本节点
return;
}
QStringList objs;
//每一个 演:幻灯片 -> 锚点
for (const auto &node : nodes) {
names.clear();
names << "uof:锚点";
findNodeAttr(node, names, "uof:图形引用", objs);
}
nodes.clear();
names.clear();
names << "uof:对象集" << "图:图形";
findNodesByAttr(rootElem, names, nodes, "图:标识符", objs);
if (nodes.empty()) {
return;
}
QList<QDomElement> paraNodes; //全部段落节点
for (const auto &node : nodes) {
names.clear();
names << "图:文本内容" << "字:段落";
findNodes(node, names, paraNodes);
}
nodes.clear();
for (const auto &node : paraNodes) {
names.clear();
names << "字:句";
findNodes(node, names, nodes); //全部段落下的全部句节点
}
for (const auto &node : nodes) {
names.clear();
names << "字:文本串";
if (findNodeText(node, names, content)) {
break;
}
}
}
/**
* @brief elem的子节点
* @param elem
* @param names
* @param nodes
*/
void FileUtils::findNodes(const QDomElement &elem, QQueue<QString> &names, QList<QDomElement> &nodes)
{
QString targetName = names.dequeue();
QDomNode node = elem.firstChild();
while (!node.isNull()) {
QDomElement e = node.toElement();
if (!e.isNull() && e.tagName() == targetName) {
if (names.empty()) {
nodes.append(e);
} else {
findNodes(e, names, nodes);
break;
}
}
node = node.nextSibling();
}
}
inline void FileUtils::findNodesByAttr(const QDomElement &elem, QQueue <QString> &names, QList <QDomElement> &nodes, const QString &attr, const QStringList &values)
{
findNodes(elem, names, nodes);
QList<QDomElement>::iterator it = nodes.begin();
while (it != nodes.end()) {
if ((*it).hasAttribute(attr) && values.contains((*it).attribute(attr))) {
it++;
} else {
it = nodes.erase(it);
}
}
}
inline bool FileUtils::findNodeText(const QDomElement &elem, QQueue<QString> &names, QString &content)
{
QList<QDomElement> nodes;
findNodes(elem, names, nodes);
for (const auto &node : nodes) {
content.append(node.text());
if (content.length() >= MAX_CONTENT_LENGTH / 3) {
return true;
}
}
return false;
}
inline void FileUtils::findNodeAttr(const QDomElement &elem, QQueue<QString> &names, const QString &attr, QStringList &attrs)
{
QList<QDomElement> nodes;
findNodes(elem, names, nodes);
for (const auto &node : nodes) {
if (node.hasAttribute(attr)) {
attrs.append(node.attribute(attr));
}
}
}
/**
* uof2.0
@ -1389,30 +1164,6 @@ void FileUtils::getUOF2PPTContent(const QString &path, QString &textContent)
}
}
inline bool FileUtils::loadZipFileToDoc(QuaZip &zipFile, QDomDocument &doc, const QString &fileName)
{
if (!zipFile.isOpen() && !zipFile.open(QuaZip::mdUnzip)) {
return false;
}
if (!zipFile.setCurrentFile(fileName)) {
return false;
}
QuaZipFile file(&zipFile);
if (!file.open(QIODevice::ReadOnly)) {
return false;
}
doc.clear();
if (!doc.setContent(&file)) {
file.close();
return false;
}
file.close();
return true;
}
/**
* OFD文件解析

View File

@ -22,44 +22,12 @@
#ifndef FILEUTILS_H
#define FILEUTILS_H
#include <QString>
#include <QCryptographicHash>
#include <QIcon>
#include <QMap>
#include <QMimeDatabase>
#include <QMimeType>
#include <QDir>
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QUrl>
#include <QMap>
#include <QQueue>
#include <QDesktopServices>
#include <QApplication>
#include <QClipboard>
#include <QFontMetrics>
#include <QLabel>
#include <quazip5/quazipfile.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <quazip5/quazip.h>
#include <uchardet/uchardet.h>
//#include <poppler-qt5.h>
#include <poppler/qt5/poppler-qt5.h>
#include "libsearch_global.h"
#include "common.h"
#include <leptonica/allheaders.h>
//#define INITIAL_STATE 0
//#define CREATING_INDEX 1
//#define FINISH_CREATING_INDEX 2
#define MAX_CONTENT_LENGTH 20480000
namespace UkuiSearch {
class LIBSEARCH_EXPORT FileUtils {
public:
@ -77,12 +45,7 @@ public:
static QString getSettingName(const QString &setting);
//A is or under B
static bool isOrUnder(QString pathA, QString pathB);
//chinese character to pinyin
static QMap<QString, QStringList> map_chinese2pinyin;
static QString find(const QString &hanzi);
static QStringList findMultiToneWords(const QString &hanzi);
static void loadHanziTable(const QString &fileName);
//parse text,docx.....
static QMimeType getMimetype(const QString &path);
@ -99,7 +62,7 @@ public:
static int openFile(QString &path, bool openInDir = false);
static bool copyPath(QString &path);
static QString escapeHtml(const QString &str);
static QString chineseSubString(const std::string &myStr,int start,int length);
static QString chineseSubString(const std::string &myStr, uint start, uint length);
static QIcon iconFromTheme(const QString &name, const QIcon &iconDefault);
static bool isOpenXMLFileEncrypted(const QString &path);
/**
@ -110,16 +73,6 @@ public:
*/
static bool isEncrypedOrUnsupport(const QString &path, const QString &suffix);
static bool isOcrSupportSize(QString path);
static size_t maxIndexCount;
static unsigned short indexStatus;
private:
static void findNodes(const QDomElement &elem, QQueue<QString> &names, QList<QDomElement> &nodes);
static inline void findNodesByAttr(const QDomElement&, QQueue<QString>&, QList<QDomElement>&, const QString &, const QStringList&);
static inline bool findNodeText(const QDomElement &elem, QQueue<QString> &names, QString &content);
static inline void findNodeAttr(const QDomElement &elem, QQueue<QString> &names, const QString &attr, QStringList &attrs);
static void processUOFPPT(const QDomDocument &doc, QString &content);
static inline bool loadZipFileToDoc(QuaZip &zipFile, QDomDocument &doc, const QString &fileName);
private:
FileUtils();

View File

@ -37,7 +37,6 @@ public:
FileSystemWatcherPrivate(FileSystemWatcher *parent);
~FileSystemWatcherPrivate();
void addWatch(const QStringList &pathList);
void addWatchWithBlackList(const QStringList &pathList, const QStringList &blackList);
QStringList removeWatch(const QString &path);
QString removeWatch(int wd);
@ -45,7 +44,6 @@ public:
private:
void init();
void traverse(QStringList pathList);
void addWatch(const QString &path);
FileSystemWatcher::WatchEvents m_watchEvents;
@ -55,6 +53,7 @@ private:
QSocketNotifier* m_notifier = nullptr;
// wd -> url
QHash<int, QString> m_watchPathHash;
QStringList m_watchedRootPaths;
FileSystemWatcher *q = nullptr;
bool m_recursive = true;

View File

@ -21,6 +21,7 @@
#include "file-system-watcher-private.h"
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <QDir>
@ -30,7 +31,6 @@
#include "ukui-search-qdbus.h"
#include "file-utils.h"
using namespace UkuiSearch;
FileSystemWatcherPrivate::FileSystemWatcherPrivate(FileSystemWatcher *parent) : q(parent)
{
qDebug() << "setInotifyMaxUserWatches start";
@ -50,31 +50,6 @@ FileSystemWatcherPrivate::~FileSystemWatcherPrivate()
}
}
void FileSystemWatcherPrivate::traverse(QStringList pathList)
{
QQueue<QString> queue;
for(QString path : pathList) {
addWatch(path);
queue.enqueue(path);
}
if(!m_recursive) {
return;
}
QFileInfoList list;
QDir dir;
dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
while(!queue.empty()) {
dir.setPath(queue.dequeue());
list = dir.entryInfoList();
for(auto i : list) {
if(!(i.isSymLink())) {
queue.enqueue(i.absoluteFilePath());
addWatch(i.absoluteFilePath());
}
}
}
}
void FileSystemWatcherPrivate::addWatch(const QString &path)
{
int wd = inotify_add_watch(m_inotifyFd, path.toStdString().c_str(), m_watchEvents | m_watchFlags);
@ -88,11 +63,6 @@ void FileSystemWatcherPrivate::addWatch(const QString &path)
}
}
void FileSystemWatcherPrivate::addWatch(const QStringList &pathList)
{
traverse(pathList);
}
void FileSystemWatcherPrivate::addWatchWithBlackList(const QStringList &pathList, const QStringList &blackList)
{
QQueue<QString> bfs;
@ -105,10 +75,15 @@ void FileSystemWatcherPrivate::addWatchWithBlackList(const QStringList &pathList
}
}
for(QString path : tmpPathList) {
if(!m_watchedRootPaths.contains(path)) {
addWatch(path);
bfs.enqueue(path);
m_watchedRootPaths.append(path);
}
}
if(!m_recursive) {
return;
}
QFileInfoList list;
QDir dir;
QStringList tmpList = blackList;
@ -219,12 +194,12 @@ FileSystemWatcher::~FileSystemWatcher()
void FileSystemWatcher::addWatch(const QStringList &pathList)
{
d->addWatch(pathList);
d->addWatchWithBlackList(pathList, QStringList());
}
void FileSystemWatcher::addWatch(const QString &path)
{
d->addWatch(QStringList(path));
d->addWatchWithBlackList(QStringList(path), QStringList());
}
void FileSystemWatcher::addWatchWithBlackList(const QStringList &pathList, const QStringList &blackList)
@ -234,6 +209,11 @@ void FileSystemWatcher::addWatchWithBlackList(const QStringList &pathList, const
QStringList FileSystemWatcher::removeWatch(const QString &path)
{
for(QString watchedPath : d->m_watchedRootPaths) {
if(FileUtils::isOrUnder(watchedPath, path)) {
d->m_watchedRootPaths.removeAll(watchedPath);
}
}
return d->removeWatch(path);
}
@ -274,57 +254,92 @@ void FileSystemWatcher::eventProcess(int socket)
return;
}
// qDebug() << "event mask:" << event->mask;
// qDebug() << "event mask:" << event->mask
// << "isDir:" << (event->mask & IN_ISDIR)
// << "event->wd:" << event->wd
// << "event->name" << QString(QByteArray::fromRawData(event->name, qstrnlen(event->name, event->len)))
// << "event->len" << event->len
// << "event->cookie" << event->cookie
// << "path:" << d->m_watchPathHash.value(event->wd);
QString path;
if (event->mask & (EventDeleteSelf | EventMoveSelf)) {
if (event->mask & (EventDeleteSelf | EventMoveSelf | EventUnmount)) {
path = d->m_watchPathHash.value(event->wd);
if(path.isEmpty()) {
i += sizeof(struct inotify_event) + event->len;
continue;
}
} else {
path = d->m_watchPathHash[event->wd] + '/' + event->name;
QByteArray name = QByteArray::fromRawData(event->name, qstrnlen(event->name, event->len));
path = d->m_watchPathHash[event->wd];
if(name.isEmpty() || path.isEmpty()) {
i += sizeof(struct inotify_event) + event->len;
continue;
}
path.append("/").append(name);
}
if(event->mask & EventCreate) {
// qDebug() << path << "--EventCreate";
Q_EMIT created(path, event->mask & IN_ISDIR);
if(event->mask & IN_ISDIR && d->m_recursive) {
if(!QFileInfo(path).isSymLink()){
addWatch(QStringList(path));
if(event->mask & IN_ISDIR) {
for(const QString &createdPath : traverse(path)) {
Q_EMIT created(createdPath, QFileInfo(createdPath).isDir());
}
}
}
if (event->mask & EventDeleteSelf) {
// qDebug() << path << "--EventDeleteSelf";
if(event->mask & IN_ISDIR) {
d->removeWatch(event->wd);
if(d->m_watchedRootPaths.contains(path)) {
// qDebug() << "EventDeleteSelf send" << path;
//All folders under this one should be deleted.
for(const QString &removedPath : d->removeWatch(path)) {
Q_EMIT deleted(removedPath, true);
}
d->m_watchedRootPaths.removeAll(path);
}
Q_EMIT deleted(path, event->mask & IN_ISDIR);
}
if (event->mask & EventDelete) {
// qDebug() << path << "--EventDelete";
// we watch all folders recursively. Thus, folder removing is reported in DeleteSelf.
if (!(event->mask & IN_ISDIR)) {
if (event->mask & IN_ISDIR) {
for(const QString &removedPath : d->removeWatch(path)) {
Q_EMIT deleted(removedPath, true);
}
} else {
Q_EMIT deleted(path, false);
}
}
if (event->mask & EventModify) {
// qDebug() << path << "--EventModify";
if(!(event->mask & IN_ISDIR)) {
Q_EMIT modified(path);
}
}
if (event->mask & EventMoveSelf) {
//Problematic if the parent is not watched, otherwise
// handled by MoveFrom/MoveTo from the parent
// qDebug() << path << "--EventMoveSelf";
if(d->m_watchedRootPaths.contains(path)) {
for(const QString &removedPath : d->removeWatch(path)) {
Q_EMIT moved(removedPath, true);
}
d->m_watchedRootPaths.removeAll(path);
}
}
if (event->mask & EventMoveFrom) {
// qDebug() << path << "--EventMoveFrom";
Q_EMIT moved(path, event->mask & IN_ISDIR);
if (event->mask & IN_ISDIR) {
for(const QString &removedPath : d->removeWatch(path)) {
Q_EMIT moved(removedPath, true);
}
} else {
Q_EMIT moved(path, false);
}
}
if (event->mask & EventMoveTo) {
// qDebug() << path << "--EventMoveTo";
Q_EMIT created(path, event->mask & IN_ISDIR);
if (event->mask & IN_ISDIR && d->m_recursive) {
if(!QFileInfo(path).isSymLink()){
addWatch(QStringList(path));
Q_EMIT moveTo(path, event->mask & IN_ISDIR);
if (event->mask & IN_ISDIR) {
for(const QString &createdPath : traverse(path)) {
Q_EMIT moveTo(createdPath, QFileInfo(createdPath).isDir());
}
}
}
@ -334,14 +349,12 @@ void FileSystemWatcher::eventProcess(int socket)
}
if (event->mask & EventUnmount) {
// qDebug() << path << "--EventUnmount";
if (event->mask & IN_ISDIR) {
d->removeWatch(event->wd);
}
// This is present because a unmount event is sent by inotify after unmounting, by
// which time the watches have already been removed.
if (path != "/") {
Q_EMIT unmounted(path, event->mask & IN_ISDIR);
}
d->m_watchedRootPaths.removeAll(path);
}
if (event->mask & EventAttributeChange) {
// qDebug() << path << "--EventAttributeChange";
@ -370,3 +383,30 @@ void FileSystemWatcher::eventProcess(int socket)
free(buf);
}
QStringList FileSystemWatcher::traverse(QString &path)
{
QStringList paths;
d->addWatch(path);
if(!d->m_recursive || QFileInfo(path).isSymLink()) {
return paths;
}
QQueue<QString> queue;
queue.enqueue(path);
QFileInfoList list;
QDir dir;
dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
dir.setSorting(QDir::DirsFirst);
while(!queue.empty()) {
dir.setPath(queue.dequeue());
list = dir.entryInfoList();
for(auto i : list) {
if(i.isDir() && !(i.isSymLink())) {
queue.enqueue(i.absoluteFilePath());
d->addWatch(i.absoluteFilePath());
}
paths.append(i.absoluteFilePath());
}
}
return paths;
}

View File

@ -153,8 +153,16 @@ Q_SIGNALS:
*/
void unmounted(const QString& path, bool isDir);
/**
* Emitted if a file is moved to one of the watched folders.
* Note:if the new file moved here overwrited a file already existed, there will not be a 'deleted' signal.
*/
void moveTo(const QString& path, bool isDir);
private Q_SLOTS:
void eventProcess(int socket);
QStringList traverse(QString &path);
private:
FileSystemWatcherPrivate* d = nullptr;

View File

@ -0,0 +1,32 @@
#ifndef GLOBALSETTINGSPRIVATE_H
#define GLOBALSETTINGSPRIVATE_H
#include "global-settings.h"
#include <QMutex>
#include <QGSettings>
#include <QMap>
namespace UkuiSearch {
class GlobalSettingsPrivate : public QObject
{
Q_OBJECT
public:
explicit GlobalSettingsPrivate(QObject *parent = nullptr);
const QVariant getValue(const QString&);
Q_SIGNALS:
void valueChanged(const QString& key, QVariant value);
private:
void setValue(const QString& key, const QVariant& value);
QMutex m_mutex;
QGSettings *m_transGsettings = nullptr;
QGSettings *m_themeGsettings = nullptr;
QMap<QString, QVariant> m_cache;
};
}
#endif // GLOBALSETTINGSPRIVATE_H

View File

@ -18,47 +18,21 @@
* Modified by: zhangpengfei <zhangpengfei@kylinos.cn>
*
*/
#include <QtConcurrent>
#include <QPalette>
#include "global-settings.h"
#include "global-settings-private.h"
#include <QPalette>
#include <QApplication>
#include <QDBusReply>
#include <QDebug>
#define CONTROL_CENTER_PERSONALISE_GSETTINGS_ID "org.ukui.control-center.personalise"
#define THEME_GSETTINGS_ID "org.ukui.style"
using namespace UkuiSearch;
static GlobalSettings *globalInstance = nullptr;
GlobalSettings *GlobalSettings::getInstance() {
if(!globalInstance) {
globalInstance = new GlobalSettings;
}
return globalInstance;
}
GlobalSettings::GlobalSettings(QObject *parent) : QObject(parent)
GlobalSettingsPrivate::GlobalSettingsPrivate(QObject *parent) : QObject(parent)
{
//搜索黑名单过滤
m_blockDirsSettings = new QSettings(BLOCK_DIRS, QSettings::IniFormat, this);
m_blockDirsSettings->setIniCodec(QTextCodec::codecForName("UTF-8"));
m_blockDirsSettings->setValue("These_are_block_dirs_conf_for_ukui_search","0");
m_blockDirsSettings->sync();
m_confWatcher = new QFileSystemWatcher(this);
m_confWatcher->addPath(BLOCK_DIRS);
connect(m_confWatcher, &QFileSystemWatcher::fileChanged, this, [ & ]() {
m_blockDirsSettings->sync();
m_confWatcher->addPath(BLOCK_DIRS);
});
//搜索历史记录
m_searchRecordSettings = new QSettings(SEARCH_HISTORY, QSettings::IniFormat, this);
m_searchRecordSettings->setIniCodec(QTextCodec::codecForName("UTF-8"));
for(QString i : m_searchRecordSettings->allKeys()) {
m_history.append(QUrl::fromPercentEncoding(i.toLocal8Bit()));
}
if(!QDBusConnection::sessionBus().connect("org.kylinssoclient.dbus",
"/org/kylinssoclient/path",
"org.freedesktop.kylinssoclient.interface",
"keyChanged",
this, SLOT(updateSearchHistory(QString))))
qWarning() << "Kylinssoclient Dbus connect fail!";
//全局页面透明度
//the default number of transparency for mainwindow is 0.7
setValue(TRANSPARENCY_KEY, 0.7);
@ -66,9 +40,10 @@ GlobalSettings::GlobalSettings(QObject *parent) : QObject(parent)
m_transGsettings = new QGSettings(CONTROL_CENTER_PERSONALISE_GSETTINGS_ID, QByteArray(), this);
connect(m_transGsettings, &QGSettings::changed, this, [ = ](const QString & key) {
if(key == TRANSPARENCY_KEY) {
setValue(TRANSPARENCY_KEY, m_transGsettings->get(TRANSPARENCY_KEY).toDouble());
double transparency = m_transGsettings->get(TRANSPARENCY_KEY).toDouble();
setValue(TRANSPARENCY_KEY, transparency);
qApp->paletteChanged(qApp->palette());
Q_EMIT this->transparencyChanged(m_transGsettings->get(TRANSPARENCY_KEY).toDouble());
Q_EMIT this->valueChanged(TRANSPARENCY_KEY, transparency);
}
});
if(m_transGsettings->keys().contains(TRANSPARENCY_KEY)) {
@ -86,7 +61,7 @@ GlobalSettings::GlobalSettings(QObject *parent) : QObject(parent)
//当前主题改变时也发出paletteChanged信号通知主界面刷新
setValue(STYLE_NAME_KEY, m_themeGsettings->get(STYLE_NAME_KEY).toString());
qApp->paletteChanged(qApp->palette());
Q_EMIT this->styleChanged(m_themeGsettings->get(STYLE_NAME_KEY).toString());
Q_EMIT this->valueChanged(STYLE_NAME_KEY, m_themeGsettings->get(STYLE_NAME_KEY).toString());
} else if(key == FONT_SIZE_KEY) {
setValue(FONT_SIZE_KEY, m_themeGsettings->get(FONT_SIZE_KEY).toDouble());
qApp->paletteChanged(qApp->palette());
@ -101,41 +76,9 @@ GlobalSettings::GlobalSettings(QObject *parent) : QObject(parent)
setValue(FONT_SIZE_KEY, m_themeGsettings->get(FONT_SIZE_KEY).toDouble());
}
}
//文件索引与搜索插件相关设置
setValue(FILE_INDEX_ENABLE_KEY, false);
setValue(WEB_ENGINE_KEY, "baidu");
setValue(CONTENT_FUZZY_SEARCH_KEY, false);
if(QGSettings::isSchemaInstalled(UKUI_SEARCH_SCHEMAS)) {
m_searchGsettings = new QGSettings(UKUI_SEARCH_SCHEMAS, QByteArray(), this);
connect(m_searchGsettings, &QGSettings::changed, this, [ = ](const QString & key) {
if(key == FILE_INDEX_ENABLE_KEY) {
bool fileSearchEnable = m_searchGsettings->get(FILE_INDEX_ENABLE_KEY).toBool();
setValue(FILE_INDEX_ENABLE_KEY, fileSearchEnable);
Q_EMIT fileSearchEnableChanged(fileSearchEnable);
} else if(key == WEB_ENGINE_KEY) {
QString webSearchEngine = m_searchGsettings->get(WEB_ENGINE_KEY).toString();
setValue(WEB_ENGINE_KEY, webSearchEngine);
Q_EMIT webSearchEngineChanged(webSearchEngine);
} else if (key == CONTENT_FUZZY_SEARCH_KEY) {
bool contentFuzzySearch = m_searchGsettings->get(CONTENT_FUZZY_SEARCH_KEY).toBool();
setValue(CONTENT_FUZZY_SEARCH_KEY, contentFuzzySearch);
Q_EMIT contentFuzzySearchEnableChanged(contentFuzzySearch);
}
});
if(m_searchGsettings->keys().contains(FILE_INDEX_ENABLE_KEY)) {
setValue(FILE_INDEX_ENABLE_KEY, m_searchGsettings->get(FILE_INDEX_ENABLE_KEY).toBool());
}
if(m_searchGsettings->keys().contains(WEB_ENGINE_KEY)) {
setValue(WEB_ENGINE_KEY, m_searchGsettings->get(WEB_ENGINE_KEY).toString());
}
if(m_searchGsettings->keys().contains(CONTENT_FUZZY_SEARCH_KEY)) {
setValue(CONTENT_FUZZY_SEARCH_KEY, m_searchGsettings->get(CONTENT_FUZZY_SEARCH_KEY).toBool());
}
}
}
const QVariant GlobalSettings::getValue(const QString &key) {
const QVariant GlobalSettingsPrivate::getValue(const QString &key) {
m_mutex.lock();
QVariant value = m_cache.value(key);
@ -143,70 +86,24 @@ const QVariant GlobalSettings::getValue(const QString &key) {
return value;
}
bool GlobalSettings::setBlockDirs(const QString &path, int &returnCode, bool remove) {
if(remove) {
if(path.isEmpty()) {
returnCode = PATH_EMPTY;
return false;
}
m_blockDirsSettings->remove(path);
return true;
}
//why QSetting's key can't start with "/"??
QString pathKey = path.right(path.length() - 1);
if (pathKey.endsWith(QLatin1Char('/'))) {
pathKey = pathKey.mid(0, pathKey.length() - 1);
}
QStringList blockDirs = m_blockDirsSettings->allKeys();
for(QString i : blockDirs) {
if(FileUtils::isOrUnder(pathKey, i)) {
// returnCode = QString(tr("My parent folder has been blocked!"));
returnCode = PATH_PARENT_BLOCKED;
return false;
}
if(FileUtils::isOrUnder(i, pathKey))
m_blockDirsSettings->remove(i);
}
m_blockDirsSettings->setValue(pathKey, "0");
return true;
}
QStringList GlobalSettings::getBlockDirs() {
return m_blockDirsSettings->allKeys();
}
void GlobalSettings::setSearchRecord(const QString &word, const QDateTime &time) {
QStringList keys = m_searchRecordSettings->allKeys();
if(keys.contains(QString(QUrl::toPercentEncoding(word))))
m_history.removeOne(word);
m_searchRecordSettings->setValue(QString(QUrl::toPercentEncoding(word)), time.toString("yyyy-MM-dd hh:mm:ss"));
if(keys.size() >= 20)
m_searchRecordSettings->remove(QString(QUrl::toPercentEncoding(m_history.takeFirst())));
m_history.append(word);
}
QStringList GlobalSettings::getSearchRecord() {
return m_history;
}
//this method is designed for main process settings only!!
void GlobalSettings::setValue(const QString &key, const QVariant &value) {
void GlobalSettingsPrivate::setValue(const QString &key, const QVariant &value) {
m_mutex.lock();
m_cache.insert(key, value);
m_mutex.unlock();
}
void GlobalSettings::updateSearchHistory(QString key) {
if(key == "search") {
m_searchRecordSettings->sync();
m_history.clear();
for(QString i : m_searchRecordSettings->allKeys()) {
m_history.append(QUrl::fromPercentEncoding(i.toLocal8Bit()));
GlobalSettings &GlobalSettings::getInstance() {
static GlobalSettings instance;
return instance;
}
const QVariant GlobalSettings::getValue(const QString& key)
{
return d->getValue(key);
}
GlobalSettings::GlobalSettings(QObject *parent) : QObject(parent), d(new GlobalSettingsPrivate(this))
{
connect(d, &GlobalSettingsPrivate::valueChanged, this, &GlobalSettings::valueChanged);
}

View File

@ -22,45 +22,18 @@
#define GLOBALSETTINGS_H
#include <QObject>
#include <QSettings>
#include <QMutex>
#include <QVector>
#include <QDir>
#include <QFileSystemWatcher>
//#include <QGSettings>
//If use pkg_config, it wont build succes,why?????????
//My demo can build access yet.
//MouseZhangZh
#include <QGSettings/QGSettings>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QApplication>
#include <QString>
#include <QVariant>
#include "libsearch_global.h"
#include "file-utils.h"
#define CONTROL_CENTER_PERSONALISE_GSETTINGS_ID "org.ukui.control-center.personalise"
#define TRANSPARENCY_KEY "transparency"
#define THEME_GSETTINGS_ID "org.ukui.style"
#define STYLE_NAME_KEY "styleName"
#define FONT_SIZE_KEY "systemFontSize"
#define ICON_THEME_KEY "iconThemeName"
#define UKUI_SEARCH_SCHEMAS "org.ukui.search.settings"
#define FILE_INDEX_ENABLE_KEY "fileIndexEnable"
#define WEB_ENGINE_KEY "webEngine"
#define CONTENT_FUZZY_SEARCH_KEY "contentFuzzySearch"
#define WEB_ENGINE "web_engine"
#define PATH_EMPTY 1;
#define PATH_NOT_IN_HOME 2;
#define PATH_PARENT_BLOCKED 3;
#define BLOCK_DIRS QDir::homePath() + "/.config/org.ukui/ukui-search/ukui-search-block-dirs.conf"
#define SEARCH_HISTORY QDir::homePath() + "/.config/org.ukui/ukui-search/ukui-search-history.conf"
//#define CLOUD_HISTORY "history"
//#define CLOUD_APPLICATIONS "applications"
namespace UkuiSearch {
const static QString TRANSPARENCY_KEY = "transparency";
const static QString STYLE_NAME_KEY = "styleName";
const static QString FONT_SIZE_KEY = "systemFontSize";
const static QString ICON_THEME_KEY = "iconThemeName";
class GlobalSettingsPrivate;
/**
* @brief The GlobalSettings class
*
@ -69,48 +42,18 @@ namespace UkuiSearch {
class LIBSEARCH_EXPORT GlobalSettings : public QObject {
Q_OBJECT
public:
static GlobalSettings *getInstance();
const QVariant getValue(const QString&);
/**
* @brief setBlockDirs
* set path for blacklist,return true if success,otherwise return false.
* @param path path to be blocked
* @param returnMessage this message will be set when return false.
* @param true to remove blocking,false to set blocking,default set false.
* @return
*/
bool setBlockDirs(const QString& path, int &returnCode, bool remove = false);
QStringList getBlockDirs();
void setSearchRecord(const QString &word, const QDateTime &time);
QStringList getSearchRecord();
void updateSearchHistory(QString key);
static GlobalSettings& getInstance();
const QVariant getValue(const QString& key);
Q_SIGNALS:
void valueChanged(const QString&);
void transparencyChanged(const double&);
void styleChanged(const QString&);
void fileSearchEnableChanged(bool);
void webSearchEngineChanged(const QString&);
void contentFuzzySearchEnableChanged(bool);
void valueChanged(const QString& key, QVariant value);
private:
explicit GlobalSettings(QObject *parent = nullptr);
~GlobalSettings() = default;
void setValue(const QString&, const QVariant&);
QGSettings *m_transGsettings;
QGSettings *m_themeGsettings;
QGSettings *m_searchGsettings;
QSettings *m_blockDirsSettings;
QSettings *m_searchRecordSettings;
QMap<QString, QVariant> m_cache;
QStringList m_history;
QFileSystemWatcher *m_confWatcher;
QMutex m_mutex;
// size_t test = 0;
GlobalSettings(const GlobalSettings&) = delete;
GlobalSettings& operator =(const GlobalSettings&) = delete;
GlobalSettingsPrivate *d;
};
}

View File

@ -18,9 +18,10 @@
*
*/
#include "basic-indexer.h"
#include "file-utils.h"
#include <QDateTime>
#include <QFileInfo>
#include <QUrl>
#include "file-utils.h"
using namespace UkuiSearch;
BasicIndexer::BasicIndexer(const QString& filePath): m_filePath(filePath)
{

View File

@ -19,8 +19,11 @@
*/
#include "batch-indexer.h"
#include <QFileInfo>
#include <QTime>
#include <QElapsedTimer>
#include <QDebug>
#include <malloc.h>
#include <QQueue>
#include <QDateTime>
#include "file-utils.h"
#include "basic-indexer.h"
@ -40,7 +43,8 @@ BatchIndexer::BatchIndexer(const QStringList &folders, const QStringList &blackL
void BatchIndexer::run()
{
QTime t = QTime::currentTime();
QElapsedTimer timer;
timer.start();
if(m_target == Target::None || m_stop->LOAD) {
Q_EMIT done(m_mode);
return;
@ -55,7 +59,7 @@ void BatchIndexer::run()
}
m_cache.clear();
malloc_trim(0);
qDebug() << "FirstRunIndexer: time :" << t.elapsed();
qDebug() << "FirstRunIndexer: time :" << timer.elapsed() << "milliseconds";
Q_EMIT done(m_mode);
}
@ -196,7 +200,7 @@ void BatchIndexer::contentIndex()
// bool ocrEnable = FileIndexerConfig::getInstance()->isOCREnable();
if(FileIndexerConfig::getInstance()->isOCREnable()) {
qDebug() << "OCR enabled.";
suffixMap.unite(targetPhotographTypeMap);
suffixMap.INSERT(targetPhotographTypeMap);
}
if(m_mode == WorkMode::Rebuild) {
contentDb.rebuild();

View File

@ -1,12 +1,37 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#ifndef COMPATIBLEDEFINE_H
#define COMPATIBLEDEFINE_H
#include <QtGlobal>
#endif // COMPATIBLEDEFINE_H
#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
//T QAtomicInteger::load() const
#define LOAD load()
//QMap<Key, T> &QMap::unite(const QMap<Key, T> &other)
#define INSERT(T) unite(T)
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
//T QAtomicInteger::loadRelaxed() const
#define LOAD loadRelaxed()
//void QMap::insert(const QMap<Key, T> &map)
#define INSERT(T) insert(T)
#endif

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#include "database.h"
using namespace UkuiSearch;

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#ifndef DATABASE_H
#define DATABASE_H
#include <xapian.h>

View File

@ -18,6 +18,7 @@
*
*/
#include "file-content-indexer.h"
#include <QDateTime>
#include "file-reader.h"
#include "file-utils.h"
#include "chinese-segmentation.h"
@ -41,9 +42,8 @@ bool fileContentIndexer::index()
}
m_document.setData(content);
//'\xEF\xBC\x8C' is "" "\xE3\x80\x82" is "。" use three " " to replace ,to ensure the offset info.
content = content.replace("\t", " ").replace("\xEF\xBC\x8C", " ").replace("\xE3\x80\x82", " ");
std::vector<KeyWord> term = ChineseSegmentation::getInstance()->callSegment(content.left(20480000).toStdString());
std::vector<KeyWord> term = ChineseSegmentation::getInstance()->callSegment(content);
content.clear();
content.squeeze();
@ -57,7 +57,10 @@ bool fileContentIndexer::index()
m_document.addTerm("PARENTTERM" + FileUtils::makeDocUterm(m_filePath.section("/", 0, -2, QString::SectionIncludeLeadingSep)));
m_document.addValue(1, m_filePath);
m_document.addValue(2, suffix);
m_document.setIndexTime(info.lastModified().toString("yyyyMMddHHmmsszzz"));
QString time = info.lastModified().toString("yyyyMMddHHmmsszzz");
m_document.addSortableSerialiseValue(3, time);
m_document.setIndexTime(time);
return true;
}

View File

@ -27,6 +27,7 @@
static const QByteArray UKUI_SEARCH_SCHEMAS = QByteArrayLiteral("org.ukui.search.settings");
static const QString FILE_INDEX_ENABLE_KEY = QStringLiteral("fileIndexEnable");
static const QString CONTENT_INDEX_ENABLE_KEY = QStringLiteral("contentIndexEnable");
static const QString CONTENT_FUZZY_SEARCH_KEY = QStringLiteral("contentFuzzySearch");
static const QString OCR_ENABLE_KEY = QStringLiteral("ocrEnable");
static const QString META_DATA_INDEX_ENABLE_KEY = QStringLiteral("metaDataIndexEnable");
@ -41,7 +42,7 @@ FileIndexerConfig *FileIndexerConfig::getInstance()
return global_intance;
}
FileIndexerConfig::FileIndexerConfig(QObject *parent) \
FileIndexerConfig::FileIndexerConfig(QObject *parent)
: QObject(parent),
m_dirWatcher(DirWatcher::getDirWatcher())
{
@ -98,6 +99,21 @@ bool FileIndexerConfig::isContentIndexEnable()
return m_settings->value(CONTENT_INDEX_ENABLE_KEY, true).toBool();
}
bool FileIndexerConfig::isFuzzySearchEnable()
{
if(m_gsettings) {
if(m_gsettings->keys().contains(CONTENT_FUZZY_SEARCH_KEY)) {
return m_gsettings->get(CONTENT_FUZZY_SEARCH_KEY).toBool();
} else {
qWarning() << "FileIndexerConfig: Can not find key:" << CONTENT_FUZZY_SEARCH_KEY << "in" << UKUI_SEARCH_SCHEMAS;
return false;
}
} else {
qWarning() << "FileIndexerConfig:" << UKUI_SEARCH_SCHEMAS << " is not found!";
return false;
}
}
bool FileIndexerConfig::isOCREnable()
{
return m_settings->value(OCR_ENABLE_KEY, true).toBool();

View File

@ -51,6 +51,11 @@ public:
* @return
*/
bool isContentIndexEnable();
/**
* @brief isFuzzySearchEnable
* @return
*/
bool isFuzzySearchEnable();
/**
* @brief isOCREnable
* @return OCR功能

View File

@ -21,6 +21,7 @@
#include "file-utils.h"
#include "binary-parser.h"
#include "ocrobject.h"
#include "common.h"
using namespace UkuiSearch;
FileReader::FileReader(QObject *parent) : QObject(parent)
{

View File

@ -23,12 +23,13 @@
#include <QHBoxLayout>
#include <QMessageBox>
#include "search-manager.h"
#include "file-indexer-config.h"
#define OCR_ICONLABLE_WITH 352
#define OCR_ICONLABLE_HEIGHT 247
using namespace UkuiSearch;
FileSearchPlugin::FileSearchPlugin(QObject *parent) : QObject(parent),m_settings(GlobalSettings::getInstance())
FileSearchPlugin::FileSearchPlugin(QObject *parent) : QObject(parent)
{
SearchPluginIface::Actioninfo open { 0, tr("Open")};
SearchPluginIface::Actioninfo Openpath { 1, tr("Open path")};
@ -60,7 +61,7 @@ void UkuiSearch::FileSearchPlugin::KeywordSearch(QString keyword, DataQueue<Resu
++SearchManager::uniqueSymbolFile;
SearchManager::m_mutexFile.unlock();
if(m_settings->getValue(FILE_INDEX_ENABLE_KEY).toBool()) {
if(FileIndexerConfig::getInstance()->isFileIndexEnable()) {
FileSearch *filesearch;
filesearch = new FileSearch(searchResult, SearchManager::uniqueSymbolFile, keyword, FILE_SEARCH_VALUE, 1, 0, 5);
m_pool.start(filesearch);
@ -80,23 +81,23 @@ void FileSearchPlugin::stopSearch()
QList<SearchPluginIface::Actioninfo> FileSearchPlugin::getActioninfo(int type)
{
Q_UNUSED(type)
return m_actionInfo;
}
void FileSearchPlugin::openAction(int actionkey, QString key, int type)
{
Q_UNUSED(type)
//TODO add some return message here.
qDebug() << "openAction!!!!!!!!";
switch (actionkey) {
case 0:
if(FileUtils::openFile(key) == -1) {
QMessageBox msgBox(m_detailPage);
msgBox.setWindowModality(Qt::WindowModal);
msgBox.setStandardButtons(QMessageBox::Yes);
msgBox.setButtonText(QMessageBox::Yes, tr("Yes"));
msgBox.setModal(true);
msgBox.addButton(tr("Yes"), QMessageBox::YesRole);
msgBox.setIcon(QMessageBox::Information);
msgBox.setText(tr("Can not get a default application for opening %1.").arg(key));
msgBox.exec();
msgBox.open();
}
break;
case 1:
@ -203,12 +204,11 @@ void FileSearchPlugin::initDetailPage()
connect(m_actionLabel1, &ActionLabel::actionTriggered, [ & ](){
if(FileUtils::openFile(m_currentActionKey) == -1) {
QMessageBox msgBox(m_detailPage);
msgBox.setWindowModality(Qt::WindowModal);
msgBox.setStandardButtons(QMessageBox::Yes);
msgBox.setButtonText(QMessageBox::Yes, tr("Yes"));
msgBox.setModal(true);
msgBox.addButton(tr("Yes"), QMessageBox::YesRole);
msgBox.setIcon(QMessageBox::Information);
msgBox.setText(tr("Can not get a default application for opening %1.").arg(m_currentActionKey));
msgBox.exec();
msgBox.open();
}
});
connect(m_actionLabel2, &ActionLabel::actionTriggered, [ & ](){
@ -238,7 +238,7 @@ void FileSearchPlugin::initDetailPage()
// return previewPage;
//}
DirSearchPlugin::DirSearchPlugin(QObject *parent) : QObject(parent),m_settings(GlobalSettings::getInstance())
DirSearchPlugin::DirSearchPlugin(QObject *parent) : QObject(parent)
{
SearchPluginIface::Actioninfo open { 0, tr("Open")};
SearchPluginIface::Actioninfo Openpath { 1, tr("Open path")};
@ -270,7 +270,7 @@ void UkuiSearch::DirSearchPlugin::KeywordSearch(QString keyword, DataQueue<Resul
++SearchManager::uniqueSymbolDir;
SearchManager::m_mutexDir.unlock();
if(m_settings->getValue(FILE_INDEX_ENABLE_KEY).toBool()) {
if(FileIndexerConfig::getInstance()->isFileIndexEnable()) {
FileSearch *filesearch;
filesearch = new FileSearch(searchResult, SearchManager::uniqueSymbolDir, keyword, DIR_SEARCH_VALUE, 1, 0, 5);
m_pool.start(filesearch);
@ -290,11 +290,13 @@ void DirSearchPlugin::stopSearch()
QList<SearchPluginIface::Actioninfo> DirSearchPlugin::getActioninfo(int type)
{
Q_UNUSED(type)
return m_actionInfo;
}
void DirSearchPlugin::openAction(int actionkey, QString key, int type)
{
Q_UNUSED(type)
//TODO add some return message here.
switch (actionkey) {
case 0:
@ -302,6 +304,7 @@ void DirSearchPlugin::openAction(int actionkey, QString key, int type)
break;
case 1:
FileUtils::openFile(key, true);
break;
case 2:
FileUtils::copyPath(key);
default:
@ -421,7 +424,7 @@ void DirSearchPlugin::initDetailPage()
// return nullptr;
//}
FileContengSearchPlugin::FileContengSearchPlugin(QObject *parent) : QObject(parent),m_settings(GlobalSettings::getInstance())
FileContengSearchPlugin::FileContengSearchPlugin(QObject *parent) : QObject(parent)
{
SearchPluginIface::Actioninfo open { 0, tr("Open")};
SearchPluginIface::Actioninfo Openpath { 1, tr("Open path")};
@ -454,9 +457,9 @@ void UkuiSearch::FileContengSearchPlugin::KeywordSearch(QString keyword, DataQue
SearchManager::m_mutexContent.unlock();
m_keyWord = keyword;
if(m_settings->getValue(FILE_INDEX_ENABLE_KEY).toBool()) {
if(FileIndexerConfig::getInstance()->isFileIndexEnable()) {
FileContentSearch *fileContentSearch;
fileContentSearch = new FileContentSearch(searchResult, SearchManager::uniqueSymbolContent, keyword, m_settings->getValue(CONTENT_FUZZY_SEARCH_KEY).toBool(), 0, 5);
fileContentSearch = new FileContentSearch(searchResult, SearchManager::uniqueSymbolContent, keyword, FileIndexerConfig::getInstance()->isFuzzySearchEnable(), 0, 5);
m_pool.start(fileContentSearch);
}
}
@ -470,11 +473,13 @@ void FileContengSearchPlugin::stopSearch()
QList<SearchPluginIface::Actioninfo> FileContengSearchPlugin::getActioninfo(int type)
{
Q_UNUSED(type)
return m_actionInfo;
}
void FileContengSearchPlugin::openAction(int actionkey, QString key, int type)
{
Q_UNUSED(type)
//TODO add some return message here.
switch (actionkey) {
case 0:
@ -482,6 +487,7 @@ void FileContengSearchPlugin::openAction(int actionkey, QString key, int type)
break;
case 1:
FileUtils::openFile(key, true);
break;
case 2:
FileUtils::copyPath(key);
default:
@ -556,18 +562,18 @@ QString FileContengSearchPlugin::wrapData(QLabel *p_label, const QString &text)
QString wrapText = text;
QFontMetrics fontMetrics = p_label->fontMetrics();
int textSize = fontMetrics.width(wrapText);
int textSize = fontMetrics.horizontalAdvance(wrapText);
if(textSize > LABEL_MAX_WIDTH){
int lastIndex = 0;
int count = 0;
for(int i = lastIndex; i < wrapText.length(); i++) {
if(fontMetrics.width(wrapText.mid(lastIndex, i - lastIndex)) == LABEL_MAX_WIDTH) {
if(fontMetrics.horizontalAdvance(wrapText.mid(lastIndex, i - lastIndex)) == LABEL_MAX_WIDTH) {
lastIndex = i;
wrapText.insert(i, '\n');
count++;
} else if(fontMetrics.width(wrapText.mid(lastIndex, i - lastIndex)) > LABEL_MAX_WIDTH) {
} else if(fontMetrics.horizontalAdvance(wrapText.mid(lastIndex, i - lastIndex)) > LABEL_MAX_WIDTH) {
lastIndex = i;
wrapText.insert(i - 1, '\n');
count++;

View File

@ -90,7 +90,6 @@ private:
bool m_enable = true;
QList<SearchPluginIface::Actioninfo> m_actionInfo;
QThreadPool m_pool;
GlobalSettings *m_settings = nullptr;
};
class LIBSEARCH_EXPORT DirSearchPlugin : public QObject, public SearchPluginIface
@ -145,7 +144,6 @@ private:
bool m_enable = true;
QList<SearchPluginIface::Actioninfo> m_actionInfo;
QThreadPool m_pool;
GlobalSettings *m_settings = nullptr;
};
class LIBSEARCH_EXPORT FileContengSearchPlugin : public QObject, public SearchPluginIface
@ -203,7 +201,6 @@ private:
bool m_enable = true;
QList<SearchPluginIface::Actioninfo> m_actionInfo;
QThreadPool m_pool;
GlobalSettings *m_settings = nullptr;
};
}

View File

@ -26,6 +26,7 @@ FileWatcher::FileWatcher(QObject *parent) : QObject(parent), m_config(FileIndexe
m_pendingFileQUeue = PendingFileQueue::getInstance();
connect(m_watcher, &FileSystemWatcher::created, this, &FileWatcher::onFileCreated);
connect(m_watcher, &FileSystemWatcher::moveTo, this, &FileWatcher::onFileMoveTo);
connect(m_watcher, &FileSystemWatcher::modified, this, &FileWatcher::onFileModefied);
connect(m_watcher, &FileSystemWatcher::deleted, this, &FileWatcher::onFileDeletedOrMoved);
connect(m_watcher, &FileSystemWatcher::moved, this, &FileWatcher::onFileDeletedOrMoved);
@ -87,6 +88,14 @@ void FileWatcher::onFileCreated(const QString &path, bool isDir)
m_pendingFileQUeue->enqueue(file);
}
void FileWatcher::onFileMoveTo(const QString &path, bool isDir)
{
PendingFile file(path);
file.setIsDir(isDir);
file.setMoveTo();
m_pendingFileQUeue->enqueue(file);
}
void FileWatcher::onFileModefied(const QString &path)
{
PendingFile file(path);

View File

@ -62,6 +62,7 @@ Q_SIGNALS:
private:
void onFileCreated(const QString& path, bool isDir);
void onFileMoveTo(const QString& path, bool isDir);
void onFileModefied(const QString& path);
void onFileDeletedOrMoved(const QString& path, bool isDir);
FileSystemWatcher *m_watcher = nullptr;

View File

@ -55,9 +55,11 @@ void IndexScheduler::addNewPath(const QString &folders, const QStringList &black
BatchIndexer::Targets target = BatchIndexer::Target::None;
if(m_config->isFileIndexEnable()) {
target |= BatchIndexer::Target::Basic;
m_statusRecorder->setStatus(INDEX_DATABASE_STATE_KEY, IndexStatusRecorder::State::Updating);
}
if(m_config->isContentIndexEnable()) {
target |= BatchIndexer::Target::Content;
m_statusRecorder->setStatus(CONTENT_INDEX_DATABASE_STATE_KEY, IndexStatusRecorder::State::Updating);
}
BatchIndexer::WorkMode mode = BatchIndexer::WorkMode::Add;
startIndexJob(QStringList() << folders, blackList, mode, target);
@ -84,6 +86,8 @@ void IndexScheduler::stop()
m_state = Stop;
qDebug() << "Index scheduler has been stopped.";
Q_EMIT stateChange(m_state);
m_statusRecorder->setStatus(INDEX_DATABASE_STATE_KEY, IndexStatusRecorder::State::Off);
m_statusRecorder->setStatus(CONTENT_INDEX_DATABASE_STATE_KEY, IndexStatusRecorder::State::Off);
}
void IndexScheduler::start()

View File

@ -39,7 +39,8 @@ public:
Initializing = 0,
Error = 1,
Ready = 2,
Updating = 3
Updating = 3,
Off = 4
};
Q_ENUM(State)

View File

@ -25,6 +25,7 @@
#include "file-content-indexer.h"
#include "common.h"
#include "file-utils.h"
#include "compatible-define.h"
using namespace UkuiSearch;
IndexUpdater::IndexUpdater(const QVector<PendingFile>& files, QAtomicInt &stop)
: m_cache(files),
@ -62,7 +63,7 @@ void IndexUpdater::UpdateIndex()
qDebug() << "===finish update basic index===";
}
if(FileIndexerConfig::getInstance()->isContentIndexEnable()) {
if(m_stop->load()) {
if(m_stop->LOAD) {
qDebug() << "Index stopped, abort update content index.";
return;
}
@ -75,7 +76,7 @@ void IndexUpdater::UpdateIndex()
QMap<QString, bool> suffixMap = targetFileTypeMap;
//ocr
if(FileIndexerConfig::getInstance()->isOCREnable()) {
suffixMap.unite(targetPhotographTypeMap);
suffixMap.INSERT(targetPhotographTypeMap);
}
qDebug() << "===update content index===";
int size = 0;
@ -89,8 +90,10 @@ void IndexUpdater::UpdateIndex()
contentDb.removeDocument(file.path());
}
} else if(true == suffixMap[suffix] && !file.isDir()) {
if(FileUtils::isEncrypedOrUnsupport(file.path(), suffix) && file.isModified()) {
if(FileUtils::isEncrypedOrUnsupport(file.path(), suffix)) {
if(file.isModified() || file.isMoveTo()) {
contentDb.removeDocument(file.path());
}
continue;
}
qDebug() << "| index:" <<file.path();
@ -98,7 +101,8 @@ void IndexUpdater::UpdateIndex()
if(indexer.index()) {
contentDb.addDocument(indexer.document());
++size;
} else if(file.isModified()){
} else if(file.isModified() || file.isMoveTo()){
contentDb.removeDocument(file.path());
}
}
@ -107,7 +111,7 @@ void IndexUpdater::UpdateIndex()
qDebug() << "30 finished.";
size = 0;
}
if(m_stop->load()) {
if(m_stop->LOAD) {
qDebug() << "Index stopped, content index update interrupted";
m_cache.clear();
m_cache.shrink_to_fit();

View File

@ -1,3 +1,21 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "ocrobject.h"
OcrObject *OcrObject::m_instance = nullptr;

View File

@ -1,3 +1,22 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#ifndef OCROBJECT_H
#define OCROBJECT_H

View File

@ -42,6 +42,8 @@ public:
bool isModified() { return m_modified; }
void setCreated() { m_created = true; }
void setMoveTo() { m_moveTo = true;}
bool isMoveTo() { return m_moveTo;}
void setDeleted() { m_deleted = true; }
@ -66,6 +68,7 @@ private:
QString m_path;
bool m_created : 1;
bool m_moveTo : 1;
bool m_deleted : 1;
bool m_modified : 1;
bool m_isDir : 1;

View File

@ -47,7 +47,7 @@ int SearchManager::getCurrentIndexCount() {
}
bool SearchManager::isBlocked(QString &path) {
QStringList blockList = GlobalSettings::getInstance()->getBlockDirs();
QStringList blockList = DirWatcher::getDirWatcher()->getBlockDirsOfUser();
for(QString i : blockList) {
if(FileUtils::isOrUnder(path, i))
return true;
@ -128,7 +128,7 @@ int FileSearch::keywordSearchfile() {
try {
qDebug() << "--keywordSearchfile start--";
Xapian::Database db(INDEX_PATH);
Xapian::Query query = creatQueryForFileSearch(db);
Xapian::Query query = creatQueryForFileSearch();
Xapian::Enquire enquire(db);
Xapian::Query queryFile;
@ -162,7 +162,7 @@ int FileSearch::keywordSearchfile() {
}
}
Xapian::Query FileSearch::creatQueryForFileSearch(Xapian::Database &db) {
Xapian::Query FileSearch::creatQueryForFileSearch() {
auto userInput = m_keyword.toLower();
std::vector<Xapian::Query> v;
for(int i = 0; i < userInput.size(); i++) {
@ -274,7 +274,7 @@ int FileContentSearch::keywordSearchContent() {
qp.set_default_op(Xapian::Query::OP_AND);
qp.set_database(db);
std::vector<KeyWord> sKeyWord = ChineseSegmentation::getInstance()->callSegment(m_keyword.toStdString());
std::vector<KeyWord> sKeyWord = ChineseSegmentation::getInstance()->callSegment(m_keyword);
//Creat a query
std::string words;
for(size_t i = 0; i < sKeyWord.size(); i++) {
@ -414,14 +414,14 @@ int OcrSearch::keywordSearchOcr() {
Xapian::QueryParser qp;
qp.set_default_op(Xapian::Query::OP_AND);
qp.set_database(db);
std::vector<KeyWord> sKeyWord = ChineseSegmentation::getInstance()->callSegment(m_keyword.toStdString());
std::vector<KeyWord> sKeyWord = ChineseSegmentation::getInstance()->callSegment(m_keyword);
//Creat a query
std::string words;
for(int i = 0; i < sKeyWord.size(); i++) {
for(size_t i = 0; i < sKeyWord.size(); i++) {
words.append(sKeyWord.at(i).word).append(" ");
}
std::vector<Xapian::Query> v;
for(int i=0; i<sKeyWord.size(); i++) {
for(size_t i = 0; i < sKeyWord.size(); i++) {
v.push_back(Xapian::Query(sKeyWord.at(i).word));
qDebug() << QString::fromStdString(sKeyWord.at(i).word);
}
@ -493,15 +493,22 @@ DirectSearch::DirectSearch(QString keyword, DataQueue<SearchPluginIface::ResultI
}
void DirectSearch::run() {
QStringList blockList = GlobalSettings::getInstance()->getBlockDirs();
QStringList blockList = DirWatcher::getDirWatcher()->getBlockDirsOfUser();
QStringList searchPath = DirWatcher::getDirWatcher()->currentIndexableDir();
QQueue<QString> bfs;
for (const QString &path : searchPath) {
if (blockList.contains(path)) {
continue;
bool underBlock(false);
for (const QString &blockDir : blockList) {
if (FileUtils::isOrUnder(path, blockDir)) {
underBlock = true;
break;
}
}
if (!underBlock) {
blockList.append(DirWatcher::getDirWatcher()->blackListOfDir(path));
bfs.enqueue(path);
match(QFileInfo(path));
}
}
if (bfs.isEmpty()) {
return;
@ -534,35 +541,25 @@ void DirectSearch::run() {
}
bfs.enqueue(i.absoluteFilePath());
}
if(i.fileName().contains(m_keyword, Qt::CaseInsensitive)) {
// qWarning() << i.fileName() << m_keyword;
// if(m_searchResult->length() > 49)
// return;
if((i.isDir() && m_value == DIR_SEARCH_VALUE)) {
SearchPluginIface::ResultInfo ri;
if(SearchManager::creatResultInfo(ri,i.absoluteFilePath())) {
SearchManager::m_mutexDir.lock();
if(m_uniqueSymbol == SearchManager::uniqueSymbolDir) {
m_searchResult->enqueue(ri);
match(i);
SearchManager::m_mutexDir.unlock();
} else {
SearchManager::m_mutexDir.unlock();
return;
}
}
} else if (i.isFile() && m_value == FILE_SEARCH_VALUE) {
}
}
void DirectSearch::match(const QFileInfo &info)
{
if(info.fileName().contains(m_keyword, Qt::CaseInsensitive)) {
if((info.isDir() && m_value == DIR_SEARCH_VALUE) || (info.isFile() && m_value == FILE_SEARCH_VALUE)) {
SearchPluginIface::ResultInfo ri;
if(SearchManager::creatResultInfo(ri,i.absoluteFilePath())) {
SearchManager::m_mutexFile.lock();
if(m_uniqueSymbol == SearchManager::uniqueSymbolFile) {
if(SearchManager::creatResultInfo(ri,info.absoluteFilePath())) {
m_searchResult->enqueue(ri);
SearchManager::m_mutexFile.unlock();
} else {
SearchManager::m_mutexFile.unlock();
return;
}
}
}
}
}
}

View File

@ -105,7 +105,7 @@ protected:
void run();
private:
int keywordSearchfile();
Xapian::Query creatQueryForFileSearch(Xapian::Database &db);
Xapian::Query creatQueryForFileSearch();
int getResult(Xapian::MSet &result);
DataQueue<SearchPluginIface::ResultInfo> *m_search_result = nullptr;
@ -161,6 +161,7 @@ public:
protected:
void run();
private:
void match(const QFileInfo& info);
QString m_keyword;
DataQueue<SearchPluginIface::ResultInfo>* m_searchResult = nullptr;
size_t m_uniqueSymbol;

View File

@ -1,4 +1,3 @@
/*
* Copyright (C) 2022, KylinSoft Co., Ltd.
*

View File

@ -7,7 +7,7 @@ TEMPLATE = lib
DEFINES += LIBSEARCH_LIBRARY
CONFIG += create_pc create_prl no_install_prl
PKGCONFIG += gio-2.0 glib-2.0 gio-unix-2.0 gsettings-qt poppler-qt5 kysdk-qtwidgets
PKGCONFIG += gio-2.0 glib-2.0 gio-unix-2.0 gsettings-qt poppler-qt5 kysdk-qtwidgets lept
CONFIG += c++11 link_pkgconfig no_keywords lrelease
QMAKE_CXXFLAGS += -Werror=return-type -Werror=return-local-addr -Werror=uninitialized
@ -39,32 +39,30 @@ include(settingsearch/settingsearch.pri)
include(websearch/websearch.pri)
include(searchinterface/search-interface.pri)
include(dirwatcher/dirwatcher.pri)
include(mailsearch/mailsearch.pri)
include(search-app-widget-plugin/search-app-widget-plugin.pri)
#include(mailsearch/mailsearch.pri)
LIBS += -L$$OUT_PWD/../libchinese-segmentation/ -lchinese-segmentation
LIBS += -lxapian -luchardet -lQt5Xdg -lquazip5 -ltesseract #-L/usr/local/lib/libjemalloc -ljemalloc
LIBS += -lukui-appwidget-manager -lukui-appwidget-provider
SOURCES += \
file-utils.cpp \
global-settings.cpp \
gobject-template.cpp \
libsearch.cpp
libsearch.cpp \
log-utils.cpp
HEADERS += \
app-db-common.h \
app-info-dbus-argument.h \
common.h \
file-utils.h \
global-settings-private.h \
global-settings.h \
gobject-template.h \
libsearch_global.h \
libsearch.h
libsearch.h \
log-utils.h
RESOURCES += \
resource1.qrc \
search-app-widget-plugin/provider/src.qrc
resource1.qrc
TRANSLATIONS += \
../translations/libukui-search/libukui-search_zh_CN.ts \
@ -73,22 +71,7 @@ TRANSLATIONS += \
qm_files.path = /usr/share/ukui-search/translations/
qm_files.files = $$OUT_PWD/.qm/*.qm
qml.files += search-app-widget-plugin/provider/data/search.qml
qml.path = /usr/share/appwidget/qml/
appwidgetconf.files += search-app-widget-plugin/provider/data/search.conf
appwidgetconf.path = /usr/share/appwidget/config/
service.files += search-app-widget-plugin/provider/org.ukui.appwidget.provider.search.service
service.path += /usr/share/dbus-1/services/
preview.files += search-app-widget-plugin/provider/data/search.png
preview.path = /usr/share/appwidget/search/
svg.files += search-app-widget-plugin/provider/data/ukui-search.svg
svg.path = /usr/share/appwidget/search/
INSTALLS += qml qm_files appwidgetconf service preview svg
INSTALLS += qm_files
# Default rules for deployment.
@ -105,12 +88,15 @@ unix {
INSTALLS += target
header.path = /usr/include/ukui-search
header.files += *.h index/*.h appsearch/*.h settingsearch/*.h plugininterface/*.h websearch/*.h search-app-widget-plugin/*.h \
header.files += libsearch_global.h \
plugininterface/*.h \
appdata/application-info.h \
appdata/application-property.h \
appdata/application-property-helper.h \
searchinterface/ukui-search-task.h \
appdata/app-info-table.h \
searchinterface/search-controller.h \
searchinterface/result-item.h \
filesystemwatcher/file-system-watcher.h
searchinterface/search-result-property.h
header.files += development-files/header-files/*
INSTALLS += header

118
libsearch/log-utils.cpp Normal file
View File

@ -0,0 +1,118 @@
#include "log-utils.h"
#include <QFile>
#include <QDebug>
#include <QDir>
#include <QDateTime>
#include <QStandardPaths>
#define LOG_FILE_COUNT 2
#define MAX_LOG_FILE_SIZE 4194304
#define MAX_LOG_CHECK_INTERVAL 43200000
quint64 LogUtils::m_startUpTime = 0;
int LogUtils::m_logFileId = -1;
QString LogUtils::m_logFileName;
QString LogUtils::m_currentLogFile;
static QString logFilePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + "/.log/ukui-search/";
void LogUtils::messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
checkLogFile();
QByteArray localMsg = msg.toLocal8Bit();
QByteArray currentTime = QTime::currentTime().toString().toLocal8Bit();
const char *file = context.file ? context.file : "";
const char *function = context.function ? context.function : "";
FILE *log_file = fopen(m_currentLogFile.toLocal8Bit().constData(), "a+");
switch (type) {
case QtDebugMsg:
if (!log_file) {
break;
}
fprintf(log_file, "Debug: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function);
break;
case QtInfoMsg:
fprintf(log_file? log_file: stdout, "Info: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function);
break;
case QtWarningMsg:
fprintf(log_file? log_file: stderr, "Warning: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function);
break;
case QtCriticalMsg:
fprintf(log_file? log_file: stderr, "Critical: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function);
break;
case QtFatalMsg:
fprintf(log_file? log_file: stderr, "Fatal: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function);
break;
}
if (log_file) {
fclose(log_file);
}
}
void LogUtils::initLogFile(const QString &fileName)
{
QDir dir;
if (!dir.exists(logFilePath)) {
if (!dir.mkpath(logFilePath)) {
qWarning() << "Unable to create" << logFilePath;
return;
}
}
m_logFileName = logFilePath + fileName + "-%1.log";
for (int i = 0; i < LOG_FILE_COUNT; ++i) {
m_currentLogFile = m_logFileName.arg(i);
if (QFile::exists(m_currentLogFile)) {
if (checkFileSize(m_currentLogFile)) {
m_logFileId = i;
break;
}
} else {
QFile file(m_currentLogFile);
file.open(QIODevice::WriteOnly);
file.close();
}
}
if (m_logFileId < 0) {
m_logFileId = 0;
m_currentLogFile = m_logFileName.arg(m_logFileId);
clearFile(m_currentLogFile);
}
qInfo() << "Current log file:" << m_currentLogFile;
}
void LogUtils::checkLogFile()
{
quint64 logTime = QDateTime::currentDateTime().toMSecsSinceEpoch();
quint64 spacing = std::max(logTime, m_startUpTime) - std::min(logTime, m_startUpTime);
if (spacing <= MAX_LOG_CHECK_INTERVAL || checkFileSize(m_currentLogFile)) {
return;
}
m_logFileId = ((m_logFileId + 1) % LOG_FILE_COUNT);
m_currentLogFile = m_logFileName.arg(m_logFileId);
if (!checkFileSize(m_currentLogFile)) {
clearFile(m_currentLogFile);
}
}
bool LogUtils::checkFileSize(const QString &fileName)
{
return QFile(fileName).size() < MAX_LOG_FILE_SIZE;
}
void LogUtils::clearFile(const QString &fileName)
{
QFile file(fileName);
file.open(QIODevice::WriteOnly);
file.write("");
file.flush();
file.close();
}

21
libsearch/log-utils.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef LOGUTILS_H
#define LOGUTILS_H
#include <QtMessageHandler>
class LogUtils
{
public:
static void initLogFile(const QString &fileName);
static void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);
private:
static void checkLogFile();
static bool checkFileSize(const QString &fileName);
static void clearFile(const QString &fileName);
static quint64 m_startUpTime;
static int m_logFileId;
static QString m_logFileName;
static QString m_currentLogFile;
};
#endif // LOGUTILS_H

View File

@ -1,4 +1,24 @@
/*
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
*/
#include "mail-search-plugin.h"
#include <QDebug>
#include "file-utils.h"
#include "chinese-segmentation.h"
using namespace UkuiSearch;

Some files were not shown because too many files have changed in this diff Show More