feat(search-plugin):add the ai search plugin.
This commit is contained in:
parent
1b920b4f5a
commit
2e5899b674
|
@ -97,9 +97,12 @@ const bool &BestListModel::isExpanded()
|
||||||
|
|
||||||
void BestListModel::appendInfo(const QString &pluginId, const SearchPluginIface::ResultInfo &info)
|
void BestListModel::appendInfo(const QString &pluginId, const SearchPluginIface::ResultInfo &info)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (m_resourceTypes.contains(info.resourceType)) {
|
if (m_resourceTypes.contains(info.resourceType)) {
|
||||||
return;
|
for (const auto& item : m_items) {
|
||||||
|
if (info.actionKey == item->info().actionKey && info.resourceType == item->info().resourceType) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
m_resourceTypes.append(info.resourceType);
|
m_resourceTypes.append(info.resourceType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@ set(LIBUKUI_SEARCH_PC_PKGS
|
||||||
uchardet
|
uchardet
|
||||||
kysdk-systime
|
kysdk-systime
|
||||||
kysdk-datacollect
|
kysdk-datacollect
|
||||||
kylin-ai-base)
|
kylin-ai-base
|
||||||
|
)
|
||||||
|
|
||||||
foreach(PC_LIB IN ITEMS ${LIBUKUI_SEARCH_PC_PKGS})
|
foreach(PC_LIB IN ITEMS ${LIBUKUI_SEARCH_PC_PKGS})
|
||||||
pkg_check_modules(${PC_LIB} REQUIRED IMPORTED_TARGET ${PC_LIB})
|
pkg_check_modules(${PC_LIB} REQUIRED IMPORTED_TARGET ${PC_LIB})
|
||||||
|
@ -105,6 +106,8 @@ set(LIBUKUI_SEARCH_SRC
|
||||||
searchinterface/ukui-search-task.cpp searchinterface/ukui-search-task.h
|
searchinterface/ukui-search-task.cpp searchinterface/ukui-search-task.h
|
||||||
settingsearch/settings-search-plugin.cpp settingsearch/settings-search-plugin.h
|
settingsearch/settings-search-plugin.cpp settingsearch/settings-search-plugin.h
|
||||||
websearch/web-search-plugin.cpp websearch/web-search-plugin.h
|
websearch/web-search-plugin.cpp websearch/web-search-plugin.h
|
||||||
|
aisearch/ai-search-plugin.cpp aisearch/ai-search-plugin.h
|
||||||
|
thumbnail-creator.cpp thumbnail-creator.h
|
||||||
icon-loader.cpp icon-loader.h
|
icon-loader.cpp icon-loader.h
|
||||||
data-collecter.cpp
|
data-collecter.cpp
|
||||||
data-collecter.h
|
data-collecter.h
|
||||||
|
@ -158,6 +161,7 @@ include_directories(
|
||||||
searchinterface/searchtasks
|
searchinterface/searchtasks
|
||||||
settingsearch
|
settingsearch
|
||||||
websearch
|
websearch
|
||||||
|
aisearch
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||||
|
|
|
@ -0,0 +1,340 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024, 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: baijunjie <baijunjie@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ai-search-plugin.h"
|
||||||
|
#include "file-utils.h"
|
||||||
|
#include "thumbnail-creator.h"
|
||||||
|
#include "file-indexer-config.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
using namespace UkuiSearch;
|
||||||
|
size_t AiSearchPlugin::uniqueSymbolAi = 0;
|
||||||
|
QMutex AiSearchPlugin::mutex;
|
||||||
|
static const int THUMBNAIL_HEIGHT = 247;
|
||||||
|
static const int THUMBNAIL_WIDTH = 352;
|
||||||
|
bool AiSearch::s_failed = false;
|
||||||
|
DataManagementSession AiSearch::s_session = nullptr;
|
||||||
|
QMutex AiSearch::s_sessionMutex;
|
||||||
|
|
||||||
|
AiSearchPlugin::AiSearchPlugin(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
SearchPluginIface::Actioninfo open { 0, tr("Open")};
|
||||||
|
SearchPluginIface::Actioninfo OpenPath {1, tr("Open path")};
|
||||||
|
SearchPluginIface::Actioninfo CopyPath { 2, tr("Copy Path")};
|
||||||
|
m_actionInfo << open << OpenPath << CopyPath;
|
||||||
|
m_pool.setMaxThreadCount(1);
|
||||||
|
m_thumbnailPool.setMaxThreadCount(1);
|
||||||
|
m_pool.setExpiryTimeout(1000);
|
||||||
|
m_timer = new QTimer(this);
|
||||||
|
m_timer->setInterval(500);
|
||||||
|
connect(m_timer, &QTimer::timeout, this, [ = ] {
|
||||||
|
if (FileIndexerConfig::getInstance()->isAiIndexEnable()) {
|
||||||
|
auto aiSearch = new AiSearch(m_searchResult, uniqueSymbolAi, m_keyword);
|
||||||
|
m_pool.start(aiSearch);
|
||||||
|
m_timer->stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
initDetailPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString AiSearchPlugin::name()
|
||||||
|
{
|
||||||
|
return "Ai Search";
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString AiSearchPlugin::description()
|
||||||
|
{
|
||||||
|
return tr("Ai Search");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AiSearchPlugin::getPluginName()
|
||||||
|
{
|
||||||
|
return tr("Ai Search");
|
||||||
|
}
|
||||||
|
|
||||||
|
void AiSearchPlugin::KeywordSearch(QString keyword, DataQueue<ResultInfo> *searchResult)
|
||||||
|
{
|
||||||
|
mutex.lock();
|
||||||
|
uniqueSymbolAi++;
|
||||||
|
mutex.unlock();
|
||||||
|
m_keyword = keyword;
|
||||||
|
m_searchResult = searchResult;
|
||||||
|
m_timer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AiSearchPlugin::stopSearch()
|
||||||
|
{
|
||||||
|
mutex.lock();
|
||||||
|
++uniqueSymbolAi;
|
||||||
|
mutex.unlock();
|
||||||
|
m_thumbnailPool.clear();
|
||||||
|
m_pool.clear();
|
||||||
|
m_timer->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<SearchPluginIface::Actioninfo> AiSearchPlugin::getActioninfo(int type)
|
||||||
|
{
|
||||||
|
Q_UNUSED(type)
|
||||||
|
return m_actionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AiSearchPlugin::openAction(int actionkey, QString key, int type)
|
||||||
|
{
|
||||||
|
Q_UNUSED(type)
|
||||||
|
//TODO add some return message here.
|
||||||
|
switch (actionkey) {
|
||||||
|
case 0:
|
||||||
|
if(FileUtils::openFile(key) == -1) {
|
||||||
|
QMessageBox msgBox(m_detailPage);
|
||||||
|
msgBox.setModal(true);
|
||||||
|
msgBox.addButton(tr("OK"), QMessageBox::YesRole);
|
||||||
|
msgBox.setIcon(QMessageBox::Information);
|
||||||
|
msgBox.setText(tr("Can not get a default application for opening %1.").arg(key));
|
||||||
|
msgBox.exec();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
FileUtils::openFile(key, true);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
FileUtils::copyPath(key);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *AiSearchPlugin::detailPage(const SearchPluginIface::ResultInfo &ri)
|
||||||
|
{
|
||||||
|
if(ri.actionKey == m_currentActionKey) {
|
||||||
|
return m_detailPage;
|
||||||
|
}
|
||||||
|
auto creator = new ThumbnailCreator(ri.actionKey, QSize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT), m_detailPage->window()->devicePixelRatio());
|
||||||
|
connect(creator, &ThumbnailCreator::ready, this, [&, ri](const QString& uri, const QImage &image){
|
||||||
|
if(uri != m_currentActionKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QPixmap pixmap = QPixmap::fromImage(image);
|
||||||
|
if(!pixmap.isNull()) {
|
||||||
|
m_iconLabel->setPixmap(pixmap);
|
||||||
|
m_detailLyt->setContentsMargins(8, (THUMBNAIL_HEIGHT - pixmap.height()) / 2 + 8, 16, 0);
|
||||||
|
} else {
|
||||||
|
m_iconLabel->setPixmap(ri.icon.pixmap(120, 120));
|
||||||
|
}
|
||||||
|
}, Qt::QueuedConnection);
|
||||||
|
m_thumbnailPool.start(creator);
|
||||||
|
m_iconLabel->setPixmap(ri.icon.pixmap(120, 120));
|
||||||
|
m_detailLyt->setContentsMargins(8, 50, 16, 0);
|
||||||
|
m_currentActionKey = ri.actionKey;
|
||||||
|
|
||||||
|
QFontMetrics fontMetrics = m_nameLabel->fontMetrics();
|
||||||
|
QString showName = fontMetrics.elidedText(ri.name, Qt::ElideRight, 215); //当字体长度超过215时显示为省略号
|
||||||
|
m_nameLabel->setText(FileUtils::setAllTextBold(showName));
|
||||||
|
if(QString::compare(showName, ri.name)) {
|
||||||
|
m_nameLabel->setToolTip(ri.name);
|
||||||
|
} else {
|
||||||
|
m_nameLabel->setToolTip("");
|
||||||
|
}
|
||||||
|
m_pluginLabel->setText(tr("File"));
|
||||||
|
|
||||||
|
m_pathLabel2->setText(m_pathLabel2->fontMetrics().elidedText(m_currentActionKey, Qt::ElideRight, m_pathLabel2->width()));
|
||||||
|
m_pathLabel2->setToolTip(m_currentActionKey);
|
||||||
|
QString modTimeText = ri.description.at(1).value;
|
||||||
|
m_timeLabel2->setText(modTimeText);
|
||||||
|
return m_detailPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AiSearchPlugin::initDetailPage()
|
||||||
|
{
|
||||||
|
m_detailPage = new QWidget();
|
||||||
|
m_detailPage->setFixedWidth(360);
|
||||||
|
m_detailPage->setAttribute(Qt::WA_TranslucentBackground);
|
||||||
|
m_detailLyt = new QVBoxLayout(m_detailPage);
|
||||||
|
m_detailLyt->setContentsMargins(8, 0, 16, 0);
|
||||||
|
m_iconLabel = new QLabel(m_detailPage);
|
||||||
|
m_iconLabel->setAlignment(Qt::AlignCenter);
|
||||||
|
m_iconLabel->setMinimumHeight(120);
|
||||||
|
|
||||||
|
m_nameFrame = new QFrame(m_detailPage);
|
||||||
|
m_nameFrameLyt = new QHBoxLayout(m_nameFrame);
|
||||||
|
m_nameFrame->setLayout(m_nameFrameLyt);
|
||||||
|
m_nameFrameLyt->setContentsMargins(8, 0, 0, 0);
|
||||||
|
m_nameLabel = new QLabel(m_nameFrame);
|
||||||
|
m_nameLabel->setMaximumWidth(280);
|
||||||
|
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 SeparationLine(m_detailPage);
|
||||||
|
|
||||||
|
m_pathFrame = new QFrame(m_detailPage);
|
||||||
|
m_pathFrameLyt = new QHBoxLayout(m_pathFrame);
|
||||||
|
m_pathLabel1 = new QLabel(m_pathFrame);
|
||||||
|
m_pathLabel2 = new QLabel(m_pathFrame);
|
||||||
|
m_pathLabel1->setText(tr("Path"));
|
||||||
|
m_pathLabel2->setFixedWidth(240);
|
||||||
|
m_pathLabel2->setAlignment(Qt::AlignRight);
|
||||||
|
m_pathFrameLyt->addWidget(m_pathLabel1);
|
||||||
|
m_pathFrameLyt->addStretch();
|
||||||
|
m_pathFrameLyt->addWidget(m_pathLabel2);
|
||||||
|
|
||||||
|
m_timeFrame = new QFrame(m_detailPage);
|
||||||
|
m_timeFrameLyt = new QHBoxLayout(m_timeFrame);
|
||||||
|
m_timeLabel1 = new QLabel(m_timeFrame);
|
||||||
|
m_timeLabel2 = new QLabel(m_timeFrame);
|
||||||
|
m_timeLabel2->setAlignment(Qt::AlignRight);
|
||||||
|
m_timeLabel1->setText(tr("Last time modified"));
|
||||||
|
m_timeFrameLyt->addWidget(m_timeLabel1);
|
||||||
|
m_timeFrameLyt->addStretch();
|
||||||
|
m_timeFrameLyt->addWidget(m_timeLabel2);
|
||||||
|
|
||||||
|
m_line_2 = new SeparationLine(m_detailPage);
|
||||||
|
|
||||||
|
m_actionFrame = new QFrame(m_detailPage);
|
||||||
|
m_actionFrameLyt = new QVBoxLayout(m_actionFrame);
|
||||||
|
m_actionFrameLyt->setContentsMargins(8, 0, 0, 0);
|
||||||
|
m_actionLabel1 = new ActionLabel(tr("Open"), m_currentActionKey, m_actionFrame);
|
||||||
|
m_actionLabel2 = new ActionLabel(tr("Open path"), m_currentActionKey, m_actionFrame);
|
||||||
|
m_actionLabel3 = new ActionLabel(tr("Copy path"), m_currentActionKey, m_actionFrame);
|
||||||
|
|
||||||
|
m_actionFrameLyt->addWidget(m_actionLabel1);
|
||||||
|
m_actionFrameLyt->addWidget(m_actionLabel2);
|
||||||
|
m_actionFrameLyt->addWidget(m_actionLabel3);
|
||||||
|
m_actionFrame->setLayout(m_actionFrameLyt);
|
||||||
|
|
||||||
|
m_detailLyt->addWidget(m_iconLabel);
|
||||||
|
m_detailLyt->addWidget(m_nameFrame);
|
||||||
|
m_detailLyt->addWidget(m_line_1);
|
||||||
|
m_detailLyt->addWidget(m_pathFrame);
|
||||||
|
m_detailLyt->addWidget(m_timeFrame);
|
||||||
|
m_detailLyt->addWidget(m_line_2);
|
||||||
|
m_detailLyt->addWidget(m_actionFrame);
|
||||||
|
m_detailPage->setLayout(m_detailLyt);
|
||||||
|
m_detailLyt->addStretch();
|
||||||
|
|
||||||
|
connect(m_actionLabel1, &ActionLabel::actionTriggered, [ & ](){
|
||||||
|
if(FileUtils::openFile(m_currentActionKey) == -1) {
|
||||||
|
QMessageBox msgBox(m_detailPage);
|
||||||
|
msgBox.setModal(true);
|
||||||
|
msgBox.addButton(tr("OK"), QMessageBox::YesRole);
|
||||||
|
msgBox.setIcon(QMessageBox::Information);
|
||||||
|
msgBox.setText(tr("Can not get a default application for opening %1.").arg(m_currentActionKey));
|
||||||
|
msgBox.exec();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(m_actionLabel2, &ActionLabel::actionTriggered, [ & ](){
|
||||||
|
FileUtils::openFile(m_currentActionKey, true);
|
||||||
|
});
|
||||||
|
connect(m_actionLabel3, &ActionLabel::actionTriggered, [ & ](){
|
||||||
|
FileUtils::copyPath(m_currentActionKey);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
AiSearchPlugin::~AiSearchPlugin()
|
||||||
|
{
|
||||||
|
m_pool.clear();
|
||||||
|
m_thumbnailPool.clear();
|
||||||
|
m_thumbnailPool.waitForDone();
|
||||||
|
m_pool.waitForDone();
|
||||||
|
AiSearch::destroySession();
|
||||||
|
}
|
||||||
|
|
||||||
|
AiSearch::AiSearch(DataQueue<SearchPluginIface::ResultInfo> *searchResult, size_t uniqueSymbol, const QString &keyword)
|
||||||
|
{
|
||||||
|
m_searchResult = searchResult;
|
||||||
|
m_uniqueSymbol = uniqueSymbol;
|
||||||
|
m_keyword = keyword;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AiSearch::run()
|
||||||
|
{
|
||||||
|
this->keywordSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AiSearch::keywordSearch()
|
||||||
|
{
|
||||||
|
if (!AiSearch::createSession()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QJsonObject keyword;
|
||||||
|
keyword.insert(QStringLiteral("text"), m_keyword);
|
||||||
|
char* results = nullptr;
|
||||||
|
data_management_similarity_search(s_session, QJsonDocument(keyword).toJson().data(), &results);
|
||||||
|
for (const auto &aResult : QJsonDocument::fromJson(results).array()) {
|
||||||
|
if (aResult.isObject()) {
|
||||||
|
SearchPluginIface::ResultInfo ri;
|
||||||
|
if (createResultInfo(ri, aResult.toObject().value("filepath").toString())) {
|
||||||
|
AiSearchPlugin::mutex.lock();
|
||||||
|
if (m_uniqueSymbol == AiSearchPlugin::uniqueSymbolAi) {
|
||||||
|
m_searchResult->enqueue(ri);
|
||||||
|
AiSearchPlugin::mutex.unlock();
|
||||||
|
} else {
|
||||||
|
AiSearchPlugin::mutex.unlock();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data_management_free_search_result(s_session, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AiSearch::createResultInfo(SearchPluginIface::ResultInfo &ri, const QString &path)
|
||||||
|
{
|
||||||
|
QFileInfo info(path);
|
||||||
|
if(!info.exists()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ri.icon = FileUtils::getFileIcon(QUrl::fromLocalFile(path).toString(), false);
|
||||||
|
ri.name = info.fileName().replace("\r", " ").replace("\n", " ");
|
||||||
|
ri.toolTip = info.fileName();
|
||||||
|
ri.resourceType = QStringLiteral("file");
|
||||||
|
ri.description = QVector<SearchPluginIface::DescriptionInfo>() \
|
||||||
|
<< SearchPluginIface::DescriptionInfo{"Path:", path} \
|
||||||
|
<< SearchPluginIface::DescriptionInfo{"Modified time:", info.lastModified().toString("yyyy/MM/dd hh:mm:ss")};
|
||||||
|
ri.actionKey = path;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AiSearch::~AiSearch() {}
|
||||||
|
|
||||||
|
bool AiSearch::createSession() {
|
||||||
|
QMutexLocker locker(&s_sessionMutex);
|
||||||
|
if (!s_session || s_failed) {
|
||||||
|
if (data_management_create_session(&s_session, DataManagementType::SYS_SEARCH, getuid()) != DataManagementResult::DATA_MANAGEMENT_SUCCESS) {
|
||||||
|
s_failed = true;
|
||||||
|
qWarning() << "===Create data management session failed!===" << s_session;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AiSearch::destroySession() {
|
||||||
|
if (data_management_destroy_session(s_session) != DataManagementResult::DATA_MANAGEMENT_SUCCESS) {
|
||||||
|
qWarning() << "===fail to destroy session===";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024, 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: baijunjie <baijunjie@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UKUI_SEARCH_AISEARCHPLUGIN_H
|
||||||
|
#define UKUI_SEARCH_AISEARCHPLUGIN_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QThreadPool>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QAction>
|
||||||
|
#include <QDBusInterface>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "action-label.h"
|
||||||
|
#include "separation-line.h"
|
||||||
|
#include "search-plugin-iface.h"
|
||||||
|
#include "icon-loader.h"
|
||||||
|
#include "kylin-ai/ai-base/datamanagement.h"
|
||||||
|
|
||||||
|
namespace UkuiSearch {
|
||||||
|
class LIBSEARCH_EXPORT AiSearchPlugin : public QObject, public SearchPluginIface {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit AiSearchPlugin(QObject *parent = nullptr);
|
||||||
|
~AiSearchPlugin() override;
|
||||||
|
PluginType pluginType() override { return PluginType::SearchPlugin; }
|
||||||
|
const QString name() override;
|
||||||
|
const QString description() override;
|
||||||
|
const QIcon icon() override { return IconLoader::loadIconQt(""); }
|
||||||
|
void setEnable(bool enable) override { m_enable = enable; }
|
||||||
|
bool isEnable() override { return m_enable; }
|
||||||
|
QString getPluginName() override;
|
||||||
|
|
||||||
|
void KeywordSearch(QString keyword, DataQueue<ResultInfo> *searchResult) override;
|
||||||
|
|
||||||
|
void stopSearch() override;
|
||||||
|
|
||||||
|
QList<SearchPluginIface::Actioninfo> getActioninfo(int type) override;
|
||||||
|
|
||||||
|
void openAction(int actionkey, QString key, int type) override;
|
||||||
|
|
||||||
|
QWidget *detailPage(const ResultInfo &ri) override;
|
||||||
|
|
||||||
|
static size_t uniqueSymbolAi;
|
||||||
|
static QMutex mutex;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initDetailPage();
|
||||||
|
QString m_currentActionKey;
|
||||||
|
QWidget *m_detailPage;
|
||||||
|
QVBoxLayout *m_detailLyt = nullptr;
|
||||||
|
QLabel *m_iconLabel = nullptr;
|
||||||
|
QFrame *m_nameFrame = nullptr;
|
||||||
|
QHBoxLayout *m_nameFrameLyt = nullptr;
|
||||||
|
QLabel *m_nameLabel = nullptr;
|
||||||
|
QLabel *m_pluginLabel = nullptr;
|
||||||
|
SeparationLine *m_line_1 = nullptr;
|
||||||
|
QFrame *m_pathFrame = nullptr;
|
||||||
|
QLabel *m_pathLabel1 = nullptr;
|
||||||
|
QLabel *m_pathLabel2 = nullptr;
|
||||||
|
QHBoxLayout *m_pathFrameLyt = nullptr;
|
||||||
|
QFrame *m_timeFrame = nullptr;
|
||||||
|
QLabel *m_timeLabel1 = nullptr;
|
||||||
|
QLabel *m_timeLabel2 = nullptr;
|
||||||
|
QHBoxLayout *m_timeFrameLyt = nullptr;
|
||||||
|
|
||||||
|
SeparationLine *m_line_2 = nullptr;
|
||||||
|
QFrame *m_actionFrame = nullptr;
|
||||||
|
QVBoxLayout *m_actionFrameLyt = nullptr;
|
||||||
|
ActionLabel *m_actionLabel1 = nullptr;
|
||||||
|
ActionLabel *m_actionLabel2 = nullptr;
|
||||||
|
ActionLabel *m_actionLabel3 = nullptr;
|
||||||
|
|
||||||
|
QVBoxLayout * m_actionLyt = nullptr;
|
||||||
|
|
||||||
|
bool m_enable = true;
|
||||||
|
QList<SearchPluginIface::Actioninfo> m_actionInfo;
|
||||||
|
QThreadPool m_pool;
|
||||||
|
QThreadPool m_thumbnailPool;
|
||||||
|
DataManagementSession m_session;
|
||||||
|
QTimer *m_timer = nullptr;
|
||||||
|
QString m_keyword;
|
||||||
|
DataQueue<ResultInfo> *m_searchResult;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AiSearch : public QRunnable {
|
||||||
|
public:
|
||||||
|
explicit AiSearch(DataQueue<SearchPluginIface::ResultInfo> *searchResult, size_t uniqueSymbol, const QString& keyword);
|
||||||
|
~AiSearch() override;
|
||||||
|
static bool createSession();
|
||||||
|
static void destroySession();
|
||||||
|
static DataManagementSession s_session;
|
||||||
|
static bool s_failed;
|
||||||
|
static QMutex s_sessionMutex;
|
||||||
|
protected:
|
||||||
|
void run() override;
|
||||||
|
private:
|
||||||
|
void keywordSearch();
|
||||||
|
bool createResultInfo(SearchPluginIface::ResultInfo &ri, const QString& path);
|
||||||
|
|
||||||
|
DataQueue<SearchPluginIface::ResultInfo> *m_searchResult = nullptr;
|
||||||
|
size_t m_uniqueSymbol;
|
||||||
|
QString m_keyword;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif //UKUI_SEARCH_AISEARCHPLUGIN_H
|
|
@ -403,7 +403,7 @@ bool AppSearchPlugin::installAppAction(const QString & name)
|
||||||
//AppSearch::AppSearch(DataQueue<SearchPluginIface::ResultInfo> *searchResult, DataQueue<ResultItem>* appSearchResults, UkuiSearchTask *appSearchTask, QString keyword, size_t uniqueSymbol)
|
//AppSearch::AppSearch(DataQueue<SearchPluginIface::ResultInfo> *searchResult, DataQueue<ResultItem>* appSearchResults, UkuiSearchTask *appSearchTask, QString keyword, size_t uniqueSymbol)
|
||||||
//{
|
//{
|
||||||
// this->setAutoDelete(true);
|
// this->setAutoDelete(true);
|
||||||
// m_search_result = searchResult;
|
// m_searchResult = searchResult;
|
||||||
// m_appSearchResults = appSearchResults;
|
// m_appSearchResults = appSearchResults;
|
||||||
// m_appSearchTask = appSearchTask;
|
// m_appSearchTask = appSearchTask;
|
||||||
// m_appSearchTask->clearKeyWords();
|
// m_appSearchTask->clearKeyWords();
|
||||||
|
@ -440,7 +440,7 @@ bool AppSearchPlugin::installAppAction(const QString & name)
|
||||||
//// m_appSearchResults->clear();
|
//// m_appSearchResults->clear();
|
||||||
//// break;
|
//// break;
|
||||||
//// }
|
//// }
|
||||||
// m_search_result->enqueue(ri);
|
// m_searchResult->enqueue(ri);
|
||||||
// } else {
|
// } else {
|
||||||
// is_empty = true;
|
// is_empty = true;
|
||||||
// }
|
// }
|
||||||
|
@ -464,7 +464,7 @@ bool AppSearchPlugin::installAppAction(const QString & name)
|
||||||
|
|
||||||
//bool AppSearch::isUniqueSymbolChanged()
|
//bool AppSearch::isUniqueSymbolChanged()
|
||||||
//{
|
//{
|
||||||
// QMutexLocker locker(&AppSearchPlugin::m_mutex);
|
// QMutexLocker locker(&AppSearchPlugin::mutex);
|
||||||
// if (m_uniqueSymbol != AppSearchPlugin::uniqueSymbol) {
|
// if (m_uniqueSymbol != AppSearchPlugin::uniqueSymbol) {
|
||||||
// qDebug() << "uniqueSymbol changged, app search finished!";
|
// qDebug() << "uniqueSymbol changged, app search finished!";
|
||||||
// return true;
|
// return true;
|
||||||
|
|
|
@ -110,7 +110,7 @@ private:
|
||||||
// size_t m_uniqueSymbol;
|
// size_t m_uniqueSymbol;
|
||||||
// UkuiSearchTask *m_appSearchTask = nullptr;
|
// UkuiSearchTask *m_appSearchTask = nullptr;
|
||||||
// DataQueue<ResultItem>* m_appSearchResults = nullptr;
|
// DataQueue<ResultItem>* m_appSearchResults = nullptr;
|
||||||
// DataQueue<SearchPluginIface::ResultInfo> *m_search_result = nullptr;
|
// DataQueue<SearchPluginIface::ResultInfo> *m_searchResult = nullptr;
|
||||||
|
|
||||||
//};
|
//};
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "libkydate.h"
|
#include "libkydate.h"
|
||||||
#include "data-collecter.h"
|
#include "data-collecter.h"
|
||||||
#include "file-reader.h"
|
#include "file-reader.h"
|
||||||
|
#include "thumbnail-creator.h"
|
||||||
|
|
||||||
#define OCR_ICONLABLE_WITH 352
|
#define OCR_ICONLABLE_WITH 352
|
||||||
#define OCR_ICONLABLE_HEIGHT 247
|
#define OCR_ICONLABLE_HEIGHT 247
|
||||||
|
@ -799,16 +800,4 @@ void FileContentSearchPlugin::initDetailPage()
|
||||||
// return nullptr;
|
// return nullptr;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
ThumbnailCreator::ThumbnailCreator(const QString &url, const QSize &targetSize, qreal dpr, QObject *parent): QObject(parent)
|
|
||||||
{
|
|
||||||
setAutoDelete(true);
|
|
||||||
m_url = url;
|
|
||||||
m_targetSize = targetSize;
|
|
||||||
m_dpr = dpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThumbnailCreator::run()
|
|
||||||
{
|
|
||||||
Q_EMIT ready(m_url, FileReader::getInstance()->getThumbnail(m_url, m_targetSize, m_dpr));
|
|
||||||
}
|
|
||||||
#include "file-search-plugin.moc"
|
#include "file-search-plugin.moc"
|
||||||
|
|
|
@ -205,23 +205,6 @@ private:
|
||||||
QThreadPool m_pool;
|
QThreadPool m_pool;
|
||||||
QThreadPool m_thumbnailPool;
|
QThreadPool m_thumbnailPool;
|
||||||
};
|
};
|
||||||
class ThumbnailCreator : public QObject, public QRunnable
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit ThumbnailCreator(const QString &url, const QSize &targetSize, qreal dpr, QObject *parent = nullptr);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void run() override;
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void ready(QString url, const QImage &image);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString m_url;
|
|
||||||
QSize m_targetSize;
|
|
||||||
qreal m_dpr;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "settings-search-plugin.h"
|
#include "settings-search-plugin.h"
|
||||||
#include "note-search-plugin.h"
|
#include "note-search-plugin.h"
|
||||||
#include "web-search-plugin.h"
|
#include "web-search-plugin.h"
|
||||||
|
#include "ai-search-plugin.h"
|
||||||
|
|
||||||
#define PLUGIN_ORDER_SETTINGS QDir::homePath() + "/.config/org.ukui/ukui-search/ukui-search-plugin-order.conf"
|
#define PLUGIN_ORDER_SETTINGS QDir::homePath() + "/.config/org.ukui/ukui-search/ukui-search-plugin-order.conf"
|
||||||
#define PLUGINS_INFO_GROUP "PluginsInfo"
|
#define PLUGINS_INFO_GROUP "PluginsInfo"
|
||||||
|
@ -34,6 +35,8 @@
|
||||||
#define PLUGIN_EXTERNAL_VALUE "External"
|
#define PLUGIN_EXTERNAL_VALUE "External"
|
||||||
#define PLUGIN_PATH_VALUE "Path"
|
#define PLUGIN_PATH_VALUE "Path"
|
||||||
#define PLUGIN_FIX_VALUE "FixPos"
|
#define PLUGIN_FIX_VALUE "FixPos"
|
||||||
|
static const QString SETTINGS_VERSION_KEY = "Version";
|
||||||
|
static const QString SETTINGS_VERSION = "1.0";
|
||||||
|
|
||||||
using namespace UkuiSearch;
|
using namespace UkuiSearch;
|
||||||
|
|
||||||
|
@ -42,6 +45,7 @@ SearchPluginManager::SearchPluginManager(QObject *parent)
|
||||||
{
|
{
|
||||||
Q_UNUSED(parent)
|
Q_UNUSED(parent)
|
||||||
initOrderSettings();
|
initOrderSettings();
|
||||||
|
registerPlugin(new AiSearchPlugin);
|
||||||
registerPlugin(new AppSearchPlugin);
|
registerPlugin(new AppSearchPlugin);
|
||||||
registerPlugin(new NoteSearchPlugin);
|
registerPlugin(new NoteSearchPlugin);
|
||||||
registerPlugin(new SettingsSearchPlugin);
|
registerPlugin(new SettingsSearchPlugin);
|
||||||
|
@ -458,9 +462,16 @@ SearchPluginManager::~SearchPluginManager()
|
||||||
void SearchPluginManager::initOrderSettings()
|
void SearchPluginManager::initOrderSettings()
|
||||||
{
|
{
|
||||||
m_orderSettings = new QSettings(PLUGIN_ORDER_SETTINGS, QSettings::IniFormat, this);
|
m_orderSettings = new QSettings(PLUGIN_ORDER_SETTINGS, QSettings::IniFormat, this);
|
||||||
|
bool needRefresh(false);
|
||||||
|
|
||||||
m_orderSettings->beginGroup(PLUGINS_INFO_GROUP);
|
m_orderSettings->beginGroup(PLUGINS_INFO_GROUP);
|
||||||
if (m_orderSettings->childGroups().isEmpty()) {
|
if (m_orderSettings->childGroups().isEmpty()) {
|
||||||
|
needRefresh = true;
|
||||||
|
} else if (m_orderSettings->value(SETTINGS_VERSION_KEY).toString() != SETTINGS_VERSION) {
|
||||||
|
m_orderSettings->setValue(SETTINGS_VERSION_KEY, SETTINGS_VERSION);
|
||||||
|
needRefresh = true;
|
||||||
|
}
|
||||||
|
if (needRefresh) {
|
||||||
bool isFixed(false);
|
bool isFixed(false);
|
||||||
for (int i = 0; i < m_defaultPluginOrder.size(); i++) {
|
for (int i = 0; i < m_defaultPluginOrder.size(); i++) {
|
||||||
QString pluginName = m_defaultPluginOrder.at(i);
|
QString pluginName = m_defaultPluginOrder.at(i);
|
||||||
|
@ -477,4 +488,4 @@ void SearchPluginManager::initOrderSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_orderSettings->endGroup();
|
m_orderSettings->endGroup();
|
||||||
}
|
}
|
|
@ -32,6 +32,7 @@ class SearchPluginManager : public QObject
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
QStringList m_defaultPluginOrder = {
|
QStringList m_defaultPluginOrder = {
|
||||||
|
"Ai Search",
|
||||||
"Applications Search",
|
"Applications Search",
|
||||||
"Note Search",
|
"Note Search",
|
||||||
"Settings Search",
|
"Settings Search",
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024, 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: baijunjie <baijunjie@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "thumbnail-creator.h"
|
||||||
|
#include "file-reader.h"
|
||||||
|
|
||||||
|
using namespace UkuiSearch;
|
||||||
|
|
||||||
|
ThumbnailCreator::ThumbnailCreator(const QString &url, const QSize &targetSize, qreal dpr, QObject *parent): QObject(parent)
|
||||||
|
{
|
||||||
|
setAutoDelete(true);
|
||||||
|
m_url = url;
|
||||||
|
m_targetSize = targetSize;
|
||||||
|
m_dpr = dpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThumbnailCreator::run()
|
||||||
|
{
|
||||||
|
Q_EMIT ready(m_url, FileReader::getInstance()->getThumbnail(m_url, m_targetSize, m_dpr));
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024, 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: baijunjie <baijunjie@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UKUI_SEARCH_THUMBNAILCREATOR_H
|
||||||
|
#define UKUI_SEARCH_THUMBNAILCREATOR_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QRunnable>
|
||||||
|
#include <QSize>
|
||||||
|
|
||||||
|
namespace UkuiSearch {
|
||||||
|
class ThumbnailCreator : public QObject, public QRunnable
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ThumbnailCreator(const QString &url, const QSize &targetSize, qreal dpr, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run() override;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void ready(QString url, const QImage &image);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_url;
|
||||||
|
QSize m_targetSize;
|
||||||
|
qreal m_dpr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //UKUI_SEARCH_THUMBNAILCREATOR_H
|
Loading…
Reference in New Issue