Merge branch 'ukss-dev0510' into 'ukss-dev'
新增搜索服务应用数据库接口;新增搜索应用插件功能;搜索服务接口新增设置返回数据结构(应用搜索插件);目录结构优化等; See merge request kylin-desktop/ukui-search!329
This commit is contained in:
commit
1939d5b865
|
@ -0,0 +1,16 @@
|
|||
[Desktop Entry]
|
||||
Name=ukui-search-app-data-service
|
||||
Name[zh_CN]=应用数据搜索服务
|
||||
GenericName=ukui-search-app-data-service
|
||||
GenericName[zh_CN]=应用数据搜索服务
|
||||
Comment=ukui-search-app-data-service
|
||||
Comment[zh_CN]=应用数据搜索服务
|
||||
Exec=/usr/bin/ukui-search-app-data-service %U
|
||||
Type=Application
|
||||
Icon=kylin-search
|
||||
X-UKUI-AutoRestart=true
|
||||
OnlyShowIn=UKUI
|
||||
NoDisplay=true
|
||||
X-UKUI-Autostart-Phase=Application
|
||||
Terminal=false
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
#include <QPushButton>
|
||||
#include <QScrollArea>
|
||||
#include <QTimer>
|
||||
#include <libsearch.h>
|
||||
#include "libsearch.h"
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
|
||||
#include "xatom-helper.h"
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
QT += core gui dbus KWindowSystem xml x11extras
|
||||
QT += core gui dbus KWindowSystem xml x11extras sql
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
#include "app-db-manager.h"
|
||||
#include <QDir>
|
||||
#include <QSqlError>
|
||||
#include <QSqlQuery>
|
||||
#include <QDebug>
|
||||
#include <QApplication>
|
||||
using namespace UkuiSearch;
|
||||
#define APP_DATABASE_PATH QDir::homePath()+"/.config/org.ukui/ukui-search/appdata/"+"app-info.db"
|
||||
#define CONNECTION_NAME QLatin1String("ukss-appdb-connection")
|
||||
static AppDBManager *global_instance = nullptr;
|
||||
AppDBManager *AppDBManager::getInstance()
|
||||
{
|
||||
if (!global_instance) {
|
||||
global_instance = new AppDBManager();
|
||||
}
|
||||
return global_instance;
|
||||
}
|
||||
AppDBManager::AppDBManager(QObject *parent) : QObject(parent), m_database(QSqlDatabase::addDatabase("QSQLITE",CONNECTION_NAME))
|
||||
{
|
||||
}
|
||||
|
||||
AppDBManager::~AppDBManager()
|
||||
{
|
||||
|
||||
}
|
||||
void AppDBManager::initDateBaseConnection()
|
||||
{
|
||||
if(!m_database.isValid()) {
|
||||
qWarning() << m_database.lastError();
|
||||
QApplication::quit();
|
||||
}
|
||||
m_database.setDatabaseName(APP_DATABASE_PATH);
|
||||
if(!m_database.open()) {
|
||||
qWarning() << m_database.lastError();
|
||||
QApplication::quit();
|
||||
}
|
||||
//todo: 建表
|
||||
}
|
||||
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
#ifndef APPDBMANAGER_H
|
||||
#define APPDBMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSqlDatabase>
|
||||
namespace UkuiSearch {
|
||||
/**
|
||||
* @brief The AppDBManager class
|
||||
* 功能:1.遍历并且监听desktop文件目录,建立并且维护应用信息数据库。
|
||||
* 2.监听应用安装,打开事件,收藏等事件,更新数据库
|
||||
*/
|
||||
|
||||
class AppDBManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static AppDBManager *getInstance();
|
||||
void initDateBaseConnection();
|
||||
private:
|
||||
explicit AppDBManager(QObject *parent = nullptr);
|
||||
~AppDBManager();
|
||||
QSqlDatabase m_database;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // APPDBMANAGER_H
|
|
@ -1,7 +1,9 @@
|
|||
#ifndef APPINFOTABLEPRIVATE_H
|
||||
#define APPINFOTABLEPRIVATE_H
|
||||
#include <QObject>
|
||||
#include <QSqlDatabase>
|
||||
#include <app-info-table.h>
|
||||
|
||||
namespace UkuiSearch {
|
||||
class AppInfoTablePrivate : public QObject
|
||||
{
|
||||
|
@ -11,8 +13,45 @@ public:
|
|||
AppInfoTablePrivate(AppInfoTablePrivate &) = delete;
|
||||
AppInfoTablePrivate &operator =(const AppInfoTablePrivate &) = delete;
|
||||
|
||||
bool setAppFavoritesState(QString &desktopfp, size_t num);
|
||||
bool setAppTopState(QString &desktopfp, size_t num);
|
||||
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 getAppCategory(QString &desktopfp, QString &category);
|
||||
|
||||
bool getAppInfoResults(QVector<AppInfoTable::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 addAppShortcut2Desktop(QString &desktopfp);
|
||||
bool addAppShortcut2Panel(QString &desktopfp);
|
||||
|
||||
bool getInstallAppMap(QMultiMap<QString, QStringList> &installAppMap);
|
||||
bool searchInstallApp(QString &keyWord, QStringList &installAppInfoRes);
|
||||
bool searchInstallApp(QStringList &keyWord, QStringList &installAppInfoRes);
|
||||
|
||||
bool uninstallApp(QString &desktopfp);
|
||||
|
||||
QString lastError(void) const;
|
||||
|
||||
private:
|
||||
AppInfoTable *q;
|
||||
~AppInfoTablePrivate();
|
||||
void initDateBaseConnection();
|
||||
void openDataBase();
|
||||
void closeDataBase();
|
||||
|
||||
AppInfoTable *q = nullptr;
|
||||
QSqlDatabase *m_database = nullptr;
|
||||
QString m_ConnectionName;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,790 @@
|
|||
#include <QDebug>
|
||||
#include <QtGlobal>
|
||||
#include <string>
|
||||
#include <QStandardPaths>
|
||||
#include <QProcess>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusReply>
|
||||
#include <QFileInfo>
|
||||
#include <QTime>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include <QApplication>
|
||||
#include <qt5xdg/XdgDesktopFile>
|
||||
#include "app-info-table.h"
|
||||
#include "app-info-table-private.h"
|
||||
#include "../ukui-search-app-data-service/app-db-common-defines.h"
|
||||
|
||||
using namespace UkuiSearch;
|
||||
AppInfoTablePrivate::AppInfoTablePrivate(AppInfoTable *parent) : QObject(parent), q(parent)
|
||||
AppInfoTablePrivate::AppInfoTablePrivate(AppInfoTable *parent) : QObject(parent), q(parent), m_database(new QSqlDatabase)
|
||||
{
|
||||
while(1) {
|
||||
srand(QTime(0,0,0).secsTo(QTime::currentTime()));
|
||||
m_ConnectionName = QString::fromStdString(std::to_string(rand()));//随机生产链接
|
||||
if (!QSqlDatabase::contains(m_ConnectionName))
|
||||
break;
|
||||
}
|
||||
qDebug() << "App info database currunt connection name:" << m_ConnectionName;
|
||||
this->openDataBase();
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::setAppFavoritesState(QString &desktopfp, size_t num)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction()) {
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("UPDATE appInfo SET MODIFYED_TIME='%0', FAVORITES=%1 WHERE DESKTOP_FILE_PATH='%2'")
|
||||
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
|
||||
.arg(num)
|
||||
.arg(desktopfp);
|
||||
if (!sql.exec(cmd)) {
|
||||
qWarning() << "Set app favorites state failed!" << 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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::setAppTopState(QString &desktopfp, size_t num)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction()) {
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("UPDATE appInfo SET MODIFYED_TIME='%0', TOP=%1 WHERE DESKTOP_FILE_PATH='%2'")
|
||||
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
|
||||
.arg(num)
|
||||
.arg(desktopfp);
|
||||
if (!sql.exec(cmd)) {
|
||||
qWarning() << "Set app favorites state failed!" << 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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::setAppLaunchTimes(QString &desktopfp, size_t num)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction()) {
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("UPDATE appInfo SET MODIFYED_TIME='%0', LAUNCH_TIMES=%1, LAUNCHED=%2 WHERE DESKTOP_FILE_PATH='%3'")
|
||||
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
|
||||
.arg(num)
|
||||
.arg(1)
|
||||
.arg(desktopfp);
|
||||
if (!sql.exec(cmd)) {
|
||||
qWarning() << "Set app favorites state failed!" << 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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::updateAppLaunchTimes(QString &desktopfp)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction()) {
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("SELECT LAUNCH_TIMES FROM appInfo WHERE DESKTOP_FILE_PATH='%1'").arg(desktopfp);
|
||||
if (sql.exec(cmd)) {
|
||||
if (sql.next()) {
|
||||
cmd = QString("UPDATE appInfo SET MODIFYED_TIME='%0', LAUNCH_TIMES=%1, LAUNCHED=%2 WHERE DESKTOP_FILE_PATH='%3'")
|
||||
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
|
||||
.arg(sql.value(0).toInt() + 1)
|
||||
.arg(1)
|
||||
.arg(desktopfp);
|
||||
if (!sql.exec(cmd)) {
|
||||
qWarning() << "Set app favorites state failed!" << m_database->lastError();
|
||||
res = false;
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Failed to exec next!" << cmd;
|
||||
res = false;
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Failed to exec:" << cmd;
|
||||
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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::setAppLockState(QString &desktopfp, size_t num)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction()) {
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("UPDATE appInfo SET MODIFYED_TIME='%0', LOCK=%1 WHERE DESKTOP_FILE_PATH='%2'")
|
||||
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
|
||||
.arg(num)
|
||||
.arg(desktopfp);
|
||||
if (!sql.exec(cmd)) {
|
||||
qWarning() << "Set app favorites state failed!" << 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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::getAllAppDesktopList(QStringList &list)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction()) {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::getFavoritesAppList(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 WHERE FAVORITES!=0 ORDER BY FAVORITES");
|
||||
int count = 0;
|
||||
if (sql.exec(cmd)) {
|
||||
while (sql.next()) {
|
||||
list.append(sql.value(0).toString());
|
||||
cmd = QString("UPDATE appInfo SET FAVORITES=%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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::getTopAppList(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 WHERE TOP!=0 ORDER BY TOP");
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::getAppCategory(QString &desktopfp, QString &category)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction()) {
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("SELECT CATEGORY FROM appInfo WHERE DESKTOP_FILE_PATH='%0'")
|
||||
.arg(desktopfp);
|
||||
if (sql.exec(cmd)) {
|
||||
if (sql.next()) {
|
||||
category = sql.value(0).toString();
|
||||
} else {
|
||||
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database->lastError();
|
||||
res = false;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::getAppInfoResults(QVector<AppInfoTable::AppInfoResult> &appInfoResults)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction()) {
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON,CATEGORY,TOP,FAVORITES,LAUNCH_TIMES,LOCK FROM appInfo");
|
||||
if (sql.exec(cmd)) {
|
||||
while (sql.next()) {
|
||||
AppInfoTable::AppInfoResult result;
|
||||
result.desktopPath = sql.value(0).toString();
|
||||
result.appLocalName = sql.value(1).toString();
|
||||
result.iconName = sql.value(2).toString();
|
||||
result.category = sql.value(3).toString();
|
||||
result.top = sql.value(4).toInt();
|
||||
result.favorate = sql.value(5).toInt();
|
||||
result.launchTimes = sql.value(6).toInt();
|
||||
result.lock = sql.value(7).toInt();
|
||||
appInfoResults.append(std::move(result));
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::getAppLockState(QString &desktopfp, size_t &num)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction()) {
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("SELECT LOCK FROM appInfo WHERE DESKTOP_FILE_PATH='%0'")
|
||||
.arg(desktopfp);
|
||||
if (sql.exec(cmd)) {
|
||||
if (sql.next()) {
|
||||
num = sql.value(0).toInt();
|
||||
} else {
|
||||
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database->lastError();
|
||||
res = false;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::getAppTopState(QString &desktopfp, size_t &num)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction()) {
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("SELECT TOP FROM appInfo WHERE DESKTOP_FILE_PATH='%0'")
|
||||
.arg(desktopfp);
|
||||
if (sql.exec(cmd)) {
|
||||
if (sql.next()) {
|
||||
num = sql.value(0).toInt();
|
||||
} else {
|
||||
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database->lastError();
|
||||
res = false;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::getAppLaunchedState(QString &desktopfp, size_t &num)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction()) {
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("SELECT LAUNCHED FROM appInfo WHERE DESKTOP_FILE_PATH='%0'")
|
||||
.arg(desktopfp);
|
||||
if (sql.exec(cmd)) {
|
||||
if (sql.next()) {
|
||||
num = sql.value(0).toInt();
|
||||
} else {
|
||||
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database->lastError();
|
||||
res = false;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::getAppFavoriteState(QString &desktopfp, size_t &num)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction()) {
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("SELECT FAVORITES FROM appInfo WHERE DESKTOP_FILE_PATH='%0'")
|
||||
.arg(desktopfp);
|
||||
if (sql.exec(cmd)) {
|
||||
if (sql.next()) {
|
||||
num = sql.value(0).toInt();
|
||||
} else {
|
||||
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database->lastError();
|
||||
res = false;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::searchInstallApp(QString &keyWord, QStringList &installAppInfoRes)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction()) {
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd;
|
||||
if (keyWord.size() < 2) {
|
||||
cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON FROM appInfo WHERE LOCAL_NAME OR NAME_EN OR NAME_ZH OR FIRST_LETTER_OF_PINYIN LIKE '%%0%' ORDER BY FAVORITES DESC")
|
||||
.arg(keyWord);
|
||||
} else {
|
||||
cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON FROM appInfo WHERE LOCAL_NAME OR NAME_EN OR NAME_ZH OR PINYIN_NAME OR FIRST_LETTER_OF_PINYIN LIKE '%%0%' ORDER BY FAVORITES DESC")
|
||||
.arg(keyWord);
|
||||
}
|
||||
|
||||
if (sql.exec(cmd)) {
|
||||
while (sql.next()) {
|
||||
installAppInfoRes << sql.value(0).toString() << sql.value(1).toString() << sql.value(2).toString();
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::searchInstallApp(QStringList &keyWord, QStringList &installAppInfoRes)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction() or keyWord.size() != 0) {
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd;
|
||||
if (keyWord.at(0).size() < 2) {
|
||||
cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON,NAME_EN,NAME_ZH,FIRST_LETTER_OF_PINYIN FROM appInfo"
|
||||
" WHERE LOCAL_NAME LIKE '%%0%' OR NAME_EN LIKE '%%0%' OR NAME_ZH LIKE '%%0%' OR FIRST_LETTER_OF_PINYIN LIKE '%%0%'")
|
||||
.arg(keyWord.at(0));
|
||||
} else {
|
||||
cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON,NAME_EN,NAME_ZH,FIRST_LETTER_OF_PINYIN FROM appInfo"
|
||||
" WHERE LOCAL_NAME LIKE '%%0%' OR NAME_EN LIKE '%%0%' OR NAME_ZH LIKE '%%0%' OR PINYIN_NAME LIKE '%%0%' OR FIRST_LETTER_OF_PINYIN LIKE '%%0%'")
|
||||
.arg(keyWord.at(0));
|
||||
}
|
||||
for (int i = 0; ++i<keyWord.size();) {
|
||||
if (keyWord.at(i).size() < 2) {
|
||||
cmd += QString(" AND (LOCAL_NAME LIKE '%%1%' OR NAME_EN LIKE '%%1%' OR NAME_ZH LIKE '%%1%' OR FIRST_LETTER_OF_PINYIN LIKE '%%1%')")
|
||||
.arg(keyWord.at(i));
|
||||
} else {
|
||||
cmd += QString(" AND (LOCAL_NAME LIKE '%%1%' OR NAME_EN LIKE '%%1%' OR NAME_ZH LIKE '%%1%' OR PINYIN_NAME LIKE '%%1%' OR FIRST_LETTER_OF_PINYIN LIKE '%%1%')")
|
||||
.arg(keyWord.at(i));
|
||||
}
|
||||
}
|
||||
cmd += QString(" ORDER BY LENGTH(LOCAL_NAME)");
|
||||
if (sql.exec(cmd)) {
|
||||
while (sql.next()) {
|
||||
installAppInfoRes << sql.value(0).toString() << sql.value(1).toString() << sql.value(2).toString();
|
||||
}
|
||||
} 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!!! keyword size:" << keyWord.size();
|
||||
res = false;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool AppInfoTablePrivate::uninstallApp(QString &desktopfp)
|
||||
{
|
||||
bool res(false);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
AppInfoTablePrivate::~AppInfoTablePrivate()
|
||||
{
|
||||
this->closeDataBase();
|
||||
}
|
||||
|
||||
void AppInfoTablePrivate::initDateBaseConnection()
|
||||
{
|
||||
m_database->setDatabaseName(APP_DATABASE_PATH + APP_DATABASE_NAME);
|
||||
if(!m_database->open()) {
|
||||
qWarning() << m_database->lastError();
|
||||
QApplication::quit();
|
||||
}
|
||||
}
|
||||
|
||||
void AppInfoTablePrivate::openDataBase()
|
||||
{
|
||||
*m_database = QSqlDatabase::addDatabase("QSQLITE", m_ConnectionName);
|
||||
m_database->setDatabaseName(APP_DATABASE_PATH + APP_DATABASE_NAME);
|
||||
|
||||
if(!m_database->open()) {
|
||||
qWarning() << m_database->lastError();
|
||||
QApplication::quit();
|
||||
}
|
||||
}
|
||||
|
||||
void AppInfoTablePrivate::closeDataBase()
|
||||
{
|
||||
m_database->close();
|
||||
delete m_database;
|
||||
QSqlDatabase::removeDatabase(m_ConnectionName);
|
||||
}
|
||||
|
||||
AppInfoTable::AppInfoTable(QObject *parent) : QObject(parent), d(new AppInfoTablePrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
bool AppInfoTable::setAppFavoritesState(QString &desktopfp, size_t num)
|
||||
{
|
||||
return d->setAppFavoritesState(desktopfp, num);
|
||||
}
|
||||
|
||||
bool AppInfoTable::setAppTopState(QString &desktopfp, size_t num)
|
||||
{
|
||||
return d->setAppTopState(desktopfp, num);
|
||||
}
|
||||
|
||||
bool AppInfoTable::setAppLaunchTimes(QString &desktopfp, size_t num)
|
||||
{
|
||||
return d->setAppLaunchTimes(desktopfp, num);
|
||||
}
|
||||
|
||||
bool AppInfoTable::updateAppLaunchTimes(QString &desktopfp)
|
||||
{
|
||||
return d->updateAppLaunchTimes(desktopfp);
|
||||
}
|
||||
|
||||
bool AppInfoTable::setAppLockState(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);
|
||||
}
|
||||
|
||||
bool AppInfoTable::getAppCategory(QString &desktopfp, QString &category)
|
||||
{
|
||||
return d->getAppCategory(desktopfp, category);
|
||||
}
|
||||
|
||||
bool AppInfoTable::getAppInfoResults(QVector<AppInfoTable::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);
|
||||
}
|
||||
|
||||
bool AppInfoTable::searchInstallApp(QString &keyWord, QStringList &installAppInfoRes)
|
||||
{
|
||||
return d->searchInstallApp(keyWord, installAppInfoRes);
|
||||
}
|
||||
|
||||
bool AppInfoTable::searchInstallApp(QStringList &keyWord, QStringList &installAppInfoRes)
|
||||
{
|
||||
return d->searchInstallApp(keyWord, installAppInfoRes);
|
||||
}
|
||||
|
||||
bool AppInfoTable::uninstallApp(QString &desktopfp)
|
||||
{
|
||||
return d->uninstallApp(desktopfp);
|
||||
}
|
||||
|
||||
QString AppInfoTable::lastError() const
|
||||
{
|
||||
return d->lastError();
|
||||
}
|
||||
|
|
|
@ -4,29 +4,77 @@
|
|||
#include <QObject>
|
||||
namespace UkuiSearch {
|
||||
class AppInfoTablePrivate;
|
||||
/**
|
||||
* @brief The AppInfoTable class
|
||||
* TODO:提供查询接口(待定),包括:
|
||||
* 1.查询全部已安装应用信息(图标,名称,分类等),并且根据系统语言切换
|
||||
* 2.查询收藏应用信息
|
||||
* 3.查询置顶顺序信息
|
||||
* 4.收藏顺序修改
|
||||
* 5.置顶顺序修改
|
||||
* 6.添加到桌面快捷方式
|
||||
* 7.固定到任务栏快捷方式
|
||||
* 8.应用启动
|
||||
* 9.应用卸载
|
||||
* 注意事项:修改接口实现时注意事务操作
|
||||
*/
|
||||
class AppInfoTable : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
typedef struct appInfoResult
|
||||
{
|
||||
appInfoResult() {
|
||||
top = 0;
|
||||
favorate = 0;
|
||||
launchTimes = 0;
|
||||
lock = 0;
|
||||
}
|
||||
|
||||
QString desktopPath;
|
||||
QString iconName;
|
||||
QString appLocalName;
|
||||
QString firstLetter;
|
||||
QString category;
|
||||
size_t top;
|
||||
size_t favorate;
|
||||
size_t launchTimes;
|
||||
size_t lock;
|
||||
|
||||
} AppInfoResult;
|
||||
|
||||
public:
|
||||
explicit AppInfoTable(QObject *parent = nullptr);
|
||||
AppInfoTable(AppInfoTable &) = delete;
|
||||
AppInfoTable &operator =(const AppInfoTable &) = delete;
|
||||
|
||||
bool setAppFavoritesState(QString &desktopfp, size_t num);
|
||||
bool setAppTopState(QString &desktopfp, size_t num);
|
||||
|
||||
bool getAllAppDesktopList(QStringList &list);
|
||||
bool getFavoritesAppList(QStringList &list);
|
||||
bool getTopAppList(QStringList &list);
|
||||
bool getLaunchTimesAppList(QStringList &list);
|
||||
bool getAppCategory(QString &desktopfp, QString &category);
|
||||
|
||||
/**
|
||||
* @brief getAppInfoResults
|
||||
* @param appInfoResults
|
||||
* @return
|
||||
*/
|
||||
bool getAppInfoResults(QVector<AppInfoTable::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 addAppShortcut2Desktop(QString &desktopfp);
|
||||
bool addAppShortcut2Panel(QString &desktopfp);
|
||||
|
||||
bool searchInstallApp(QString &keyWord, QStringList &installAppInfoRes);
|
||||
bool searchInstallApp(QStringList &keyWord, QStringList &installAppInfoRes);
|
||||
|
||||
bool uninstallApp(QString &desktopfp);
|
||||
|
||||
/**
|
||||
* @brief lastError
|
||||
* @return
|
||||
*/
|
||||
QString lastError(void) const;
|
||||
|
||||
private:
|
||||
bool setAppLaunchTimes(QString &desktopfp, size_t num);
|
||||
bool setAppLockState(QString &desktopfp, size_t num);
|
||||
bool updateAppLaunchTimes(QString &desktopfp);
|
||||
|
||||
AppInfoTablePrivate *d;
|
||||
|
||||
};
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
INCLUDEPATH += $$PWD
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/app-db-manager.h \
|
||||
$$PWD/app-info-table-private.h \
|
||||
$$PWD/app-info-table.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/app-db-manager.cpp \
|
||||
$$PWD/app-info-table.cpp
|
||||
|
||||
|
|
|
@ -21,9 +21,10 @@
|
|||
#include <glib.h>
|
||||
#include <qt5xdg/XdgIcon>
|
||||
#include <qt5xdg/XdgDesktopFile>
|
||||
#include <QMap>
|
||||
#include "file-utils.h"
|
||||
#include "app-search-plugin.h"
|
||||
#define ANDROID_APP_DESKTOP_PATH QDir::homePath() + "/.local/share/applications/"
|
||||
|
||||
using namespace UkuiSearch;
|
||||
static AppMatch *app_match_Class = nullptr;
|
||||
|
||||
|
@ -36,13 +37,6 @@ AppMatch *AppMatch::getAppMatch() {
|
|||
AppMatch::AppMatch(QObject *parent) : QThread(parent)
|
||||
// m_versionCommand(new QProcess(this))
|
||||
{
|
||||
m_watchAppDir = new QFileSystemWatcher(this);
|
||||
m_watchAppDir->addPath("/usr/share/applications/");
|
||||
QDir androidPath(ANDROID_APP_DESKTOP_PATH);
|
||||
if(!androidPath.exists()) {
|
||||
androidPath.mkpath(ANDROID_APP_DESKTOP_PATH);
|
||||
}
|
||||
m_watchAppDir->addPath(ANDROID_APP_DESKTOP_PATH);
|
||||
qDBusRegisterMetaType<QMap<QString, QString>>();
|
||||
qDBusRegisterMetaType<QList<QMap<QString, QString>>>();
|
||||
m_interFace = new QDBusInterface("com.kylin.softwarecenter.getsearchresults", "/com/kylin/softwarecenter/getsearchresults",
|
||||
|
@ -52,6 +46,7 @@ AppMatch::AppMatch(QObject *parent) : QThread(parent)
|
|||
qWarning() << qPrintable(QDBusConnection::sessionBus().lastError().message());
|
||||
}
|
||||
m_interFace->setTimeout(1500);
|
||||
m_appInfoTable = new AppInfoTable;
|
||||
qDebug() << "AppMatch init finished.";
|
||||
}
|
||||
|
||||
|
@ -60,10 +55,10 @@ AppMatch::~AppMatch() {
|
|||
delete m_interFace;
|
||||
}
|
||||
m_interFace = NULL;
|
||||
if(m_watchAppDir) {
|
||||
delete m_watchAppDir;
|
||||
if(m_appInfoTable) {
|
||||
delete m_appInfoTable;
|
||||
}
|
||||
m_watchAppDir = NULL;
|
||||
m_appInfoTable = NULL;
|
||||
}
|
||||
|
||||
void AppMatch::startMatchApp(QString input, size_t uniqueSymbol, DataQueue<SearchPluginIface::ResultInfo> *searchResult) {
|
||||
|
@ -72,73 +67,6 @@ void AppMatch::startMatchApp(QString input, size_t uniqueSymbol, DataQueue<Searc
|
|||
qDebug() << "App match finished!";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief AppMatch::getAllDesktopFilePath 遍历所有desktop文件
|
||||
* @param path 存放desktop文件夹
|
||||
*/
|
||||
void AppMatch::getAllDesktopFilePath(QString path) {
|
||||
|
||||
QDir dir(path);
|
||||
if(!dir.exists()) {
|
||||
return;
|
||||
}
|
||||
dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
|
||||
dir.setSorting(QDir::DirsFirst);
|
||||
QFileInfoList list = dir.entryInfoList();
|
||||
list.removeAll(QFileInfo("/usr/share/applications/screensavers"));
|
||||
if(list.size() < 1) {
|
||||
return;
|
||||
}
|
||||
XdgDesktopFile desktopfile;
|
||||
int i = 0;
|
||||
while(i < list.size()) {
|
||||
QFileInfo fileInfo = list.at(i);
|
||||
//如果是文件夹,递归
|
||||
bool isDir = fileInfo.isDir();
|
||||
if(isDir) {
|
||||
getAllDesktopFilePath(fileInfo.filePath());
|
||||
qDebug() << fileInfo.filePath();
|
||||
++i;
|
||||
} else {
|
||||
QString filePathStr = fileInfo.filePath();
|
||||
if(m_ExcludedDesktopfiles.contains(filePathStr)) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
//过滤后缀不是.desktop的文件
|
||||
if(!filePathStr.endsWith(".desktop")) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
desktopfile.load(filePathStr);
|
||||
if(desktopfile.value("NoDisplay").toString().contains("true") || desktopfile.value("NotShowIn").toString().contains("UKUI")) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
QString name = desktopfile.localizedValue("Name").toString();
|
||||
if(name.isEmpty()) {
|
||||
++i;
|
||||
qDebug() << filePathStr << "name!!";
|
||||
continue;
|
||||
}
|
||||
|
||||
QString icon = desktopfile.iconName();
|
||||
NameString appname;
|
||||
QStringList appInfolist;
|
||||
|
||||
appname.app_name = name;
|
||||
appInfolist << filePathStr << icon;
|
||||
appInfolist.append(desktopfile.value("Name").toString());
|
||||
appInfolist.append(desktopfile.value("Name[zh_CN]").toString());
|
||||
m_installAppMap.insert(appname, appInfolist);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief AppMatch::appNameMatch
|
||||
* 进行匹配
|
||||
|
@ -146,7 +74,36 @@ void AppMatch::getAllDesktopFilePath(QString path) {
|
|||
* 应用名字
|
||||
*/
|
||||
void AppMatch::appNameMatch(QString keyWord, size_t uniqueSymbol, DataQueue<SearchPluginIface::ResultInfo> *searchResult) {
|
||||
QMapIterator<NameString, QStringList> iter(m_installAppMap);
|
||||
QStringList results;
|
||||
//m_appInfoTable->searchInstallAppOrderByFavoritesDesc(keyWord, results);
|
||||
for (int i = 0; i < results.size() / 3; i++) {
|
||||
{
|
||||
QMutexLocker locker(&AppSearchPlugin::m_mutex);
|
||||
if (uniqueSymbol != AppSearchPlugin::uniqueSymbol) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SearchPluginIface::ResultInfo ri;
|
||||
ri.actionKey = results.at(i*3);
|
||||
ri.name = results.at(i*3 + 1);
|
||||
ri.icon = XdgIcon::fromTheme(results.at(i*3 + 2), QIcon(":/res/icons/desktop.png"));
|
||||
ri.type = 0;
|
||||
|
||||
searchResult->enqueue(ri);
|
||||
}
|
||||
|
||||
/* QMultiMap<QString, QStringList> installAppMap;
|
||||
m_appInfoTable->getInstallAppMap(installAppMap);
|
||||
QMap<NameString, QStringList> resultAppMap;
|
||||
for (auto i = installAppMap.begin(); i != installAppMap.end(); ++i) {
|
||||
NameString name;
|
||||
name.app_name = i.key();
|
||||
QStringList infoList;
|
||||
infoList = i.value();
|
||||
resultAppMap.insert(name, infoList);
|
||||
}
|
||||
QMapIterator<NameString, QStringList> iter(resultAppMap);
|
||||
while(iter.hasNext()) {
|
||||
iter.next();
|
||||
if(iter.key().app_name.contains(keyWord, Qt::CaseInsensitive)) {
|
||||
|
@ -224,27 +181,16 @@ void AppMatch::appNameMatch(QString keyWord, size_t uniqueSymbol, DataQueue<Sear
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AppMatch::softWareCenterSearch(QMap<NameString, QStringList> &softwarereturn) {
|
||||
// if(m_interFace->timeout() != -1) {
|
||||
// qWarning() << "softWareCente Dbus is timeout !";
|
||||
// return;
|
||||
// }
|
||||
// slotDBusCallFinished(softwarereturn);
|
||||
qDebug() << "softWareCenter match app is successful!";
|
||||
}*/
|
||||
}
|
||||
|
||||
void AppMatch::slotDBusCallFinished(QString keyWord, size_t uniqueSymbol, DataQueue<SearchPluginIface::ResultInfo> *searchResult) {
|
||||
QDBusReply<QList<QMap<QString, QString>>> reply = m_interFace->call("get_search_result", keyWord); //阻塞,直到远程方法调用完成。
|
||||
// QDBusPendingReply<QList<QMap<QString,QString>>> reply = *call;
|
||||
if(reply.isValid()) {
|
||||
parseSoftWareCenterReturn(reply.value(), uniqueSymbol, searchResult);
|
||||
} else {
|
||||
qWarning() << "SoftWareCenter dbus called failed!";
|
||||
}
|
||||
// call->deleteLater();
|
||||
}
|
||||
|
||||
void AppMatch::parseSoftWareCenterReturn(QList<QMap<QString, QString>> list, size_t uniqueSymbol, DataQueue<SearchPluginIface::ResultInfo> *searchResult) {
|
||||
|
@ -275,24 +221,17 @@ void AppMatch::parseSoftWareCenterReturn(QList<QMap<QString, QString>> list, siz
|
|||
}
|
||||
}
|
||||
|
||||
void AppMatch::creatResultInfo(SearchPluginIface::ResultInfo &ri, QMapIterator<NameString, QStringList> &iter, bool isInstalled)
|
||||
{
|
||||
// ri.icon = QIcon::fromTheme(iter.value().at(1), QIcon(":/res/icons/desktop.png"));
|
||||
ri.icon = XdgIcon::fromTheme(iter.value().at(1), QIcon(":/res/icons/desktop.png"));
|
||||
ri.name = iter.key().app_name;
|
||||
ri.actionKey = iter.value().at(0);
|
||||
ri.type = 0; //0 means installed apps.
|
||||
}
|
||||
//void AppMatch::creatResultInfo(SearchPluginIface::ResultInfo &ri, QMapIterator<NameString, QStringList> &iter, bool isInstalled)
|
||||
//{
|
||||
//// ri.icon = QIcon::fromTheme(iter.value().at(1), QIcon(":/res/icons/desktop.png"));
|
||||
// ri.icon = XdgIcon::fromTheme(iter.value().at(1), QIcon(":/res/icons/desktop.png"));
|
||||
// ri.name = iter.key().app_name;
|
||||
// ri.actionKey = iter.value().at(0);
|
||||
// ri.type = 0; //0 means installed apps.
|
||||
//}
|
||||
|
||||
void AppMatch::run() {
|
||||
qDebug() << "App map init..";
|
||||
this->getAllDesktopFilePath("/usr/share/applications/");
|
||||
this->getAllDesktopFilePath(ANDROID_APP_DESKTOP_PATH);
|
||||
connect(m_watchAppDir, &QFileSystemWatcher::directoryChanged, this, [ = ](const QString & path) {
|
||||
m_installAppMap.clear();
|
||||
this->getAllDesktopFilePath("/usr/share/applications/");
|
||||
this->getAllDesktopFilePath(ANDROID_APP_DESKTOP_PATH);
|
||||
qDebug() << "App map update " << m_installAppMap.size();
|
||||
});
|
||||
qDebug() << "App map init finished.." << m_installAppMap.size();
|
||||
|
||||
qDebug() << "App map init finished..";
|
||||
}
|
||||
|
|
|
@ -29,31 +29,9 @@
|
|||
#include <QtDBus>
|
||||
#include <QThread>
|
||||
#include "search-plugin-iface.h"
|
||||
#include "../appdata/app-info-table.h"
|
||||
|
||||
namespace UkuiSearch {
|
||||
class NameString {
|
||||
public:
|
||||
explicit NameString(const QString &str_) : app_name(str_) {}
|
||||
NameString() = default;
|
||||
QString app_name;
|
||||
bool operator<(const NameString& name) const {
|
||||
return this->app_name.length() <= name.app_name.length();
|
||||
}
|
||||
bool operator==(const NameString& name) const {
|
||||
return this->app_name == name.app_name;
|
||||
}
|
||||
};
|
||||
|
||||
//struct NameString
|
||||
//{
|
||||
// QString app_name;
|
||||
// //重载操作符
|
||||
// inline bool operator < (const NameString& name) const
|
||||
// {
|
||||
//// return name.app_name.length() >= app_name.length();
|
||||
// return true;
|
||||
// }
|
||||
//};
|
||||
|
||||
class AppMatch : public QThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -68,61 +46,14 @@ private:
|
|||
~AppMatch();
|
||||
void getAllDesktopFilePath(QString path);
|
||||
void appNameMatch(QString keyWord, size_t uniqueSymbol, DataQueue<SearchPluginIface::ResultInfo> *searchResult);
|
||||
void softWareCenterSearch(QMap<NameString, QStringList> &softwarereturn);
|
||||
void parseSoftWareCenterReturn(QList<QMap<QString, QString>> list, size_t uniqueSymbol, DataQueue<SearchPluginIface::ResultInfo> *searchResult);
|
||||
void creatResultInfo(SearchPluginIface::ResultInfo &ri, QMapIterator<NameString, QStringList> &iter, bool isInstalled = true);
|
||||
//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;
|
||||
QDBusInterface *m_interFace = nullptr;
|
||||
QFileSystemWatcher *m_watchAppDir = nullptr;
|
||||
QMap<NameString, QStringList> m_installAppMap;
|
||||
|
||||
QStringList m_ExcludedDesktopfiles = {
|
||||
"/usr/share/applications/software-properties-livepatch.desktop",
|
||||
"/usr/share/applications/mate-color-select.desktop",
|
||||
"/usr/share/applications/blueman-adapters.desktop",
|
||||
"/usr/share/applications/blueman-manager.desktop",
|
||||
"/usr/share/applications/mate-user-guide.desktop",
|
||||
"/usr/share/applications/nm-connection-editor.desktop",
|
||||
"/usr/share/applications/debian-uxterm.desktop",
|
||||
"/usr/share/applications/debian-xterm.desktop",
|
||||
"/usr/share/applications/im-config.desktop",
|
||||
"/usr/share/applications/fcitx.desktop",
|
||||
"/usr/share/applications/fcitx-configtool.desktop",
|
||||
"/usr/share/applications/onboard-settings.desktop",
|
||||
"/usr/share/applications/info.desktop",
|
||||
"/usr/share/applications/ukui-power-preferences.desktop",
|
||||
"/usr/share/applications/ukui-power-statistics.desktop",
|
||||
"/usr/share/applications/software-properties-drivers.desktop",
|
||||
"/usr/share/applications/software-properties-gtk.desktop",
|
||||
"/usr/share/applications/gnome-session-properties.desktop",
|
||||
"/usr/share/applications/org.gnome.font-viewer.desktop",
|
||||
"/usr/share/applications/xdiagnose.desktop",
|
||||
"/usr/share/applications/gnome-language-selector.desktop",
|
||||
"/usr/share/applications/mate-notification-properties.desktop",
|
||||
"/usr/share/applications/transmission-gtk.desktop",
|
||||
"/usr/share/applications/mpv.desktop",
|
||||
"/usr/share/applications/system-config-printer.desktop",
|
||||
"/usr/share/applications/org.gnome.DejaDup.desktop",
|
||||
"/usr/share/applications/yelp.desktop",
|
||||
"/usr/share/applications/peony-computer.desktop",
|
||||
"/usr/share/applications/peony-home.desktop",
|
||||
"/usr/share/applications/peony-trash.desktop",
|
||||
|
||||
//v10
|
||||
"/usr/share/applications/mate-about.desktop",
|
||||
"/usr/share/applications/time.desktop",
|
||||
"/usr/share/applications/network.desktop",
|
||||
"/usr/share/applications/shares.desktop",
|
||||
"/usr/share/applications/mate-power-statistics.desktop",
|
||||
"/usr/share/applications/display-im6.desktop",
|
||||
"/usr/share/applications/display-im6.q16.desktop",
|
||||
"/usr/share/applications/openjdk-8-policytool.desktop",
|
||||
"/usr/share/applications/kylin-io-monitor.desktop",
|
||||
"/usr/share/applications/wps-office-uninstall.desktop",
|
||||
};
|
||||
|
||||
private Q_SLOTS:
|
||||
void slotDBusCallFinished(QString keyWord, size_t uniqueSymbol, DataQueue<SearchPluginIface::ResultInfo> *searchResult);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
using namespace UkuiSearch;
|
||||
size_t AppSearchPlugin::uniqueSymbol = 0;
|
||||
QMutex AppSearchPlugin::m_mutex;
|
||||
AppSearchPlugin::AppSearchPlugin(QObject *parent) : QObject(parent)
|
||||
AppSearchPlugin::AppSearchPlugin(QObject *parent) : QObject(parent), m_appSearchTask(new UkuiSearchTask(this))
|
||||
{
|
||||
SearchPluginIface::Actioninfo open { 0, tr("Open")};
|
||||
SearchPluginIface::Actioninfo addtoDesktop { 1, tr("Add Shortcut to Desktop")};
|
||||
|
@ -14,10 +14,18 @@ AppSearchPlugin::AppSearchPlugin(QObject *parent) : QObject(parent)
|
|||
SearchPluginIface::Actioninfo install { 0, tr("Install")};
|
||||
m_actionInfo_installed << open << addtoDesktop << addtoPanel;
|
||||
m_actionInfo_not_installed << install;
|
||||
AppMatch::getAppMatch()->start();
|
||||
m_pool.setMaxThreadCount(1);
|
||||
m_pool.setExpiryTimeout(1000);
|
||||
initDetailPage();
|
||||
|
||||
m_appSearchResults = m_appSearchTask->init();
|
||||
m_appSearchTask->initSearchPlugin(SearchType::Application);
|
||||
m_appSearchTask->setSearchOnlineApps(true);
|
||||
m_appSearchTask->setResultDataType(SearchType::Application, UkuiSearch::ApplicationDesktopPath |
|
||||
UkuiSearch::ApplicationLocalName |
|
||||
UkuiSearch::ApplicationIconName |
|
||||
UkuiSearch::ApplicationDescription |
|
||||
UkuiSearch::IsOnlineApplication);
|
||||
}
|
||||
|
||||
const QString AppSearchPlugin::name()
|
||||
|
@ -40,7 +48,7 @@ void AppSearchPlugin::KeywordSearch(QString keyword, DataQueue<SearchPluginIface
|
|||
m_mutex.lock();
|
||||
++uniqueSymbol;
|
||||
m_mutex.unlock();
|
||||
AppSearch *appsearch = new AppSearch(searchResult, keyword, uniqueSymbol);
|
||||
AppSearch *appsearch = new AppSearch(searchResult, m_appSearchResults, m_appSearchTask, keyword, uniqueSymbol);
|
||||
m_pool.start(appsearch);
|
||||
}
|
||||
|
||||
|
@ -103,7 +111,7 @@ void AppSearchPlugin::openAction(int actionkey, QString key, int type)
|
|||
QWidget *AppSearchPlugin::detailPage(const ResultInfo &ri)
|
||||
{
|
||||
m_currentActionKey = ri.actionKey;
|
||||
m_iconLabel->setPixmap(ri.icon.pixmap(120, 120));
|
||||
m_iconLabel->setPixmap(ri.icon.isNull() ? QIcon(":/res/icons/desktop.png").pixmap(120, 120) : ri.icon.pixmap(120, 120));
|
||||
QFontMetrics fontMetrics = m_nameLabel->fontMetrics();
|
||||
QString showname = fontMetrics.elidedText(ri.name, Qt::ElideRight, 215); //当字体长度超过215时显示为省略号
|
||||
m_nameLabel->setText(FileUtils::setAllTextBold(showname));
|
||||
|
@ -206,16 +214,6 @@ void AppSearchPlugin::initDetailPage()
|
|||
});
|
||||
}
|
||||
|
||||
//bool AppSearchPlugin::isPreviewEnable(QString key, int type)
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
|
||||
//QWidget *AppSearchPlugin::previewPage(QString key, int type, QWidget *parent = nullptr)
|
||||
//{
|
||||
// return nullptr;
|
||||
//}
|
||||
|
||||
bool AppSearchPlugin::launch(const QString &path)
|
||||
{
|
||||
GDesktopAppInfo * desktopAppInfo = g_desktop_app_info_new_from_filename(path.toLocal8Bit().data());
|
||||
|
@ -275,11 +273,14 @@ bool AppSearchPlugin::installAppAction(const QString & name) {
|
|||
}
|
||||
}
|
||||
|
||||
AppSearch::AppSearch(DataQueue<SearchPluginIface::ResultInfo> *searchResult, const QString &keyword, size_t uniqueSymbol)
|
||||
AppSearch::AppSearch(DataQueue<SearchPluginIface::ResultInfo> *searchResult, DataQueue<ResultItem>* appSearchResults, UkuiSearchTask *appSearchTask, QString keyword, size_t uniqueSymbol)
|
||||
{
|
||||
this->setAutoDelete(true);
|
||||
m_search_result = searchResult;
|
||||
m_keyword = keyword;
|
||||
m_appSearchResults = appSearchResults;
|
||||
m_appSearchTask = appSearchTask;
|
||||
m_appSearchTask->clearKeyWords();
|
||||
m_appSearchTask->addKeyword(keyword);
|
||||
m_uniqueSymbol = uniqueSymbol;
|
||||
}
|
||||
|
||||
|
@ -289,5 +290,55 @@ AppSearch::~AppSearch()
|
|||
|
||||
void AppSearch::run()
|
||||
{
|
||||
AppMatch::getAppMatch()->startMatchApp(m_keyword, m_uniqueSymbol, m_search_result);
|
||||
m_appSearchTask->startSearch(SearchType::Application);
|
||||
QTimer timer;
|
||||
timer.setInterval(3000);
|
||||
bool is_empty;
|
||||
while(1) {
|
||||
is_empty = false;
|
||||
if(!m_appSearchResults->isEmpty()) {
|
||||
ResultItem oneResult = m_appSearchResults->dequeue();
|
||||
SearchPluginIface::ResultInfo ri;
|
||||
ri.actionKey = oneResult.getExtral().at(0).toString();
|
||||
ri.name = oneResult.getExtral().at(1).toString();
|
||||
ri.icon = oneResult.getExtral().at(2).value<QIcon>();
|
||||
SearchPluginIface::DescriptionInfo description;
|
||||
description.key = QString(tr("Application Description:"));
|
||||
description.value = oneResult.getExtral().at(3).toString();
|
||||
ri.description.append(description);
|
||||
ri.type = oneResult.getExtral().at(4).toInt();
|
||||
if (isUniqueSymbolChanged()) {
|
||||
m_appSearchResults->clear();
|
||||
break;
|
||||
}
|
||||
m_search_result->enqueue(ri);
|
||||
} else {
|
||||
is_empty = true;
|
||||
}
|
||||
if (isUniqueSymbolChanged()) {
|
||||
break;
|
||||
}
|
||||
if(timer.isActive() && timer.remainingTime() < 0.01) {
|
||||
qWarning()<<"-------------->stopped by itself";
|
||||
break;
|
||||
}
|
||||
if(is_empty && !timer.isActive()) {
|
||||
timer.start();
|
||||
} else if(!is_empty) {
|
||||
timer.stop();
|
||||
} else {
|
||||
QThread::msleep(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AppSearch::isUniqueSymbolChanged()
|
||||
{
|
||||
QMutexLocker locker(&AppSearchPlugin::m_mutex);
|
||||
if (m_uniqueSymbol != AppSearchPlugin::uniqueSymbol) {
|
||||
qDebug() << "uniqueSymbol changged, app search finished!";
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,14 @@
|
|||
#include <QFrame>
|
||||
#include <QLabel>
|
||||
#include <QAction>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusReply>
|
||||
#include <QtDBus>
|
||||
#include "search-plugin-iface.h"
|
||||
#include "app-match.h"
|
||||
#include "action-label.h"
|
||||
#include "separation-line.h"
|
||||
#include "libsearch_global.h"
|
||||
#include "ukui-search-task.h"
|
||||
namespace UkuiSearch {
|
||||
class LIBSEARCH_EXPORT AppSearchPlugin : public QObject, public SearchPluginIface
|
||||
{
|
||||
|
@ -49,6 +52,9 @@ private:
|
|||
static size_t uniqueSymbol;
|
||||
static QMutex m_mutex;
|
||||
|
||||
UkuiSearchTask *m_appSearchTask = nullptr;
|
||||
DataQueue<ResultItem>* m_appSearchResults = nullptr;
|
||||
|
||||
QString m_currentActionKey;
|
||||
QWidget *m_detailPage;
|
||||
QVBoxLayout *m_detailLyt = nullptr;
|
||||
|
@ -75,16 +81,19 @@ private:
|
|||
class AppSearch : public QObject, public QRunnable {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AppSearch(DataQueue<SearchPluginIface::ResultInfo> *searchResult, const QString& keyword, size_t uniqueSymbol);
|
||||
AppSearch(DataQueue<SearchPluginIface::ResultInfo> *searchResult, DataQueue<ResultItem>* appSearchResults, UkuiSearchTask *appSearchTask, QString keyword, size_t uniqueSymbol);
|
||||
~AppSearch();
|
||||
protected:
|
||||
void run() override;
|
||||
private:
|
||||
DataQueue<SearchPluginIface::ResultInfo> *m_search_result = nullptr;
|
||||
|
||||
bool isUniqueSymbolChanged();
|
||||
|
||||
size_t m_uniqueSymbol;
|
||||
QString m_keyword;
|
||||
QMap<NameString, QStringList> m_installed_apps;
|
||||
QMap<NameString, QStringList> m_not_installed_apps;
|
||||
UkuiSearchTask *m_appSearchTask = nullptr;
|
||||
DataQueue<ResultItem>* m_appSearchResults = nullptr;
|
||||
DataQueue<SearchPluginIface::ResultInfo> *m_search_result = nullptr;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
INCLUDEPATH += $$PWD
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/app-match.h \
|
||||
$$PWD/app-search-plugin.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/app-match.cpp \
|
||||
$$PWD/app-search-plugin.cpp
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include "app-info-table.h"
|
|
@ -1,5 +1,5 @@
|
|||
QT += core xml widgets dbus concurrent sql
|
||||
VERSION = 2.2.3
|
||||
QT += core xml widgets dbus concurrent sql KWindowSystem
|
||||
VERSION = 2.3.0
|
||||
DEFINES += VERSION='\\"$${VERSION}\\"'
|
||||
|
||||
TARGET = ukui-search
|
||||
|
@ -55,7 +55,8 @@ HEADERS += \
|
|||
global-settings.h \
|
||||
gobject-template.h \
|
||||
libsearch_global.h \
|
||||
libsearch.h
|
||||
libsearch.h \
|
||||
../ukui-search-app-data-service/app-db-common-defines.h
|
||||
|
||||
RESOURCES += \
|
||||
resource1.qrc \
|
||||
|
@ -86,6 +87,7 @@ unix {
|
|||
header.path = /usr/include/ukui-search
|
||||
header.files += *.h index/*.h appsearch/*.h settingsearch/*.h plugininterface/*.h websearch/*.h \
|
||||
searchinterface/ukui-search-task.h \
|
||||
appdata/app-info-table.h \
|
||||
searchinterface/search-controller.h \
|
||||
searchinterface/result-item.h
|
||||
header.files += development-files/header-files/*
|
||||
|
|
|
@ -1,15 +1,44 @@
|
|||
#ifndef COMMONDEFINES_H
|
||||
#define COMMONDEFINES_H
|
||||
#include <QFlags>
|
||||
namespace UkuiSearch {
|
||||
/**
|
||||
* @brief The SearchType enum
|
||||
*
|
||||
*/
|
||||
enum class SearchType
|
||||
{
|
||||
File = 0x1 << 0,
|
||||
FileContent = 0x1 << 1,
|
||||
Application = 0x1 << 2,
|
||||
Setting = 0x1 << 3,
|
||||
Note = 0x1 << 4,
|
||||
Mail = 0x1 << 5,
|
||||
Custom = 0x1 << 6
|
||||
File = 1u << 0,
|
||||
FileContent = 1u << 1,
|
||||
Application = 1u << 2,
|
||||
Setting = 1u << 3,
|
||||
Note = 1u << 4,
|
||||
Mail = 1u << 5,
|
||||
Custom = 1u << 6
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The ResultDataType enum
|
||||
*
|
||||
*/
|
||||
enum ResultDataType
|
||||
{
|
||||
FilePath = 1u << 0,
|
||||
FileIconName = 1u << 1,
|
||||
FileName = 1u << 2,
|
||||
ModifiedTime = 1u << 3,
|
||||
ApplicationDesktopPath = 1u << 4,
|
||||
ApplicationLocalName = 1u << 5,
|
||||
ApplicationIconName = 1u << 6,
|
||||
ApplicationDescription = 1u << 7,
|
||||
IsOnlineApplication = 1u << 8
|
||||
//add more...
|
||||
|
||||
};
|
||||
Q_DECLARE_FLAGS(ResultDataTypes, ResultDataType)
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(UkuiSearch::ResultDataTypes)
|
||||
|
||||
#endif // COMMONDEFINES_H
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "file-search-task.h"
|
||||
#include "file-content-search-task.h"
|
||||
#include "app-search-task.h"
|
||||
|
||||
using namespace UkuiSearch;
|
||||
static SearchTaskPluginManager *global_instance = nullptr;
|
||||
|
@ -24,6 +25,8 @@ void SearchTaskPluginManager::initPlugins(SearchType searchType)
|
|||
case SearchType::FileContent:
|
||||
registerBuildinPlugin(new FileContentSearchTask(this));
|
||||
break;
|
||||
case SearchType::Application:
|
||||
registerBuildinPlugin(new AppSearchTask(this));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -127,6 +130,9 @@ SearchTaskPluginIface *SearchTaskPluginManager::getPlugin(SearchType searchType,
|
|||
case SearchType::FileContent:
|
||||
searchPlugin = new FileContentSearchTask(this);
|
||||
break;
|
||||
case SearchType::Application:
|
||||
searchPlugin = new AppSearchTask(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -10,13 +10,15 @@ public:
|
|||
~ResultItemPrivate();
|
||||
void setSearchId(size_t searchId);
|
||||
void setItemKey(QString itemKey);
|
||||
void setExtral(QVariantList extral);
|
||||
size_t getSearchId();
|
||||
QString getItemKey();
|
||||
QVariantList getExtral();
|
||||
|
||||
private:
|
||||
size_t m_searchId;
|
||||
QString m_itemKey;
|
||||
QString m_label;
|
||||
QVariant m_extral;
|
||||
QVariantList m_extral;
|
||||
//and something else...
|
||||
|
||||
ResultItem *q;
|
||||
|
|
|
@ -7,7 +7,6 @@ ResultItemPrivate::ResultItemPrivate::ResultItemPrivate(ResultItem *parent) : q(
|
|||
|
||||
ResultItemPrivate::~ResultItemPrivate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ResultItemPrivate::setSearchId(size_t searchId)
|
||||
|
@ -20,6 +19,13 @@ void ResultItemPrivate::setItemKey(QString itemKey)
|
|||
m_itemKey = itemKey;
|
||||
}
|
||||
|
||||
void ResultItemPrivate::setExtral(QVariantList extral)
|
||||
{
|
||||
for (auto &info : extral) {
|
||||
m_extral.append(info);
|
||||
}
|
||||
}
|
||||
|
||||
size_t ResultItemPrivate::getSearchId()
|
||||
{
|
||||
return m_searchId;
|
||||
|
@ -29,6 +35,12 @@ QString ResultItemPrivate::getItemKey()
|
|||
{
|
||||
return m_itemKey;
|
||||
}
|
||||
|
||||
QVariantList ResultItemPrivate::getExtral()
|
||||
{
|
||||
return m_extral;
|
||||
}
|
||||
|
||||
ResultItem::ResultItem() : d(new ResultItemPrivate(this))
|
||||
{
|
||||
}
|
||||
|
@ -43,22 +55,39 @@ ResultItem::ResultItem(const QString itemKey) : d(new ResultItemPrivate(this))
|
|||
d->setItemKey(itemKey);
|
||||
}
|
||||
|
||||
ResultItem::ResultItem(const size_t searchId, const QString itemKey) : d(new ResultItemPrivate(this))
|
||||
ResultItem::ResultItem(const size_t searchId, const QString itemKey, QVariantList extral) : d(new ResultItemPrivate(this))
|
||||
{
|
||||
d->setSearchId(searchId);
|
||||
d->setItemKey(itemKey);
|
||||
d->setExtral(extral);
|
||||
}
|
||||
|
||||
size_t ResultItem::getSearchId()
|
||||
|
||||
size_t ResultItem::getSearchId() const
|
||||
{
|
||||
return d->getSearchId();
|
||||
}
|
||||
|
||||
QString ResultItem::getItemKey()
|
||||
QString ResultItem::getItemKey() const
|
||||
{
|
||||
return d->getItemKey();
|
||||
}
|
||||
|
||||
QVariantList ResultItem::getExtral() const
|
||||
{
|
||||
return d->getExtral();
|
||||
}
|
||||
|
||||
ResultItem::~ResultItem()
|
||||
{
|
||||
if (d)
|
||||
delete d;
|
||||
d = nullptr;
|
||||
}
|
||||
|
||||
ResultItem::ResultItem(const ResultItem &item): d(new ResultItemPrivate(this))
|
||||
{
|
||||
d->setSearchId(item.getSearchId());
|
||||
d->setItemKey(item.getItemKey());
|
||||
d->setExtral(item.getExtral());
|
||||
}
|
||||
|
|
|
@ -9,12 +9,16 @@ class ResultItem
|
|||
{
|
||||
public:
|
||||
explicit ResultItem();
|
||||
virtual ~ResultItem();
|
||||
|
||||
ResultItem(const ResultItem &item);
|
||||
explicit ResultItem(const size_t searchId);
|
||||
explicit ResultItem(const QString itemKey);
|
||||
explicit ResultItem(const size_t searchId, const QString itemKey);
|
||||
size_t getSearchId();
|
||||
QString getItemKey();
|
||||
~ResultItem();
|
||||
explicit ResultItem(const size_t searchId, const QString itemKey, QVariantList extral = QVariantList());
|
||||
size_t getSearchId() const;
|
||||
QString getItemKey() const;
|
||||
QVariantList getExtral() const;
|
||||
|
||||
private:
|
||||
ResultItemPrivate *d;
|
||||
};
|
||||
|
|
|
@ -21,9 +21,12 @@ public:
|
|||
void addFileLabel(QString &label);
|
||||
void setOnlySearchFile(bool onlySearchFile);
|
||||
void setOnlySearchDir(bool onlySearchDir);
|
||||
void setSearchOnlineApps(bool searchOnlineApps);
|
||||
|
||||
size_t getCurrentSearchId();
|
||||
DataQueue<ResultItem>* getDataQueue();
|
||||
ResultDataTypes getResultDataType(SearchType searchType);
|
||||
QStringList getCustomResultDataType(QString customSearchType);
|
||||
bool beginSearchIdCheck(size_t searchId);
|
||||
void finishSearchIdCheck();
|
||||
void stop();
|
||||
|
@ -34,11 +37,15 @@ public:
|
|||
QStringList getFileLabel();
|
||||
bool isSearchFileOnly();
|
||||
bool isSearchDirOnly();
|
||||
bool isSearchOnlineApps();
|
||||
void clearAllConditions();
|
||||
void clearKeyWords();
|
||||
void clearSearchDir();
|
||||
void clearFileLabel();
|
||||
|
||||
bool setResultDataType(SearchType searchType, ResultDataTypes dataType);
|
||||
bool setCustomResultDataType(QString customSearchType, QStringList dataType);
|
||||
|
||||
/**
|
||||
* @brief 分页选项
|
||||
* @param first 指定起始位置
|
||||
|
@ -52,7 +59,7 @@ private:
|
|||
void copyData();
|
||||
//TODO: 这里是否可以改为字节对齐的写法?
|
||||
// DataQueue<ResultItem>* m_dataQueue = nullptr ;
|
||||
std::shared_ptr<DataQueue<ResultItem>> m_sharedDataueue = nullptr;
|
||||
std::shared_ptr<DataQueue<ResultItem>> m_sharedDataQueue = nullptr;
|
||||
size_t m_searchId = 0;
|
||||
QMutex m_searchIdMutex;
|
||||
SearchController *q = nullptr;
|
||||
|
@ -65,9 +72,13 @@ private:
|
|||
bool m_activeKeywordSegmentation = false;
|
||||
bool m_onlySearchFile = false;
|
||||
bool m_onlySearchDir = false;
|
||||
bool m_searchOnlineApps = false;
|
||||
|
||||
unsigned int m_first = 0;
|
||||
unsigned int m_maxResults = 100; //默认取100条结果
|
||||
|
||||
QMap<SearchType, ResultDataTypes> m_searchType2ResultDataType;
|
||||
QMap<QString, QStringList> m_customSearchType2ResultDataType;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -24,22 +24,22 @@ size_t SearchControllerPrivate::refreshSearchId()
|
|||
|
||||
DataQueue<ResultItem> *SearchControllerPrivate::refreshDataqueue()
|
||||
{
|
||||
if(!m_sharedDataueue.get()) {
|
||||
if(!m_sharedDataQueue.get()) {
|
||||
// m_dataQueue = new DataQueue<ResultItem>;
|
||||
m_sharedDataueue = std::make_shared<DataQueue<ResultItem>>();
|
||||
return m_sharedDataueue.get();
|
||||
m_sharedDataQueue = std::make_shared<DataQueue<ResultItem>>();
|
||||
return m_sharedDataQueue.get();
|
||||
}
|
||||
m_sharedDataueue.get()->clear();
|
||||
return m_sharedDataueue.get();
|
||||
m_sharedDataQueue.get()->clear();
|
||||
return m_sharedDataQueue.get();
|
||||
}
|
||||
|
||||
DataQueue<ResultItem> *SearchControllerPrivate::initDataQueue()
|
||||
{
|
||||
if(!m_sharedDataueue.get()) {
|
||||
m_sharedDataueue = std::make_shared<DataQueue<ResultItem>>();
|
||||
return m_sharedDataueue.get();
|
||||
if(!m_sharedDataQueue.get()) {
|
||||
m_sharedDataQueue = std::make_shared<DataQueue<ResultItem>>();
|
||||
return m_sharedDataQueue.get();
|
||||
}
|
||||
return m_sharedDataueue.get();
|
||||
return m_sharedDataQueue.get();
|
||||
}
|
||||
|
||||
void SearchControllerPrivate::addSearchDir(QString &path)
|
||||
|
@ -77,6 +77,11 @@ void SearchControllerPrivate::setOnlySearchDir(bool onlySearchDir)
|
|||
m_onlySearchDir = onlySearchDir;
|
||||
}
|
||||
|
||||
void SearchControllerPrivate::setSearchOnlineApps(bool searchOnlineApps)
|
||||
{
|
||||
m_searchOnlineApps = searchOnlineApps;
|
||||
}
|
||||
|
||||
size_t SearchControllerPrivate::getCurrentSearchId()
|
||||
{
|
||||
m_searchIdMutex.lock();
|
||||
|
@ -88,7 +93,17 @@ size_t SearchControllerPrivate::getCurrentSearchId()
|
|||
|
||||
DataQueue<ResultItem> *SearchControllerPrivate::getDataQueue()
|
||||
{
|
||||
return m_sharedDataueue.get();
|
||||
return m_sharedDataQueue.get();
|
||||
}
|
||||
|
||||
ResultDataTypes SearchControllerPrivate::getResultDataType(SearchType searchType)
|
||||
{
|
||||
return m_searchType2ResultDataType[searchType];
|
||||
}
|
||||
|
||||
QStringList SearchControllerPrivate::getCustomResultDataType(QString customSearchType)
|
||||
{
|
||||
return m_customSearchType2ResultDataType[customSearchType];
|
||||
}
|
||||
|
||||
bool SearchControllerPrivate::beginSearchIdCheck(size_t searchId)
|
||||
|
@ -151,13 +166,17 @@ bool SearchControllerPrivate::isSearchDirOnly()
|
|||
return m_onlySearchDir;
|
||||
}
|
||||
|
||||
bool SearchControllerPrivate::isSearchOnlineApps()
|
||||
{
|
||||
return m_searchOnlineApps;
|
||||
}
|
||||
|
||||
void SearchControllerPrivate::copyData()
|
||||
{
|
||||
|
||||
if(m_formerController.get()) {
|
||||
m_searchId = m_formerController.get()->getCurrentSearchId();
|
||||
//所有子节点都有一个指向根节点的队列的智能指针
|
||||
m_sharedDataueue = m_formerController.get()->d->m_sharedDataueue;
|
||||
m_sharedDataQueue = m_formerController.get()->d->m_sharedDataQueue;
|
||||
m_keywords = m_formerController.get()->getKeyword();
|
||||
m_searchDirs = m_formerController.get()->getSearchDir();
|
||||
m_FileLabels = m_formerController.get()->getFileLabel();
|
||||
|
@ -190,6 +209,20 @@ void SearchControllerPrivate::clearFileLabel()
|
|||
m_FileLabels.clear();
|
||||
}
|
||||
|
||||
bool SearchControllerPrivate::setResultDataType(SearchType searchType, ResultDataTypes dataType)
|
||||
{
|
||||
bool res(true);
|
||||
m_searchType2ResultDataType[searchType] = dataType;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool SearchControllerPrivate::setCustomResultDataType(QString customSearchType, QStringList dataType)
|
||||
{
|
||||
bool res(true);
|
||||
m_customSearchType2ResultDataType[customSearchType] = dataType;
|
||||
return res;
|
||||
}
|
||||
|
||||
void SearchControllerPrivate::setPagination(unsigned int first, unsigned int maxResults)
|
||||
{
|
||||
m_first = first;
|
||||
|
@ -258,6 +291,16 @@ DataQueue<ResultItem> *SearchController::getDataQueue()
|
|||
return d->getDataQueue();
|
||||
}
|
||||
|
||||
ResultDataTypes SearchController::getResultDataType(SearchType searchType)
|
||||
{
|
||||
return d->getResultDataType(searchType);
|
||||
}
|
||||
|
||||
QStringList SearchController::getCustomResultDataType(QString customSearchType)
|
||||
{
|
||||
return d->getCustomResultDataType(customSearchType);
|
||||
}
|
||||
|
||||
void SearchController::setActiveKeywordSegmentation(bool active)
|
||||
{
|
||||
d->setActiveKeywordSegmentation(active);
|
||||
|
@ -278,6 +321,11 @@ void SearchController::setOnlySearchDir(bool onlySearchDir)
|
|||
d->setOnlySearchDir(onlySearchDir);
|
||||
}
|
||||
|
||||
void SearchController::setSearchOnlineApps(bool searchOnlineApps)
|
||||
{
|
||||
d->setSearchOnlineApps(searchOnlineApps);
|
||||
}
|
||||
|
||||
bool SearchController::beginSearchIdCheck(size_t searchId)
|
||||
{
|
||||
return d->beginSearchIdCheck(searchId);
|
||||
|
@ -323,6 +371,11 @@ bool SearchController::isSearchDirOnly()
|
|||
return d->isSearchDirOnly();
|
||||
}
|
||||
|
||||
bool SearchController::isSearchOnlineApps()
|
||||
{
|
||||
return d->isSearchOnlineApps();
|
||||
}
|
||||
|
||||
void SearchController::stop()
|
||||
{
|
||||
d->stop();
|
||||
|
@ -362,3 +415,13 @@ unsigned int SearchController::maxResults() const
|
|||
{
|
||||
return d->maxResults();
|
||||
}
|
||||
|
||||
bool SearchController::setResultDataType(SearchType searchType, ResultDataTypes dataType)
|
||||
{
|
||||
return d->setResultDataType(searchType, dataType);
|
||||
}
|
||||
|
||||
bool SearchController::setCustomResultDataType(QString customSearchType, QStringList dataType)
|
||||
{
|
||||
return d->setCustomResultDataType(customSearchType, dataType);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <QStringList>
|
||||
#include <memory>
|
||||
#include "data-queue.h"
|
||||
#include "common-defines.h"
|
||||
//todo: url parser?
|
||||
namespace UkuiSearch {
|
||||
class UkuiSearchTask;
|
||||
|
@ -34,11 +35,14 @@ public:
|
|||
void addFileLabel(QString &label);
|
||||
void setOnlySearchFile(bool onlySearchFile);
|
||||
void setOnlySearchDir(bool onlySearchDir);
|
||||
void setSearchOnlineApps(bool searchOnlineApps);
|
||||
//以上方法插件请不要调用
|
||||
|
||||
//以下方法插件可以调用
|
||||
size_t getCurrentSearchId();
|
||||
DataQueue<ResultItem>* getDataQueue();
|
||||
ResultDataTypes getResultDataType(SearchType searchType);
|
||||
QStringList getCustomResultDataType(QString customSearchType);
|
||||
bool beginSearchIdCheck(size_t searchId);
|
||||
void finishSearchIdCheck();
|
||||
|
||||
|
@ -49,6 +53,7 @@ public:
|
|||
QStringList getFileLabel();
|
||||
bool isSearchFileOnly();
|
||||
bool isSearchDirOnly();
|
||||
bool isSearchOnlineApps();
|
||||
void clearAllConditions();
|
||||
void clearKeyWords();
|
||||
void clearSearchDir();
|
||||
|
@ -58,6 +63,8 @@ public:
|
|||
unsigned int first() const;
|
||||
unsigned int maxResults() const;
|
||||
|
||||
bool setResultDataType(SearchType searchType, ResultDataTypes dataType);
|
||||
bool setCustomResultDataType(QString customSearchType, QStringList dataType);
|
||||
private:
|
||||
std::shared_ptr<SearchController> m_parent = nullptr;
|
||||
SearchControllerPrivate *d = nullptr;
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
#include "app-search-task.h"
|
||||
#include "index-status-recorder.h"
|
||||
#include "common.h"
|
||||
#include <qt5xdg/XdgIcon>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QQueue>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace UkuiSearch;
|
||||
AppSearchTask::AppSearchTask(QObject *parent)
|
||||
{
|
||||
this->setParent(parent);
|
||||
qRegisterMetaType<size_t>("size_t");
|
||||
m_pool = new QThreadPool(this);
|
||||
m_pool->setMaxThreadCount(1);
|
||||
}
|
||||
|
||||
const QString AppSearchTask::name()
|
||||
{
|
||||
return tr("Application");
|
||||
}
|
||||
|
||||
const QString AppSearchTask::description()
|
||||
{
|
||||
return tr("Application search.");
|
||||
}
|
||||
|
||||
QString AppSearchTask::getCustomSearchType()
|
||||
{
|
||||
return "Application";
|
||||
}
|
||||
|
||||
void AppSearchTask::startSearch(std::shared_ptr<SearchController> searchController)
|
||||
{
|
||||
AppSearchWorker *appSearchWorker;
|
||||
appSearchWorker = new AppSearchWorker(this, searchController);
|
||||
m_pool->start(appSearchWorker);
|
||||
}
|
||||
|
||||
void AppSearchTask::stop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void AppSearchTask::sendFinishSignal(size_t searchId)
|
||||
{
|
||||
Q_EMIT searchFinished(searchId);
|
||||
}
|
||||
|
||||
|
||||
AppSearchWorker::AppSearchWorker(AppSearchTask *AppSarchTask, std::shared_ptr<SearchController> searchController) : m_AppSearchTask(AppSarchTask), m_searchController(searchController)
|
||||
{
|
||||
qDBusRegisterMetaType<QMap<QString, QString>>();
|
||||
qDBusRegisterMetaType<QList<QMap<QString, QString>>>();
|
||||
m_interFace = new QDBusInterface("com.kylin.softwarecenter.getsearchresults", "/com/kylin/softwarecenter/getsearchresults",
|
||||
"com.kylin.getsearchresults",
|
||||
QDBusConnection::sessionBus());
|
||||
if(!m_interFace->isValid()) {
|
||||
qWarning() << qPrintable(QDBusConnection::sessionBus().lastError().message());
|
||||
}
|
||||
m_interFace->setTimeout(1500);
|
||||
}
|
||||
|
||||
void AppSearchWorker::run()
|
||||
{
|
||||
m_currentSearchId = m_searchController->getCurrentSearchId();
|
||||
bool finished = true;
|
||||
QStringList results;
|
||||
QStringList keyWords = m_searchController->getKeyword();
|
||||
ResultDataTypes dataType = m_searchController->getResultDataType(SearchType::Application);
|
||||
m_appInfoTable.searchInstallApp(keyWords, results);
|
||||
for (int i = 0; i < results.size() / 3; i++) {
|
||||
if (m_searchController->beginSearchIdCheck(m_currentSearchId)) {
|
||||
QVariantList info;
|
||||
if (dataType & UkuiSearch::ApplicationDesktopPath) {
|
||||
info << QVariant(results.at(i*3));
|
||||
}
|
||||
if (dataType & UkuiSearch::ApplicationLocalName) {
|
||||
info << QVariant(results.at(i*3 + 1));
|
||||
}
|
||||
if (dataType & UkuiSearch::ApplicationIconName) {
|
||||
info << QVariant(XdgIcon::fromTheme(results.at(i*3 + 2)));
|
||||
}
|
||||
if (dataType & UkuiSearch::ApplicationDescription) {//本地应用暂无简介
|
||||
info << QVariant(QString());
|
||||
}
|
||||
if (dataType & UkuiSearch::IsOnlineApplication) {
|
||||
info << QVariant(0);
|
||||
}
|
||||
ResultItem ri(m_currentSearchId, results.at(i*3), info);
|
||||
m_searchController->getDataQueue()->enqueue(ri);
|
||||
m_searchController->finishSearchIdCheck();
|
||||
} else {
|
||||
qDebug() << "Search id changed!";
|
||||
m_searchController->finishSearchIdCheck();
|
||||
}
|
||||
}
|
||||
if (m_searchController->isSearchOnlineApps()) {
|
||||
//online app search
|
||||
for (auto keyword : keyWords) {
|
||||
QDBusReply<QList<QMap<QString, QString>>> reply = m_interFace->call("get_search_result", keyword); //阻塞,直到远程方法调用完成。
|
||||
if(reply.isValid()) {
|
||||
for(int i = 0; i < reply.value().size(); i++) {
|
||||
if (m_searchController->beginSearchIdCheck(m_currentSearchId)) {
|
||||
QVariantList info;
|
||||
if (dataType & UkuiSearch::ApplicationDesktopPath) {
|
||||
info << QVariant(reply.value().at(i).value("appname"));
|
||||
}
|
||||
if (dataType & UkuiSearch::ApplicationLocalName) {
|
||||
QLocale locale;
|
||||
if(locale.language() == QLocale::Chinese) {
|
||||
info << QVariant(reply.value().at(i).value("displayname_cn"));
|
||||
} else {
|
||||
info << QVariant(reply.value().at(i).value("appname"));
|
||||
}
|
||||
}
|
||||
if (dataType & UkuiSearch::ApplicationIconName) {
|
||||
info << QVariant(QIcon(reply.value().at(i).value("icon")));
|
||||
}
|
||||
if (dataType & UkuiSearch::ApplicationDescription) {//在线应用有效
|
||||
info << QVariant(reply.value().at(i).value("discription"));
|
||||
}
|
||||
if (dataType & UkuiSearch::IsOnlineApplication) {
|
||||
info << QVariant(1);
|
||||
}
|
||||
ResultItem ri(m_currentSearchId, reply.value().at(i).value("appname"), info);
|
||||
m_searchController->getDataQueue()->enqueue(ri);
|
||||
m_searchController->finishSearchIdCheck();
|
||||
} else {
|
||||
qDebug() << "Search id changed!";
|
||||
m_searchController->finishSearchIdCheck();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qWarning() << "SoftWareCenter dbus called failed!";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (finished) QMetaObject::invokeMethod(m_AppSearchTask, "searchFinished", Q_ARG(size_t, m_currentSearchId));
|
||||
}
|
||||
|
||||
AppSearchWorker::~AppSearchWorker()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void AppSearchWorker::sendErrorMsg(const QString &msg)
|
||||
{
|
||||
QMetaObject::invokeMethod(m_AppSearchTask, "searchError",
|
||||
Q_ARG(size_t, m_currentSearchId),
|
||||
Q_ARG(QString, msg));
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef APPSEARCHTASK_H
|
||||
#define APPSEARCHTASK_H
|
||||
|
||||
#include <QIcon>
|
||||
#include <QThreadPool>
|
||||
#include <QRunnable>
|
||||
#include <QDBusInterface>
|
||||
#include <QtDBus>
|
||||
#include "search-task-plugin-iface.h"
|
||||
#include "search-controller.h"
|
||||
#include "result-item.h"
|
||||
#include "app-info-table.h"
|
||||
|
||||
namespace UkuiSearch {
|
||||
class AppSearchTask : public SearchTaskPluginIface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AppSearchTask(QObject *parent);
|
||||
PluginType pluginType() {return PluginType::SearchTaskPlugin;}
|
||||
const QString name();
|
||||
const QString description();
|
||||
const QIcon icon() {return QIcon::fromTheme("appsearch");}
|
||||
void setEnable(bool enable) {}
|
||||
bool isEnable() { return true;}
|
||||
|
||||
SearchType getSearchType() {return SearchType::Application;}
|
||||
QString getCustomSearchType();
|
||||
void startSearch(std::shared_ptr<SearchController> searchController);
|
||||
void stop();
|
||||
Q_INVOKABLE void sendFinishSignal(size_t searchId);
|
||||
|
||||
private:
|
||||
QThreadPool *m_pool = nullptr;
|
||||
};
|
||||
|
||||
class AppSearchWorker : public QRunnable
|
||||
{
|
||||
public:
|
||||
explicit AppSearchWorker(AppSearchTask *AppSarchTask, std::shared_ptr<SearchController> searchController);
|
||||
|
||||
protected:
|
||||
void run();
|
||||
|
||||
private:
|
||||
~AppSearchWorker();
|
||||
void sendErrorMsg(const QString &msg);
|
||||
|
||||
private:
|
||||
AppInfoTable m_appInfoTable;
|
||||
AppSearchTask *m_AppSearchTask = nullptr;
|
||||
std::shared_ptr<SearchController> m_searchController;
|
||||
QDBusInterface *m_interFace = nullptr;
|
||||
size_t m_currentSearchId = 0;
|
||||
};
|
||||
}
|
||||
#endif // APPSEARCHTASK_H
|
|
@ -52,12 +52,12 @@ const QIcon FileContentSearchTask::icon()
|
|||
|
||||
void FileContentSearchTask::setEnable(bool enable)
|
||||
{
|
||||
e_enable = enable;
|
||||
m_enable = enable;
|
||||
}
|
||||
|
||||
bool FileContentSearchTask::isEnable()
|
||||
{
|
||||
return e_enable && IndexStatusRecorder::getInstance()->contentIndexDatabaseEnable();
|
||||
return m_enable && IndexStatusRecorder::getInstance()->contentIndexDatabaseEnable();
|
||||
}
|
||||
|
||||
QString FileContentSearchTask::getCustomSearchType()
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
|
||||
private:
|
||||
QThreadPool *m_pool = nullptr;
|
||||
bool e_enable = true;
|
||||
bool m_enable = true;
|
||||
};
|
||||
|
||||
class FileContentSearchWorker : public QRunnable
|
||||
|
|
|
@ -11,9 +11,6 @@
|
|||
#include "result-item.h"
|
||||
|
||||
namespace UkuiSearch {
|
||||
/*
|
||||
* 这里只写了大概框架,具体逻辑未实现,可以当成伪代码参考。
|
||||
*/
|
||||
class FileSearchTask : public SearchTaskPluginIface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
@ -2,10 +2,12 @@ INCLUDEPATH += $$PWD
|
|||
|
||||
HEADERS += \
|
||||
$$PWD/file-search-task.h \
|
||||
$$PWD/file-content-search-task.h
|
||||
$$PWD/file-content-search-task.h \
|
||||
$$PWD/app-search-task.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/file-search-task.cpp \
|
||||
$$PWD/file-content-search-task.cpp
|
||||
$$PWD/file-content-search-task.cpp \
|
||||
$$PWD/app-search-task.cpp
|
||||
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@ public:
|
|||
void setOnlySearchDir(bool onlySearchDir);
|
||||
void setSearchOnlineApps(bool searchOnlineApps);
|
||||
void initSearchPlugin(SearchType searchType, const QString& customSearchType = QString());
|
||||
bool setResultDataType(SearchType searchType, ResultDataTypes dataType);
|
||||
bool setCustomResultDataType(QString customSearchType, QStringList dataType);
|
||||
void clearAllConditions();
|
||||
void clearKeyWords();
|
||||
void clearSearchDir();
|
||||
|
|
|
@ -54,6 +54,7 @@ void UkuiSearchTaskPrivate::setOnlySearchDir(bool onlySearchDir)
|
|||
|
||||
void UkuiSearchTaskPrivate::setSearchOnlineApps(bool searchOnlineApps)
|
||||
{
|
||||
m_searchCotroller->setSearchOnlineApps(searchOnlineApps);
|
||||
}
|
||||
|
||||
void UkuiSearchTaskPrivate::initSearchPlugin(SearchType searchType, const QString& customSearchType)
|
||||
|
@ -67,6 +68,17 @@ void UkuiSearchTaskPrivate::initSearchPlugin(SearchType searchType, const QStrin
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
bool UkuiSearchTaskPrivate::setCustomResultDataType(QString customSearchType, QStringList dataType)
|
||||
{
|
||||
return m_searchCotroller->setCustomResultDataType(customSearchType, dataType);
|
||||
}
|
||||
|
||||
bool UkuiSearchTaskPrivate::setResultDataType(SearchType searchType, ResultDataTypes dataType)
|
||||
{
|
||||
return m_searchCotroller->setResultDataType(searchType, dataType);
|
||||
}
|
||||
|
||||
size_t UkuiSearchTaskPrivate::startSearch(SearchType searchtype, const QString& customSearchType)
|
||||
{
|
||||
m_searchId = m_searchCotroller->refreshSearchId();
|
||||
|
@ -167,6 +179,16 @@ void UkuiSearchTask::initSearchPlugin(SearchType searchType)
|
|||
d->initSearchPlugin(searchType);
|
||||
}
|
||||
|
||||
bool UkuiSearchTask::setResultDataType(SearchType searchType, ResultDataTypes dataType)
|
||||
{
|
||||
return d->setResultDataType(searchType, dataType);
|
||||
}
|
||||
|
||||
bool UkuiSearchTask::setCustomResultDataType(QString customSearchType, QStringList dataType)
|
||||
{
|
||||
return d->setCustomResultDataType(customSearchType, dataType);
|
||||
}
|
||||
|
||||
size_t UkuiSearchTask::startSearch(SearchType searchtype, QString customSearchType)
|
||||
{
|
||||
return d->startSearch(searchtype, customSearchType);
|
||||
|
|
|
@ -21,6 +21,15 @@ public:
|
|||
void setOnlySearchDir(bool onlySearchDir);
|
||||
void setSearchOnlineApps(bool searchOnlineApps);
|
||||
void initSearchPlugin(SearchType searchType);
|
||||
/**
|
||||
* @brief setResultDataType
|
||||
* @param searchType
|
||||
* @param dataType
|
||||
* @return
|
||||
*/
|
||||
bool setResultDataType(SearchType searchType, UkuiSearch::ResultDataTypes dataType);
|
||||
bool setCustomResultDataType(QString customSearchType, QStringList dataType);
|
||||
|
||||
void clearAllConditions();
|
||||
void clearKeyWords();
|
||||
void clearSearchDir();
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef APPDBCOMMONDEFINES_H
|
||||
#define APPDBCOMMONDEFINES_H
|
||||
#include <QDir>
|
||||
|
||||
namespace UkuiSearch {
|
||||
|
||||
#define APP_DATABASE_PATH QDir::homePath()+"/.config/org.ukui/ukui-search/appdata/"
|
||||
#define APP_DATABASE_NAME "app-info.db"
|
||||
|
||||
}
|
||||
#endif // APPDBCOMMONDEFINES_H
|
|
@ -0,0 +1,490 @@
|
|||
#include <qt5xdg/XdgDesktopFile>
|
||||
#include <QMutexLocker>
|
||||
#include <QCryptographicHash>
|
||||
#include <QFile>
|
||||
#include "app-db-manager.h"
|
||||
#include "../libsearch/file-utils.h"
|
||||
using namespace UkuiSearch;
|
||||
#define GENERAL_APP_DESKTOP_PATH "/usr/share/applications/"
|
||||
#define ANDROID_APP_DESKTOP_PATH QDir::homePath() + "/.local/share/applications/"
|
||||
#define SNAPD_APP_DESKTOP_PATH "/var/lib/snapd/desktop/applications/"
|
||||
|
||||
static AppDBManager *global_instance = AppDBManager::getInstance();
|
||||
QMutex AppDBManager::s_installAppMapMutex;
|
||||
AppDBManager *AppDBManager::getInstance()
|
||||
{
|
||||
if (!global_instance) {
|
||||
global_instance = new AppDBManager();
|
||||
}
|
||||
return global_instance;
|
||||
}
|
||||
AppDBManager::AppDBManager(QObject *parent) : QObject(parent), m_database(new QSqlDatabase)
|
||||
{
|
||||
openDataBase();
|
||||
m_watchAppDir = new QFileSystemWatcher(this);
|
||||
m_watchAppDir->addPath(GENERAL_APP_DESKTOP_PATH);
|
||||
QDir androidPath(ANDROID_APP_DESKTOP_PATH);
|
||||
if(!androidPath.exists()) {
|
||||
androidPath.mkpath(ANDROID_APP_DESKTOP_PATH);
|
||||
}
|
||||
m_watchAppDir->addPath(ANDROID_APP_DESKTOP_PATH);
|
||||
|
||||
QDir snapdPath(SNAPD_APP_DESKTOP_PATH);
|
||||
if(!snapdPath.exists()) {
|
||||
snapdPath.mkpath(SNAPD_APP_DESKTOP_PATH);
|
||||
}
|
||||
m_watchAppDir->addPath(SNAPD_APP_DESKTOP_PATH);
|
||||
|
||||
initDateBaseConnection();
|
||||
|
||||
connect(m_watchAppDir, &QFileSystemWatcher::directoryChanged, this, [ = ](const QString & path) {
|
||||
qDebug() << "m_watchAppDir directoryChanged:" << path;
|
||||
if (m_database->transaction()) {
|
||||
this->updateAppInfoDB();
|
||||
if (!m_database->commit()) {
|
||||
qWarning() << "Failed to commit !";
|
||||
m_database->rollback();
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Failed to start transaction mode!!!";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AppDBManager::~AppDBManager()
|
||||
{
|
||||
if(m_watchAppDir) {
|
||||
delete m_watchAppDir;
|
||||
}
|
||||
m_watchAppDir = NULL;
|
||||
closeDataBase();
|
||||
}
|
||||
|
||||
void AppDBManager::buildAppInfoDB()
|
||||
{
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("CREATE TABLE IF NOT EXISTS appInfo(%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12,%13,%14,%15,%16,%17,%18,%19,%20)")
|
||||
// .arg("ID INT")//自增id
|
||||
.arg("DESKTOP_FILE_PATH TEXT")//desktop文件路径
|
||||
.arg("MODIFYED_TIME TEXT")//YYYYMMDDHHmmSS 修改日期
|
||||
.arg("INSERT_TIME TEXT")//YYYYMMDDHHmmSS 插入日期
|
||||
.arg("LOCAL_NAME TEXT")//本地名称,跟随系统语言
|
||||
.arg("NAME_EN TEXT")//应用英文名称
|
||||
.arg("NAME_ZH TEXT")//应用中文名称
|
||||
.arg("PINYIN_NAME TEXT")//中文拼音
|
||||
.arg("FIRST_LETTER_OF_PINYIN TEXT")//中文拼音首字母
|
||||
.arg("ICON TEXT")//图标名称(或路径)
|
||||
.arg("TYPE TEXT")//应用类型
|
||||
.arg("CATEGORY TEXT")//应用分类
|
||||
.arg("EXEC TEXT")//应用命令
|
||||
.arg("COMMENT TEXT")//应用注释
|
||||
.arg("MD5 TEXT")//desktop文件内容md5值
|
||||
.arg("LAUNCH_TIMES INT")//应用打开次数, 等比例缩减
|
||||
.arg("FAVORITES INT")//收藏顺序0:为收藏,>0的数字表示收藏顺序
|
||||
.arg("LAUNCHED INT")//应用安装后是否打开过0:未打开过;1:打开过
|
||||
.arg("TOP INT")//置顶顺序 0:未置顶;>0的数字表示置顶顺序
|
||||
.arg("LOCK INT")//应用是否锁定(管控),0未锁定,1锁定
|
||||
.arg("PRIMARY KEY (DESKTOP_FILE_PATH)");
|
||||
|
||||
if (!sql.exec(cmd)) {
|
||||
qWarning() << m_database->lastError() << cmd;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AppDBManager::updateAppInfoDB()
|
||||
{
|
||||
QMutexLocker locker(&s_installAppMapMutex);
|
||||
m_installAppMap.clear();
|
||||
this->getAllDesktopFilePath(GENERAL_APP_DESKTOP_PATH);
|
||||
this->getAllDesktopFilePath(ANDROID_APP_DESKTOP_PATH);
|
||||
this->getAllDesktopFilePath(SNAPD_APP_DESKTOP_PATH);
|
||||
QStringList filePathList;
|
||||
this->getFilePathList(filePathList);
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd;
|
||||
if (!sql.exec("SELECT COUNT(*) FROM appInfo")) {
|
||||
this->buildAppInfoDB();
|
||||
for (auto &filePath : filePathList) {
|
||||
this->addAppDesktopFile2DB(filePath);
|
||||
}
|
||||
} else {
|
||||
cmd = QString("SELECT COUNT(*) FROM appInfo");
|
||||
if (sql.exec(cmd)) {
|
||||
if (sql.next()) {
|
||||
if (sql.value(0).toInt() > filePathList.size()) {
|
||||
int size = sql.value(0).toInt();
|
||||
cmd = QString("SELECT DESKTOP_FILE_PATH FROM appInfo");
|
||||
if (!sql.exec(cmd)) {
|
||||
qWarning() << m_database->lastError() << cmd;
|
||||
return;
|
||||
}
|
||||
QString path;
|
||||
for (int i = 0; i<size; ++i) {
|
||||
if (!sql.next()) {
|
||||
qWarning() << m_database->lastError() << cmd;
|
||||
return;
|
||||
}
|
||||
path = sql.value(0).toString();
|
||||
if (!filePathList.contains(path)) {
|
||||
this->deleteAppDesktopFile2DB(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (QString &filePath:filePathList) {
|
||||
cmd = QString("SELECT COUNT(*) FROM appInfo WHERE DESKTOP_FILE_PATH = '%0'").arg(filePath);
|
||||
if (sql.exec(cmd)) {
|
||||
if (sql.next()) {
|
||||
if (sql.value(0).toInt() == 0) {
|
||||
this->addAppDesktopFile2DB(filePath);
|
||||
} else {
|
||||
cmd = QString("SELECT MD5 FROM appInfo WHERE DESKTOP_FILE_PATH = '%0'").arg(filePath);
|
||||
if (!sql.exec(cmd)) {
|
||||
qWarning() << m_database->lastError() << cmd;
|
||||
return;
|
||||
}
|
||||
if (!sql.next()) {
|
||||
qWarning() << m_database->lastError() << cmd;
|
||||
return;
|
||||
}
|
||||
if (sql.value(0).toString() != getAppDesktopMd5(filePath)) {
|
||||
this->updateAppDesktopFile2DB(filePath);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qWarning() << m_database->lastError() << cmd;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
qWarning() << m_database->lastError() << cmd;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qWarning() << m_database->lastError() << cmd;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
qWarning() << m_database->lastError() << cmd;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AppDBManager::getFilePathList(QStringList &pathList)
|
||||
{
|
||||
for (auto i=m_installAppMap.begin(); i!=m_installAppMap.end(); ++i) {
|
||||
pathList.append(i.value().at(0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief AppMatch::getAllDesktopFilePath 遍历所有desktop文件
|
||||
* @param path 存放desktop文件夹
|
||||
*/
|
||||
void AppDBManager::getAllDesktopFilePath(QString path) {
|
||||
|
||||
QDir dir(path);
|
||||
if(!dir.exists()) {
|
||||
return;
|
||||
}
|
||||
dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
|
||||
dir.setSorting(QDir::DirsFirst);
|
||||
QFileInfoList list = dir.entryInfoList();
|
||||
list.removeAll(QFileInfo("/usr/share/applications/screensavers"));
|
||||
if(list.size() < 1) {
|
||||
return;
|
||||
}
|
||||
XdgDesktopFile desktopfile;
|
||||
int i = 0;
|
||||
while(i < list.size()) {
|
||||
QFileInfo fileInfo = list.at(i);
|
||||
//如果是文件夹,递归
|
||||
bool isDir = fileInfo.isDir();
|
||||
if(isDir) {
|
||||
getAllDesktopFilePath(fileInfo.filePath());
|
||||
qDebug() << fileInfo.filePath();
|
||||
++i;
|
||||
} else {
|
||||
QString filePathStr = fileInfo.filePath();
|
||||
if(m_excludedDesktopfiles.contains(filePathStr)) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
//过滤后缀不是.desktop的文件
|
||||
if(!filePathStr.endsWith(".desktop")) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
desktopfile.load(filePathStr);
|
||||
if(desktopfile.value("NoDisplay").toString().contains("true") || desktopfile.value("NotShowIn").toString().contains("UKUI")) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
QString name = desktopfile.localizedValue("Name").toString();
|
||||
if(name.isEmpty()) {
|
||||
++i;
|
||||
qDebug() << filePathStr << "name!!";
|
||||
continue;
|
||||
}
|
||||
|
||||
QString icon = desktopfile.iconName();
|
||||
NameString appname;
|
||||
QStringList appInfolist;
|
||||
|
||||
appname.app_name = name;
|
||||
appInfolist << filePathStr << icon;
|
||||
appInfolist.append(desktopfile.value("Name").toString());
|
||||
appInfolist.append(desktopfile.value("Name[zh_CN]").toString());
|
||||
m_installAppMap.insert(appname, appInfolist);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AppDBManager::initDateBaseConnection()
|
||||
{
|
||||
if (m_database->transaction()) {
|
||||
this->updateAppInfoDB();
|
||||
if (!m_database->commit()) {
|
||||
qWarning() << "Failed to commit !";
|
||||
m_database->rollback();
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Failed to start transaction mode!!!";
|
||||
}
|
||||
}
|
||||
|
||||
void AppDBManager::openDataBase()
|
||||
{
|
||||
QDir dir;
|
||||
if (!dir.exists(APP_DATABASE_PATH)) {
|
||||
dir.mkpath(APP_DATABASE_PATH);
|
||||
}
|
||||
if (QSqlDatabase::contains(CONNECTION_NAME)) {
|
||||
*m_database = QSqlDatabase::database(CONNECTION_NAME);
|
||||
} else {
|
||||
*m_database = QSqlDatabase::addDatabase("QSQLITE", CONNECTION_NAME);
|
||||
m_database->setDatabaseName(APP_DATABASE_PATH + APP_DATABASE_NAME);
|
||||
}
|
||||
if(!m_database->open()) {
|
||||
qWarning() << m_database->lastError();
|
||||
QApplication::quit();
|
||||
}
|
||||
}
|
||||
|
||||
void AppDBManager::closeDataBase()
|
||||
{
|
||||
m_database->close();
|
||||
delete m_database;
|
||||
QSqlDatabase::removeDatabase(CONNECTION_NAME);
|
||||
}
|
||||
|
||||
QString AppDBManager::getAppDesktopMd5(QString &desktopfd)
|
||||
{
|
||||
QString res;
|
||||
QFile file(desktopfd);
|
||||
file.open(QIODevice::ReadOnly);
|
||||
res = QString::fromStdString(QCryptographicHash::hash(file.readAll(), QCryptographicHash::Md5).toHex().toStdString());
|
||||
file.close();
|
||||
return res;
|
||||
}
|
||||
|
||||
void AppDBManager::getInstallAppMap(QMap<QString, QStringList> &installAppMap)
|
||||
{
|
||||
QMutexLocker locker(&s_installAppMapMutex);
|
||||
for (auto i=m_installAppMap.begin(); i!=m_installAppMap.end(); ++i) {
|
||||
installAppMap[i.key().app_name] = i.value();
|
||||
}
|
||||
installAppMap.detach();
|
||||
}
|
||||
|
||||
bool AppDBManager::addAppDesktopFile2DB(QString &desktopfd)
|
||||
{
|
||||
bool res(true);
|
||||
QSqlQuery sql(*m_database);
|
||||
XdgDesktopFile desktopfile;
|
||||
desktopfile.load(desktopfd);
|
||||
QString hanzi, pinyin, firstLetterOfPinyin;
|
||||
bool isHanzi = true;
|
||||
if (desktopfile.contains("Name[zh_CN]")) {
|
||||
hanzi = desktopfile.value("Name[zh_CN]").toString();
|
||||
} else {
|
||||
hanzi = desktopfile.value("Name").toString();
|
||||
if (!hanzi.contains(QRegExp("[\\x4e00-\\x9fa5]+"))) {
|
||||
isHanzi = false;
|
||||
}
|
||||
}
|
||||
if (isHanzi) {
|
||||
QStringList pinyinList = FileUtils::findMultiToneWords(hanzi);
|
||||
for (int i = 0; i<pinyinList.size(); ++i) {
|
||||
if (i%2) {
|
||||
firstLetterOfPinyin += pinyinList.at(i);
|
||||
} else {
|
||||
pinyin += pinyinList.at(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString cmd = QString("INSERT INTO appInfo "
|
||||
"(DESKTOP_FILE_PATH,MODIFYED_TIME,INSERT_TIME,LOCAL_NAME,NAME_EN,NAME_ZH,PINYIN_NAME,FIRST_LETTER_OF_PINYIN,ICON,TYPE,CATEGORY,EXEC,COMMENT,MD5,LAUNCH_TIMES,FAVORITES,LAUNCHED,TOP,LOCK) "
|
||||
"VALUES('%1','%2','%3','%4','%5','%6','%7','%8','%9','%10','%11','%12','%13','%14',%15,%16,%17,%18,%19)")
|
||||
.arg(desktopfd)
|
||||
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
|
||||
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
|
||||
.arg(desktopfile.localizedValue("Name").toString())
|
||||
.arg(desktopfile.value("Name").toString())
|
||||
.arg(hanzi)
|
||||
.arg(pinyin)
|
||||
.arg(firstLetterOfPinyin)
|
||||
.arg(desktopfile.value("Icon").toString())
|
||||
.arg(desktopfile.value("Type").toString())
|
||||
.arg(desktopfile.value("Categories").toString())
|
||||
.arg(desktopfile.value("Exec").toString())
|
||||
.arg(desktopfile.value("Comment").toString())
|
||||
.arg(getAppDesktopMd5(desktopfd))
|
||||
.arg(0)
|
||||
.arg(0)
|
||||
.arg(0)
|
||||
.arg(0)
|
||||
.arg(0);
|
||||
if (!sql.exec(cmd)) {
|
||||
qWarning() << m_database->lastError() << cmd;
|
||||
res = false;
|
||||
}
|
||||
if (res) {
|
||||
qDebug() << "app database add " << desktopfd << "success!";
|
||||
} else {
|
||||
qDebug() << "app database add " << desktopfd << "failed!";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool AppDBManager::deleteAppDesktopFile2DB(QString &desktopfd)
|
||||
{
|
||||
bool res(true);
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("DELETE FROM appInfo WHERE DESKTOP_FILE_PATH = '%0'").arg(desktopfd);
|
||||
if (!sql.exec(cmd)) {
|
||||
qWarning() << m_database->lastError() << cmd;
|
||||
res = false;
|
||||
}
|
||||
if (res) {
|
||||
qDebug() << "app database delete " << desktopfd << "success!";
|
||||
} else {
|
||||
qDebug() << "app database delete " << desktopfd << "failed!";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool AppDBManager::updateAppDesktopFile2DB(QString &desktopfd)
|
||||
{
|
||||
bool res(true);
|
||||
XdgDesktopFile desktopfile;
|
||||
desktopfile.load(desktopfd);
|
||||
if(desktopfile.value("NoDisplay").toString().contains("true") || desktopfile.value("NotShowIn").toString().contains("UKUI")) {
|
||||
qDebug() << "app" << desktopfd << "is changed, NoDisplay or NotShowIn is working!";
|
||||
return this->deleteAppDesktopFile2DB(desktopfd);
|
||||
}
|
||||
QString hanzi, pinyin, firstLetterOfPinyin;
|
||||
bool isHanzi = true;
|
||||
if (desktopfile.contains("Name[zh_CN]")) {
|
||||
hanzi = desktopfile.value("Name[zh_CN]").toString();
|
||||
} else {
|
||||
hanzi = desktopfile.value("Name").toString();
|
||||
if (!hanzi.contains(QRegExp("[\\x4e00-\\x9fa5]+"))) {
|
||||
isHanzi = false;
|
||||
}
|
||||
}
|
||||
if (isHanzi) {
|
||||
QStringList pinyinList = FileUtils::findMultiToneWords(hanzi);
|
||||
for (int i = 0; i<pinyinList.size(); ++i) {
|
||||
if (i%2) {
|
||||
firstLetterOfPinyin += pinyinList.at(i);
|
||||
} else {
|
||||
pinyin += pinyinList.at(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("UPDATE appInfo SET "
|
||||
"MODIFYED_TIME='%0',"
|
||||
"LOCAL_NAME='%1',"
|
||||
"NAME_EN='%2',"
|
||||
"NAME_ZH='%3'"
|
||||
",PINYIN_NAME='%4',"
|
||||
"FIRST_LETTER_OF_PINYIN='%5',"
|
||||
"ICON='%6',"
|
||||
"TYPE='%7',"
|
||||
"CATEGORY='%8',"
|
||||
"EXEC='%9',"
|
||||
"COMMENT='%10',"
|
||||
"MD5='%11' "
|
||||
"WHERE DESKTOP_FILE_PATH='%12'")
|
||||
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
|
||||
.arg(desktopfile.localizedValue("Name").toString())
|
||||
.arg(desktopfile.value("Name").toString())
|
||||
.arg(hanzi)
|
||||
.arg(pinyin)
|
||||
.arg(firstLetterOfPinyin)
|
||||
.arg(desktopfile.value("Icon").toString())
|
||||
.arg(desktopfile.value("Type").toString())
|
||||
.arg(desktopfile.value("Categories").toString())
|
||||
.arg(desktopfile.value("Exec").toString())
|
||||
.arg(desktopfile.value("Comment").toString())
|
||||
.arg(getAppDesktopMd5(desktopfd))
|
||||
.arg(desktopfd);
|
||||
if (!sql.exec(cmd)) {
|
||||
qWarning() << m_database->lastError() << cmd;
|
||||
res = false;
|
||||
}
|
||||
if (res) {
|
||||
qDebug() << "app database update " << desktopfd << "success!";
|
||||
} else {
|
||||
qDebug() << "app database update " << desktopfd << "failed!";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool AppDBManager::updateAppLaunchTimes(QString &desktopfp)
|
||||
{
|
||||
bool res(true);
|
||||
if (m_database->transaction()) {
|
||||
QSqlQuery sql(*m_database);
|
||||
QString cmd = QString("SELECT LAUNCH_TIMES FROM appInfo WHERE DESKTOP_FILE_PATH='%1'").arg(desktopfp);
|
||||
if (sql.exec(cmd)) {
|
||||
if (sql.next()) {
|
||||
cmd = QString("UPDATE appInfo SET MODIFYED_TIME='%0', LAUNCH_TIMES=%1, LAUNCHED=%2 WHERE DESKTOP_FILE_PATH='%3'")
|
||||
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
|
||||
.arg(sql.value(0).toInt() + 1)
|
||||
.arg(1)
|
||||
.arg(desktopfp);
|
||||
if (!sql.exec(cmd)) {
|
||||
qWarning() << "Set app favorites state failed!" << m_database->lastError();
|
||||
res = false;
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Failed to exec next!" << cmd;
|
||||
res = false;
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Failed to exec:" << cmd;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
#ifndef APPDBMANAGER_H
|
||||
#define APPDBMANAGER_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QObject>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include <QDebug>
|
||||
#include <QApplication>
|
||||
#include <QDateTime>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QMutex>
|
||||
#include "app-db-common-defines.h"
|
||||
|
||||
#define CONNECTION_NAME QLatin1String("ukss-appdb-connection")
|
||||
|
||||
namespace UkuiSearch {
|
||||
/**
|
||||
* @brief The AppDBManager class
|
||||
* 功能:1.遍历并且监听desktop文件目录,建立并且维护应用信息数据库。
|
||||
* 2.监听应用安装,打开事件,收藏等事件,更新数据库
|
||||
*/
|
||||
class NameString {
|
||||
public:
|
||||
explicit NameString(const QString &str_) : app_name(str_) {}
|
||||
NameString() = default;
|
||||
QString app_name;
|
||||
bool operator<(const NameString& name) const {
|
||||
return this->app_name.length() <= name.app_name.length();
|
||||
}
|
||||
bool operator==(const NameString& name) const {
|
||||
return this->app_name == name.app_name;
|
||||
}
|
||||
};
|
||||
|
||||
class AppDBManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
enum APP_LOCK_STATE{
|
||||
APP_UNLOCK = 0,
|
||||
APP_LOCK
|
||||
};
|
||||
|
||||
public:
|
||||
static AppDBManager *getInstance();
|
||||
|
||||
QString getAppDesktopMd5(QString &desktopfd);
|
||||
|
||||
void getInstallAppMap(QMap<QString, QStringList> &installAppMap);
|
||||
|
||||
bool addAppDesktopFile2DB(QString &desktopfd);
|
||||
bool deleteAppDesktopFile2DB(QString &desktopfd);
|
||||
bool updateAppDesktopFile2DB(QString &desktopfd);
|
||||
bool updateAppLaunchTimes(QString &desktopfp);
|
||||
|
||||
private:
|
||||
explicit AppDBManager(QObject *parent = nullptr);
|
||||
~AppDBManager();
|
||||
|
||||
void getAllDesktopFilePath(QString path);
|
||||
|
||||
void initDateBaseConnection();
|
||||
void openDataBase();
|
||||
void closeDataBase();
|
||||
|
||||
void buildAppInfoDB();
|
||||
void updateAppInfoDB();
|
||||
void getFilePathList(QStringList &pathList);
|
||||
|
||||
QSqlDatabase *m_database = nullptr;
|
||||
|
||||
QFileSystemWatcher *m_watchAppDir = nullptr;
|
||||
|
||||
static QMutex s_installAppMapMutex;
|
||||
QMap<NameString, QStringList> m_installAppMap;
|
||||
|
||||
QStringList m_excludedDesktopfiles = {
|
||||
"/usr/share/applications/software-properties-livepatch.desktop",
|
||||
"/usr/share/applications/mate-color-select.desktop",
|
||||
"/usr/share/applications/blueman-adapters.desktop",
|
||||
"/usr/share/applications/blueman-manager.desktop",
|
||||
"/usr/share/applications/mate-user-guide.desktop",
|
||||
"/usr/share/applications/nm-connection-editor.desktop",
|
||||
"/usr/share/applications/debian-uxterm.desktop",
|
||||
"/usr/share/applications/debian-xterm.desktop",
|
||||
"/usr/share/applications/im-config.desktop",
|
||||
"/usr/share/applications/fcitx.desktop",
|
||||
"/usr/share/applications/fcitx-configtool.desktop",
|
||||
"/usr/share/applications/onboard-settings.desktop",
|
||||
"/usr/share/applications/info.desktop",
|
||||
"/usr/share/applications/ukui-power-preferences.desktop",
|
||||
"/usr/share/applications/ukui-power-statistics.desktop",
|
||||
"/usr/share/applications/software-properties-drivers.desktop",
|
||||
"/usr/share/applications/software-properties-gtk.desktop",
|
||||
"/usr/share/applications/gnome-session-properties.desktop",
|
||||
"/usr/share/applications/org.gnome.font-viewer.desktop",
|
||||
"/usr/share/applications/xdiagnose.desktop",
|
||||
"/usr/share/applications/gnome-language-selector.desktop",
|
||||
"/usr/share/applications/mate-notification-properties.desktop",
|
||||
"/usr/share/applications/transmission-gtk.desktop",
|
||||
"/usr/share/applications/mpv.desktop",
|
||||
"/usr/share/applications/system-config-printer.desktop",
|
||||
"/usr/share/applications/org.gnome.DejaDup.desktop",
|
||||
"/usr/share/applications/yelp.desktop",
|
||||
"/usr/share/applications/peony-computer.desktop",
|
||||
"/usr/share/applications/peony-home.desktop",
|
||||
"/usr/share/applications/peony-trash.desktop",
|
||||
|
||||
//v10
|
||||
"/usr/share/applications/mate-about.desktop",
|
||||
"/usr/share/applications/time.desktop",
|
||||
"/usr/share/applications/network.desktop",
|
||||
"/usr/share/applications/shares.desktop",
|
||||
"/usr/share/applications/mate-power-statistics.desktop",
|
||||
"/usr/share/applications/display-im6.desktop",
|
||||
"/usr/share/applications/display-im6.q16.desktop",
|
||||
"/usr/share/applications/openjdk-8-policytool.desktop",
|
||||
"/usr/share/applications/kylin-io-monitor.desktop",
|
||||
"/usr/share/applications/wps-office-uninstall.desktop",
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // APPDBMANAGER_H
|
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Tianjin KYLIN Information Technology 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, 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <KWindowSystem>
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include "convert-winid-to-desktop.h"
|
||||
|
||||
ConvertWinidToDesktop::ConvertWinidToDesktop(QObject *parent) : QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QString ConvertWinidToDesktop::tranIdToDesktop(WId id)
|
||||
{
|
||||
KWindowInfo info(id, 0, NET::WM2AllProperties);
|
||||
QString desktopName = confirmDesktopFile(info);
|
||||
qDebug() << "PID:" << info.pid() << "open desktopName:" << desktopName;
|
||||
return desktopName;
|
||||
}
|
||||
|
||||
QString ConvertWinidToDesktop::confirmDesktopFile(KWindowInfo info)
|
||||
{
|
||||
QString desktopFilePath = nullptr;
|
||||
QDir dir = QDir(DESKTOP_FILE_PATH);
|
||||
QFileInfoList list = dir.entryInfoList();
|
||||
//跳过 ./ 和 ../ 目录
|
||||
list.removeAll(QFile(USR_SHARE_APP_CURRENT));
|
||||
list.removeAll(QFile(USR_SHARE_APP_UPER));
|
||||
|
||||
//第一种方法:获取点击应用时大部分desktop文件名
|
||||
desktopFilePath = searchFromEnviron(info, list);
|
||||
|
||||
//第二种方法:比较名字一致性
|
||||
if (desktopFilePath.isEmpty()) {
|
||||
m_classClass = info.windowClassClass().toLower();
|
||||
m_className = info.windowClassName();
|
||||
|
||||
//匹配安卓兼容
|
||||
if (m_className == "kylin-kmre-window") {
|
||||
return searchAndroidApp(info);
|
||||
}
|
||||
|
||||
QFile file(QString("/proc/%1/status").arg(info.pid()));
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
char buf[1024];
|
||||
qint64 len=file.readLine(buf,sizeof(buf));
|
||||
if (len!=-1) {
|
||||
m_statusName = QString::fromLocal8Bit(buf).remove("Name:").remove("\t").remove("\n");
|
||||
}
|
||||
}
|
||||
desktopFilePath = compareClassName(list);
|
||||
}
|
||||
|
||||
//第三种方法:比较cmd命令行操作一致性
|
||||
if (desktopFilePath.isEmpty()) {
|
||||
QFile file(QString("/proc/%1/cmdline").arg(info.pid()));
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
char buf[1024];
|
||||
qint64 len=file.readLine(buf,sizeof(buf));
|
||||
if (len!=-1) {
|
||||
m_cmdLine = QString::fromLocal8Bit(buf).remove("\n");
|
||||
}
|
||||
}
|
||||
desktopFilePath = compareCmdExec(list);
|
||||
}
|
||||
|
||||
//第四种方法:匹配部分字段
|
||||
if (desktopFilePath.isEmpty()) {
|
||||
desktopFilePath = compareLastStrategy(list);
|
||||
}
|
||||
return desktopFilePath;
|
||||
}
|
||||
|
||||
QString ConvertWinidToDesktop::searchAndroidApp(KWindowInfo info)
|
||||
{
|
||||
QDir androidDir = QString(QDir::homePath() + ANDROID_FILE_PATH);
|
||||
QFileInfoList androidList = androidDir.entryInfoList();
|
||||
androidList.removeAll(QDir::homePath() + ANDROID_APP_CURRENT);
|
||||
androidList.removeAll(QDir::homePath() + ANDROID_APP_UPER);
|
||||
|
||||
QFile file(QString("/proc/%1/cmdline").arg(info.pid()));
|
||||
file.open(QIODevice::ReadOnly);
|
||||
QByteArray cmd = file.readAll();
|
||||
file.close();
|
||||
QList<QByteArray> cmdList = cmd.split('\0');
|
||||
for (int i = 0; i < androidList.size(); i++) {
|
||||
QFileInfo fileInfo = androidList.at(i);
|
||||
QString desktopName = fileInfo.filePath();
|
||||
if (!fileInfo.filePath().endsWith(".desktop")) {
|
||||
continue;
|
||||
}
|
||||
desktopName = desktopName.mid(desktopName.lastIndexOf("/") + 1);
|
||||
desktopName = desktopName.left(desktopName.lastIndexOf("."));
|
||||
if(desktopName == cmdList.at(10)){
|
||||
return fileInfo.filePath();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QString ConvertWinidToDesktop::searchFromEnviron(KWindowInfo info, QFileInfoList list)
|
||||
{
|
||||
QFile file("/proc/" + QString::number(info.pid()) + "/environ");
|
||||
file.open(QIODevice::ReadOnly);
|
||||
QByteArray BA = file.readAll();
|
||||
file.close();
|
||||
QList<QByteArray> list_BA = BA.split('\0');
|
||||
|
||||
QString desktopFilePath = nullptr;
|
||||
for (int i = 0; i < list_BA.length(); i++) {
|
||||
if (list_BA.at(i).startsWith("GIO_LAUNCHED_DESKTOP_FILE=")) {
|
||||
desktopFilePath = list_BA.at(i);
|
||||
desktopFilePath = desktopFilePath.mid(desktopFilePath.indexOf("=") + 1);
|
||||
//desktop文件地址需要重写
|
||||
desktopFilePath = desktopFilePath.mid(desktopFilePath.lastIndexOf("/") + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//desktop文件地址重写
|
||||
if (!desktopFilePath.isEmpty()) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
QFileInfo fileInfo = list.at(i);
|
||||
if (fileInfo.filePath() == DESKTOP_FILE_PATH + desktopFilePath) {
|
||||
desktopFilePath = fileInfo.filePath();
|
||||
return desktopFilePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
return desktopFilePath;
|
||||
}
|
||||
|
||||
QString ConvertWinidToDesktop::compareClassName(QFileInfoList list)
|
||||
{
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
QFileInfo fileInfo = list.at(i);;
|
||||
QString pathDesktopName = fileInfo.filePath();
|
||||
if (!fileInfo.filePath().endsWith(".desktop")) {
|
||||
continue;
|
||||
}
|
||||
pathDesktopName = pathDesktopName.mid(pathDesktopName.lastIndexOf("/") + 1);
|
||||
pathDesktopName = pathDesktopName.left(pathDesktopName.lastIndexOf("."));
|
||||
if (pathDesktopName == m_classClass || pathDesktopName == m_className || pathDesktopName == m_statusName) {
|
||||
return fileInfo.filePath();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QString ConvertWinidToDesktop::compareCmdExec(QFileInfoList list)
|
||||
{
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
QString cmd;
|
||||
QFileInfo fileInfo = list.at(i);
|
||||
if (!fileInfo.filePath().endsWith(".desktop")) {
|
||||
continue;
|
||||
}
|
||||
cmd.sprintf(GET_DESKTOP_EXEC_NAME_MAIN, fileInfo.filePath().toStdString().data());
|
||||
QString desktopFileExeName = getDesktopFileName(cmd).remove("\n");
|
||||
|
||||
if (desktopFileExeName.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (desktopFileExeName == m_cmdLine || desktopFileExeName.startsWith(m_cmdLine) || m_cmdLine.startsWith(desktopFileExeName)) {
|
||||
return fileInfo.filePath();
|
||||
}
|
||||
|
||||
//仅仅是为了适配微信
|
||||
desktopFileExeName = "/usr/lib/" + desktopFileExeName;
|
||||
if (desktopFileExeName == m_cmdLine || desktopFileExeName.startsWith(m_cmdLine) || m_cmdLine.startsWith(desktopFileExeName)) {
|
||||
return fileInfo.filePath();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//最后的匹配策略汇总
|
||||
QString ConvertWinidToDesktop::compareLastStrategy(QFileInfoList list)
|
||||
{
|
||||
QString desktopFilePath = compareCmdName(list);
|
||||
|
||||
if (desktopFilePath.isEmpty()) {
|
||||
desktopFilePath = compareDesktopClass(list);
|
||||
}
|
||||
|
||||
if (desktopFilePath.isEmpty()) {
|
||||
desktopFilePath = containsName(list);
|
||||
}
|
||||
return desktopFilePath;
|
||||
}
|
||||
|
||||
QString ConvertWinidToDesktop::compareCmdName(QFileInfoList list)
|
||||
{
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
QString cmd;
|
||||
QFileInfo fileInfo = list.at(i);
|
||||
if (!fileInfo.filePath().endsWith(".desktop")) {
|
||||
continue;
|
||||
}
|
||||
cmd.sprintf(GET_DESKTOP_EXEC_NAME_MAIN, fileInfo.filePath().toStdString().data());
|
||||
QString desktopFileExeName = getDesktopFileName(cmd).remove("\n");
|
||||
|
||||
if (desktopFileExeName.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (desktopFileExeName.startsWith(m_className) || desktopFileExeName.endsWith(m_className)) {
|
||||
return fileInfo.filePath();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QString ConvertWinidToDesktop::compareDesktopClass(QFileInfoList list)
|
||||
{
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
QFileInfo fileInfo = list.at(i);
|
||||
QString pathDesktopName = fileInfo.filePath();
|
||||
if (!fileInfo.filePath().endsWith(".desktop")) {
|
||||
continue;
|
||||
}
|
||||
pathDesktopName = pathDesktopName.mid(pathDesktopName.lastIndexOf("/") + 1);
|
||||
pathDesktopName = pathDesktopName.left(pathDesktopName.lastIndexOf("."));
|
||||
|
||||
if (pathDesktopName.startsWith(m_className) || pathDesktopName.endsWith(m_className)) {
|
||||
return fileInfo.filePath();
|
||||
}
|
||||
else if (m_className.startsWith(pathDesktopName) || m_className.endsWith(pathDesktopName)) {
|
||||
return fileInfo.filePath();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QString ConvertWinidToDesktop::containsName(QFileInfoList list)
|
||||
{
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
QString cmd;
|
||||
QFileInfo fileInfo = list.at(i);
|
||||
QString pathDesktopName = fileInfo.filePath();
|
||||
|
||||
if (!fileInfo.filePath().endsWith(".desktop")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cmd.sprintf(GET_DESKTOP_EXEC_NAME_MAIN, fileInfo.filePath().toStdString().data());
|
||||
QString desktopFileExeName = getDesktopFileName(cmd).remove("\n");
|
||||
|
||||
pathDesktopName = pathDesktopName.mid(pathDesktopName.lastIndexOf("/") + 1);
|
||||
pathDesktopName = pathDesktopName.left(pathDesktopName.lastIndexOf("."));
|
||||
|
||||
if (pathDesktopName.contains(m_className) || desktopFileExeName.contains(m_className)) {
|
||||
return fileInfo.filePath();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//执行头文件中宏定义写好的终端指令获取对应的Exec字段
|
||||
QString ConvertWinidToDesktop::getDesktopFileName(QString cmd)
|
||||
{
|
||||
char name[200];
|
||||
FILE *fp1 = NULL;
|
||||
if ((fp1 = popen(cmd.toStdString().data(), "r")) == NULL) {
|
||||
return QString();
|
||||
}
|
||||
memset(name, 0, sizeof(name));
|
||||
fgets(name, sizeof(name), fp1);
|
||||
pclose(fp1);
|
||||
return QString(name);
|
||||
}
|
||||
|
||||
ConvertWinidToDesktop::~ConvertWinidToDesktop()
|
||||
{
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Tianjin KYLIN Information Technology 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, 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONVERTDESKTOPTOWINID_H
|
||||
#define CONVERTDESKTOPTOWINID_H
|
||||
|
||||
#include <QObject>
|
||||
#include <KWindowSystem>
|
||||
#include <QDir>
|
||||
|
||||
#define DESKTOP_FILE_PATH "/usr/share/applications/"
|
||||
#define USR_SHARE_APP_CURRENT "/usr/share/applications/."
|
||||
#define USR_SHARE_APP_UPER "/usr/share/applications/.."
|
||||
#define PEONY_TRASH "/usr/share/applications/peony-trash.desktop"
|
||||
#define PEONY_COMUTER "/usr/share/applications/peony-computer.desktop"
|
||||
#define PEONY_HOME "/usr/share/applications/peony-home.desktop"
|
||||
#define PEONY_MAIN "/usr/share/applications/peony.desktop"
|
||||
|
||||
#define GET_DESKTOP_EXEC_NAME_MAIN "cat %s | awk '{if($1~\"Exec=\")if($2~\"\%\"){print $1} else print}' | cut -d '=' -f 2"
|
||||
#define ANDROID_FILE_PATH "/.local/share/applications/"
|
||||
#define ANDROID_APP_CURRENT "/.local/share/applications/."
|
||||
#define ANDROID_APP_UPER "/.local/share/applications/.."
|
||||
|
||||
|
||||
/**
|
||||
* @brief The ConvertWinidToDesktop class
|
||||
* 需要实现的功能,desktop文件与windowId的转换
|
||||
* 传入(int)WindowId,转化为desktop文件的路径
|
||||
*/
|
||||
|
||||
class ConvertWinidToDesktop : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ConvertWinidToDesktop(QObject *parent = nullptr);
|
||||
~ConvertWinidToDesktop();
|
||||
|
||||
QString tranIdToDesktop(WId id);
|
||||
|
||||
private:
|
||||
QString m_classClass = nullptr;
|
||||
QString m_className = nullptr;
|
||||
QString m_statusName = nullptr;
|
||||
QString m_cmdLine = nullptr;
|
||||
|
||||
QString confirmDesktopFile(KWindowInfo info);
|
||||
QString searchFromEnviron(KWindowInfo info, QFileInfoList list);
|
||||
QString searchAndroidApp(KWindowInfo info);
|
||||
QString compareClassName(QFileInfoList list);
|
||||
QString compareCmdExec(QFileInfoList list);
|
||||
QString compareLastStrategy(QFileInfoList list);
|
||||
QString compareCmdName(QFileInfoList list);
|
||||
QString compareDesktopClass(QFileInfoList list);
|
||||
QString containsName(QFileInfoList list);
|
||||
QString getDesktopFileName(QString cmd);
|
||||
};
|
||||
|
||||
#endif // CONVERTDESKTOPTOWINID_H
|
|
@ -1,8 +1,67 @@
|
|||
#include <QCoreApplication>
|
||||
#include <QTime>
|
||||
#include <QStandardPaths>
|
||||
#include <QFile>
|
||||
#include "ukui-search-app-data-service.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::HomeLocation) + "/.config/org.ukui/ukui-search-app-data-service.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[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
// Output log to file
|
||||
qInstallMessageHandler(messageOutput);
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
#endif
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
#endif
|
||||
UkuiSearchAppDataService ukss(argc, argv, "ukui-search-app-data-service");
|
||||
if (ukss.isRunning())
|
||||
return 0;
|
||||
|
||||
return a.exec();
|
||||
return ukss.exec();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
#include <QDebug>
|
||||
#include "ukui-search-app-data-service.h"
|
||||
#include "app-db-manager.h"
|
||||
#include "convert-winid-to-desktop.h"
|
||||
|
||||
using namespace UkuiSearch;
|
||||
UkuiSearchAppDataService::UkuiSearchAppDataService(int &argc, char *argv[], const QString &applicationName):
|
||||
QtSingleApplication (applicationName, argc, argv)
|
||||
{
|
||||
qDebug()<<"ukui search app data service constructor start";
|
||||
setApplicationVersion(QString("v%1").arg(VERSION));
|
||||
setQuitOnLastWindowClosed(false);
|
||||
|
||||
if (!this->isRunning()) {
|
||||
connect(this, &QtSingleApplication::messageReceived, [=](QString msg) {
|
||||
this->parseCmd(msg, true);
|
||||
});
|
||||
//监控应用进程开启
|
||||
connect(KWindowSystem::self(), &KWindowSystem::windowAdded, [ = ](WId id) {
|
||||
ConvertWinidToDesktop reply;
|
||||
QString desktopfp = reply.tranIdToDesktop(id);
|
||||
if (!desktopfp.isEmpty()) {
|
||||
AppDBManager::getInstance()->updateAppLaunchTimes(desktopfp);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//parse cmd
|
||||
qDebug()<<"parse cmd";
|
||||
auto message = this->arguments().join(' ').toUtf8();
|
||||
parseCmd(message, !isRunning());
|
||||
qDebug()<<"ukui search app data service constructor end";
|
||||
}
|
||||
|
||||
void UkuiSearchAppDataService::parseCmd(QString msg, bool isPrimary)
|
||||
{
|
||||
QCommandLineParser parser;
|
||||
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
|
||||
QCommandLineOption quitOption(QStringList()<<"q"<<"quit", tr("Stop service"));
|
||||
parser.addOption(quitOption);
|
||||
|
||||
if (isPrimary) {
|
||||
const QStringList args = QString(msg).split(' ');
|
||||
parser.process(args);
|
||||
|
||||
if (parser.isSet(quitOption)) {
|
||||
qApp->quit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (arguments().count() < 2) {
|
||||
parser.showHelp();
|
||||
}
|
||||
parser.process(arguments());
|
||||
sendMessage(msg);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef UkuiSearchAppDataService_H
|
||||
#define UkuiSearchAppDataService_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QCommandLineParser>
|
||||
#include "qtsingleapplication.h"
|
||||
namespace UkuiSearch {
|
||||
|
||||
class UkuiSearchAppDataService : public QtSingleApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
UkuiSearchAppDataService(int &argc, char *argv[], const QString &applicationName = "ukui-search-app-data-service");
|
||||
|
||||
protected Q_SLOTS:
|
||||
void parseCmd(QString msg, bool isPrimary);
|
||||
};
|
||||
}
|
||||
#endif // UkuiSearchAppDataService_H
|
|
@ -1,4 +1,4 @@
|
|||
QT += core gui dbus
|
||||
QT += core gui dbus sql xml KWindowSystem
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
|
@ -7,8 +7,7 @@ TARGET = ukui-search-app-data-service
|
|||
VERSION = 1.0.0
|
||||
DEFINES += VERSION='\\"$${VERSION}\\"'
|
||||
CONFIG += c++11 link_pkgconfig no_keywords lrelease
|
||||
PKGCONFIG += gsettings-qt
|
||||
|
||||
PKGCONFIG += glib-2.0 gio-unix-2.0 gio-2.0 poppler-qt5
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any Qt feature that has been marked deprecated (the exact warnings
|
||||
|
@ -22,9 +21,34 @@ QMAKE_CXXFLAGS += -Werror=return-type -Werror=return-local-addr -Werror=uninitia
|
|||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
main.cpp
|
||||
#include(../libsearch/appdata/appdata.pri)
|
||||
include(../3rd-parties/qtsingleapplication/qtsingleapplication.pri)
|
||||
|
||||
LIBS += -lQt5Xdg -lquazip5 -luchardet -ltesseract
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
convert-winid-to-desktop.cpp \
|
||||
app-db-manager.cpp \
|
||||
ukui-search-app-data-service.cpp \
|
||||
../libsearch/file-utils.cpp \
|
||||
../libsearch/gobject-template.cpp
|
||||
|
||||
HEADERS += \
|
||||
convert-winid-to-desktop.h \
|
||||
app-db-manager.h \
|
||||
ukui-search-app-data-service.h \
|
||||
app-db-common-defines.h \
|
||||
../libsearch/file-utils.h \
|
||||
../libsearch/gobject-template.h
|
||||
|
||||
# Default rules for deployment.
|
||||
target.path = /usr/bin
|
||||
INSTALLS += target
|
||||
|
||||
desktop.path = /etc/xdg/autostart
|
||||
desktop.files += ../data/ukui-search-app-data-service.desktop
|
||||
INSTALLS += desktop
|
||||
|
||||
LIBS += -L$$OUT_PWD/../libchinese-segmentation/ -lchinese-segmentation
|
||||
INCLUDEPATH += $$PWD/../libchinese-segmentation
|
||||
DEPENDPATH += $$PWD/../libchinese-segmentation
|
||||
|
|
|
@ -7,6 +7,7 @@ SUBDIRS += $$PWD/libchinese-segmentation \
|
|||
$$PWD/ukui-search-service \
|
||||
$$PWD/ukui-search-app-data-service \
|
||||
$$PWD/ukui-search-service-dir-manager
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any Qt feature that has been marked deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
|
@ -23,7 +24,7 @@ ukui-search-service.depends += libsearch
|
|||
#src.depends = libsearch
|
||||
frontend.depends = libsearch
|
||||
|
||||
CONFIG += ordered \
|
||||
CONFIG += ordered
|
||||
|
||||
QT += widgets
|
||||
|
||||
|
|
Loading…
Reference in New Issue