forked from openkylin/ukui-search
Compare commits
66 Commits
debian/uns
...
upstream
Author | SHA1 | Date |
---|---|---|
iaom | 7e296c325a | |
iaom | d1bf50859a | |
JunjieBai | 3d13080b4c | |
JunjieBai | a128cfb5b7 | |
iaom | c871929ef1 | |
JunjieBai | 3b8c35c2c2 | |
JunjieBai | 5157a6be6c | |
JunjieBai | 322e8d95ee | |
iaom | 255518c245 | |
iaom | ed768ff48f | |
JunjieBai | e52bc8ca76 | |
iaom | 02dfef8627 | |
JunjieBai | c91a74c66d | |
iaom | df3332046f | |
iaom | f5eaf99f6f | |
JunjieBai | 35818d321e | |
iaom | 94ea037203 | |
iaom | d9db5ff896 | |
iaom | e7676c887a | |
iaom | e5e62cd3f7 | |
JunjieBai | c5304dfe94 | |
jixiaoxu | 12d5e76cc5 | |
iaom | 37e3de3cee | |
iaom | 80320ab9f2 | |
iaom | 543b766351 | |
iaom | b172baca45 | |
JunjieBai | 0e7d204f11 | |
JunjieBai | b59d0a57d8 | |
iaom | 65060337de | |
JunjieBai | 8f03c44ef4 | |
JunjieBai | fbd391d110 | |
iaom | 5481dd7ed8 | |
JunjieBai | eb0b77035d | |
iaom | b03fb44f6c | |
iaom | ff0dd3384a | |
baijunjie | 29e5ee6767 | |
iaom | 6911e159ad | |
iaom | a2514a1d98 | |
JunjieBai | 5f4e172c0d | |
iaom | 7babaf3147 | |
iaom | 031ce8bbd8 | |
iaom | 7e670163fa | |
JunjieBai | 610210a9a3 | |
iaom | 993c8e30ea | |
JunjieBai | e09044dfee | |
iaom | 366201ddf9 | |
iaom | 6a96a0e2f0 | |
iaom | 87f4170a5e | |
JunjieBai | ea3913cb5b | |
JunjieBai | 91b455341d | |
jixiaoxu | 2760b30a2a | |
jixiaoxu | 0725b5b097 | |
iaom | 308b9b642f | |
JunjieBai | 4a98056c06 | |
iaom | d354773177 | |
JunjieBai | bf22f0e150 | |
JunjieBai | 0e267ac29c | |
JunjieBai | f9a638c05b | |
iaom | b1a8486bd1 | |
iaom | 498147414d | |
iaom | e53d13c54b | |
iaom | 9b835b9686 | |
JunjieBai | 04a9cb487e | |
JunjieBai | 68a1fc4f43 | |
JunjieBai | 7f2267d72a | |
JunjieBai | 738f116b83 |
102
README.md
102
README.md
|
@ -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) 。建立索引时,搜索会对常用的文本文件进行解析,提取关键词存入数据库。搜索时,用户输入的文本也会被提取关键词,和数据库中的关键词进行匹配, 所以文本索引并不能保证你搜索一个文本文件里的任意内容都能搜出这个文件,这也不是普遍的应用场景。搜索输入的文本中必须要包含【关键词】才可以。比如你搜索一个‘的’,由于‘的’并不是任何文件的关键词,所以并不会有搜索到任何文件。事实上,我们有一个停用词词库,专门用来排除‘我’‘的’于是‘等等基本上在每个文档都会出现的一些无用词。目前,搜索支持解析的文件格式有:docx,pptx, xlsx, txt(大部分编码格式), doc, dot, wps, ppt, pps, dps, et, xls, pdf,uof,uot,uos,uop,ofd以上格式均不支持加密文件的解析,此外,文件索引支持图片ocr提取文字,所以你也可以通过图片中的文字搜索到图片(就像文档一样),支持的图片格式:png,bmp,gif,tif,tiff,webp,jpe,jpg,jpeg。
|
||||
|
||||
> 注意:应用的.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);
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
> 接口使用注意事项:
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,8 +353,9 @@ 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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,10 +48,10 @@ void SearchResultManager::stopSearch()
|
|||
{
|
||||
if(m_getResultThread->isRunning()) {
|
||||
m_getResultThread->stop();
|
||||
SearchPluginIface *plugin = SearchPluginManager::getInstance()->getPlugin(m_pluginId);
|
||||
plugin->stopSearch();
|
||||
qDebug() << m_pluginId << "stopped";
|
||||
}
|
||||
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 {
|
||||
this->requestInterruption();
|
||||
}
|
||||
msleep(100);
|
||||
} else {
|
||||
timer->stop();
|
||||
deadline.setRemainingTime(3000);
|
||||
Q_EMIT gotResultInfo(oneResult);
|
||||
}
|
||||
|
||||
if(timer->isActive() && timer->remainingTime() < 0.01 && m_resultQueue->isEmpty()) {
|
||||
this->requestInterruption();
|
||||
}
|
||||
}
|
||||
delete m_timer;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
@ -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";
|
||||
this->appWidgetUpdate();
|
||||
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;
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <QSyntaxHighlighter>
|
||||
#include <QTextCharFormat>
|
||||
#include <QRegExp>
|
||||
#include "global-settings.h"
|
||||
|
||||
namespace UkuiSearch {
|
||||
class HightLightEffectHelper : public QSyntaxHighlighter
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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}});
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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,36 +173,35 @@ 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();
|
||||
}
|
||||
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");
|
||||
SearchResultPropertyMap data = oneResult.getAllValue();
|
||||
if(oneResult.getSearchId() == 0 && oneResult.getItemKey().isEmpty() && data.isEmpty()) {
|
||||
if(deadline.remainingTime()) {
|
||||
msleep(100);
|
||||
} 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();
|
||||
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();
|
||||
}
|
||||
m_searchResult->enqueue(ri);
|
||||
}
|
||||
|
||||
if(m_timer->isActive() && m_timer->remainingTime() < 0.01 && m_appSearchResults->isEmpty()) {
|
||||
this->requestInterruption();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#include "app-info-table.h"
|
|
@ -1 +0,0 @@
|
|||
#include "search-controller.h"
|
|
@ -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"
|
||||
|
|
|
@ -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!";
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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文件解析
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
addWatch(path);
|
||||
bfs.enqueue(path);
|
||||
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";
|
||||
Q_EMIT modified(path);
|
||||
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";
|
||||
// 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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -51,6 +51,11 @@ public:
|
|||
* @return 是否启动文本内容索引
|
||||
*/
|
||||
bool isContentIndexEnable();
|
||||
/**
|
||||
* @brief isFuzzySearchEnable
|
||||
* @return 是否启动模糊搜索
|
||||
*/
|
||||
bool isFuzzySearchEnable();
|
||||
/**
|
||||
* @brief isOCREnable
|
||||
* @return 是否激活OCR功能(文件内容索引)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -39,7 +39,8 @@ public:
|
|||
Initializing = 0,
|
||||
Error = 1,
|
||||
Ready = 2,
|
||||
Updating = 3
|
||||
Updating = 3,
|
||||
Off = 4
|
||||
};
|
||||
Q_ENUM(State)
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
contentDb.removeDocument(file.path());
|
||||
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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
blockList.append(DirWatcher::getDirWatcher()->blackListOfDir(path));
|
||||
bfs.enqueue(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);
|
||||
SearchManager::m_mutexDir.unlock();
|
||||
} else {
|
||||
SearchManager::m_mutexDir.unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (i.isFile() && m_value == FILE_SEARCH_VALUE) {
|
||||
SearchPluginIface::ResultInfo ri;
|
||||
if(SearchManager::creatResultInfo(ri,i.absoluteFilePath())) {
|
||||
SearchManager::m_mutexFile.lock();
|
||||
if(m_uniqueSymbol == SearchManager::uniqueSymbolFile) {
|
||||
m_searchResult->enqueue(ri);
|
||||
SearchManager::m_mutexFile.unlock();
|
||||
} else {
|
||||
SearchManager::m_mutexFile.unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
SearchManager::m_mutexDir.lock();
|
||||
if(m_uniqueSymbol == SearchManager::uniqueSymbolDir) {
|
||||
match(i);
|
||||
SearchManager::m_mutexDir.unlock();
|
||||
} else {
|
||||
SearchManager::m_mutexDir.unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,info.absoluteFilePath())) {
|
||||
m_searchResult->enqueue(ri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) 2022, KylinSoft Co., Ltd.
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -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
Loading…
Reference in New Issue