372 lines
13 KiB
C++
372 lines
13 KiB
C++
/*
|
|
* Copyright (C) 2023, KylinSoft Co., Ltd.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
* Authors: iaom <zhangpengfei@kylinos.cn>
|
|
*/
|
|
|
|
#include "settings-manager.h"
|
|
#include "settings-manager-private.h"
|
|
#include <QFile>
|
|
#include <QDir>
|
|
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
#include <QJsonValue>
|
|
#include <QDebug>
|
|
#include <QList>
|
|
#include <QLockFile>
|
|
#include <QCoreApplication>
|
|
#include <mutex>
|
|
#include "settings-properties-info.h"
|
|
|
|
using namespace UkuiNotification;
|
|
|
|
static const QString SETTINGS_FILE_PATH = QDir::homePath() + QStringLiteral("/.config/org.ukui/ukui-notification");
|
|
static const QString SETTINGS_FILE_PATH_NAME = SETTINGS_FILE_PATH + QStringLiteral("/ukui-notification-settings.json");
|
|
static std::once_flag flag;
|
|
static SettingsManager *s_self;
|
|
SettingsManagerPrivate::SettingsManagerPrivate(QObject* parent) : QObject(parent)
|
|
{
|
|
for(SettingsProperty::Property property : SINGLE_APPLICATION_SETTINGS) {
|
|
SettingsPropertiesInfo info(property);
|
|
m_applicationDefaultSettings.insert(info.name(), info.defaultValue());
|
|
}
|
|
}
|
|
|
|
SettingsManagerPrivate::~SettingsManagerPrivate()
|
|
{
|
|
}
|
|
|
|
void SettingsManagerPrivate::init()
|
|
{
|
|
m_watcher = new QFileSystemWatcher(this);
|
|
connect(m_watcher, &QFileSystemWatcher::fileChanged, this, &SettingsManagerPrivate::checkAndLoad);
|
|
//TODO 应用数据服务接口更新中
|
|
m_applicationInfo = new UkuiSearch::ApplicationInfo(this);
|
|
if (qApp->property("IS_UKUI_NOTIFICATION_SERVER").toBool()) {
|
|
connect(m_applicationInfo, &UkuiSearch::ApplicationInfo::appDBItems2BAdd, this,&SettingsManagerPrivate::desktopFileAdd);
|
|
}
|
|
connect(m_applicationInfo, &UkuiSearch::ApplicationInfo::appDBItems2BDelete, this, &SettingsManagerPrivate::desktopFileDelete);
|
|
checkAndLoad();
|
|
}
|
|
void SettingsManagerPrivate::checkAndLoad()
|
|
{
|
|
QLockFile lockFile(SETTINGS_FILE_PATH + QStringLiteral("ukui-notification-settings.json.lock"));
|
|
lockFile.lock();
|
|
QFile settingsFile(SETTINGS_FILE_PATH_NAME);
|
|
if (!settingsFile.exists()) {
|
|
qDebug() << SETTINGS_FILE_PATH_NAME << " is not exist, start create settings file.";
|
|
createSettingsFile();
|
|
lockFile.unlock();
|
|
return;
|
|
}
|
|
|
|
if (!settingsFile.open(QFile::ReadOnly)) {
|
|
qWarning() << "SettingsManagerPrivate: configuration file " << settingsFile.fileName() << "open failed !";
|
|
m_watcher->addPath(SETTINGS_FILE_PATH_NAME);
|
|
lockFile.unlock();
|
|
return;
|
|
}
|
|
// 读取json数据
|
|
QByteArray byteArray = settingsFile.readAll();
|
|
settingsFile.close();
|
|
QJsonParseError errRpt;
|
|
QJsonDocument jsonDocument(QJsonDocument::fromJson(byteArray, &errRpt));
|
|
if (errRpt.error != QJsonParseError::NoError) {
|
|
qWarning() << "SettingsManagerPrivate: Incorrect configuration files. JSON parse error";
|
|
createSettingsFile();
|
|
lockFile.unlock();
|
|
return;
|
|
}
|
|
|
|
// 读取配置文件
|
|
QJsonObject settingsData = jsonDocument.object();
|
|
QString version = settingsData.value("VERSION").toString();
|
|
if (version != QString(NOTIFICATION_SETTINGS_VERSION)) {
|
|
qDebug() << "Notification settings version is different, need update! configFile:" << version << " new:" << NOTIFICATION_SETTINGS_VERSION;
|
|
updateSettingsFile();
|
|
} else {
|
|
if(m_needCheckApplist) {
|
|
checkApplicationList(settingsData);
|
|
m_needCheckApplist = false;
|
|
}
|
|
m_settingsData.swap(settingsData);
|
|
Q_EMIT settingsUpdateFinished();
|
|
m_watcher->addPath(SETTINGS_FILE_PATH_NAME);
|
|
}
|
|
lockFile.unlock();
|
|
}
|
|
|
|
void SettingsManagerPrivate::createSettingsFile()
|
|
{
|
|
initSettingsData(m_settingsData);
|
|
save2SettingsFile(m_settingsData);
|
|
Q_EMIT settingsUpdateFinished();
|
|
m_watcher->addPath(SETTINGS_FILE_PATH_NAME);
|
|
}
|
|
|
|
void SettingsManagerPrivate::updateSettingsFile()
|
|
{
|
|
m_watcher->removePath(SETTINGS_FILE_PATH_NAME);
|
|
//初始化当前版本默认值
|
|
QJsonObject newData;
|
|
initSettingsData(newData);
|
|
//同步全局配置
|
|
QJsonObject newGlobalData = newData.value(QStringLiteral("Global")).toObject();
|
|
QJsonObject oldGlobalData = m_settingsData.value(QStringLiteral("Global")).toObject();
|
|
for(const QString &key : newGlobalData.keys()) {
|
|
QJsonValue oldValue = oldGlobalData.value(key);
|
|
if(!oldValue.isUndefined()) {
|
|
newGlobalData.insert(key, oldValue);
|
|
}
|
|
}
|
|
newData.insert(QStringLiteral("Global"), newGlobalData);
|
|
//同步所有应用配置
|
|
QJsonObject newApplicationsData = newData.value(QStringLiteral("Applications")).toObject();
|
|
QJsonObject oldApplicationsData = m_settingsData.value(QStringLiteral("Applications")).toObject();
|
|
for(const QString &desktopEntry : newApplicationsData.keys()) {
|
|
if(oldApplicationsData.contains(desktopEntry)) {
|
|
QJsonObject oldSingleAppData = oldApplicationsData.value(desktopEntry).toObject();
|
|
QJsonObject newSingleAppData = newApplicationsData.value(desktopEntry).toObject();
|
|
for(const QString &key : newSingleAppData.keys()) {
|
|
QJsonValue oldValue = oldSingleAppData.value(key);
|
|
if(!oldValue.isUndefined()) {
|
|
newSingleAppData.insert(key, oldValue);
|
|
}
|
|
}
|
|
newApplicationsData.insert(desktopEntry, newSingleAppData);
|
|
}
|
|
}
|
|
newData.insert(QStringLiteral("Applications"), newApplicationsData);
|
|
//写入数据
|
|
m_settingsData.swap(newData);
|
|
save2SettingsFile(m_settingsData);
|
|
m_watcher->addPath(SETTINGS_FILE_PATH_NAME);
|
|
Q_EMIT settingsUpdateFinished();
|
|
}
|
|
|
|
QStringList SettingsManagerPrivate::getAppInfo()
|
|
{
|
|
// 过滤掉不需要显示的应用
|
|
UkuiSearch::ApplicationPropertyMap restrictions = {
|
|
{UkuiSearch::ApplicationProperty::DontDisplay, 0}
|
|
};
|
|
|
|
return m_applicationInfo->getInfo(UkuiSearch::ApplicationProperties{}, restrictions).keys();
|
|
}
|
|
|
|
void SettingsManagerPrivate::initSettingsData(QJsonObject &data)
|
|
{
|
|
data.insert("VERSION", QString(NOTIFICATION_SETTINGS_VERSION));
|
|
|
|
//全局设置
|
|
QJsonObject globalSettings;
|
|
for(SettingsProperty::Property property : GLOBAL_SETTINGS) {
|
|
SettingsPropertiesInfo info(property);
|
|
globalSettings.insert(info.name(), info.defaultValue());
|
|
}
|
|
data.insert(QStringLiteral("Global"), globalSettings);
|
|
|
|
//应用设置
|
|
QJsonObject applicationsSettings;
|
|
for (const QString &desktopFile : getAppInfo()) {
|
|
applicationsSettings.insert(desktopFile, m_applicationDefaultSettings);
|
|
}
|
|
data.insert(QStringLiteral("Applications"), applicationsSettings);
|
|
}
|
|
|
|
void SettingsManagerPrivate::desktopFileAdd(const QStringList &data)
|
|
{
|
|
QJsonObject applicationsSettings = m_settingsData.value(QStringLiteral("Applications")).toObject();
|
|
bool needUpdate = false;
|
|
for (const QString &desktopPath : data) {
|
|
if(m_applicationInfo->getInfo(desktopPath, UkuiSearch::ApplicationProperty::AutoStart).toInt() == 0) {
|
|
applicationsSettings.insert(desktopPath, m_applicationDefaultSettings);
|
|
needUpdate = true;
|
|
}
|
|
}
|
|
if(!needUpdate) {
|
|
return;
|
|
}
|
|
|
|
m_settingsData.insert(QStringLiteral("Applications"), applicationsSettings);
|
|
|
|
QLockFile lockFile(SETTINGS_FILE_PATH + QStringLiteral("ukui-notification-settings.json.lock"));
|
|
lockFile.lock();
|
|
m_watcher->removePath(SETTINGS_FILE_PATH_NAME);
|
|
save2SettingsFile(m_settingsData);
|
|
m_watcher->addPath(SETTINGS_FILE_PATH_NAME);
|
|
lockFile.unlock();
|
|
Q_EMIT settingsUpdateFinished();
|
|
}
|
|
|
|
void SettingsManagerPrivate::desktopFileDelete(const QStringList &data)
|
|
{
|
|
if (data.isEmpty()) {
|
|
return;
|
|
}
|
|
if (qApp->property("IS_UKUI_NOTIFICATION_SERVER").toBool()) {
|
|
QJsonObject applicationsSettings = m_settingsData.value(QStringLiteral("Applications")).toObject();
|
|
for (const QString &app : data) {
|
|
applicationsSettings.remove(app);
|
|
}
|
|
m_settingsData.insert(QStringLiteral("Applications"), applicationsSettings);
|
|
QLockFile lockFile(SETTINGS_FILE_PATH + QStringLiteral("ukui-notification-settings.json.lock"));
|
|
lockFile.lock();
|
|
m_watcher->removePath(SETTINGS_FILE_PATH_NAME);
|
|
save2SettingsFile(m_settingsData);
|
|
m_watcher->addPath(SETTINGS_FILE_PATH_NAME);
|
|
lockFile.unlock();
|
|
Q_EMIT settingsUpdateFinished();
|
|
}
|
|
for(const QString &app : data) {
|
|
Q_EMIT appUninstalled(app);
|
|
}
|
|
}
|
|
|
|
void SettingsManagerPrivate::save2SettingsFile(const QJsonObject &jsonDocData)
|
|
{
|
|
QDir dir;
|
|
QString configFileDir(SETTINGS_FILE_PATH);
|
|
if (!dir.exists(configFileDir)) {
|
|
if (!dir.mkdir(configFileDir)) {
|
|
qWarning() << "Unable to create notification settings config file.";
|
|
return;
|
|
}
|
|
}
|
|
|
|
QFile settingsFile(SETTINGS_FILE_PATH_NAME);
|
|
settingsFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
|
|
|
if (settingsFile.write(QJsonDocument(jsonDocData).toJson()) == -1) {
|
|
qWarning() << "SettingsManagerPrivate: Error saving configuration file.";
|
|
}
|
|
settingsFile.flush();
|
|
settingsFile.close();
|
|
}
|
|
|
|
void SettingsManagerPrivate::checkApplicationList(QJsonObject &data)
|
|
{
|
|
QStringList appList = getAppInfo();
|
|
QStringList appNeedRemoved;
|
|
QJsonObject applicationSettings = data.value(QStringLiteral("Applications")).toObject();
|
|
for(const QString &desktopFile : applicationSettings.keys()) {
|
|
if(appList.contains(desktopFile)) {
|
|
appList.removeAll(desktopFile);
|
|
} else {
|
|
appNeedRemoved.append(desktopFile);
|
|
}
|
|
}
|
|
//移除应用列表里已经不存在的应用
|
|
for(const QString &desktopFile : appNeedRemoved) {
|
|
applicationSettings.remove(desktopFile);
|
|
}
|
|
//将配置文件中没有的应用插入
|
|
for(const QString &desktopFile : appList) {
|
|
applicationSettings.insert(desktopFile, m_applicationDefaultSettings);
|
|
}
|
|
data.insert(QStringLiteral("Applications"), applicationSettings);
|
|
save2SettingsFile(data);
|
|
}
|
|
|
|
SettingsManager::SettingsManager(QObject *parent) : QObject(parent), d(new SettingsManagerPrivate(this))
|
|
{
|
|
connect(d, &SettingsManagerPrivate::settingsUpdateFinished, this, &SettingsManager::settingsDataChanged);
|
|
connect(d, &SettingsManagerPrivate::appUninstalled, this, &SettingsManager::appUninstalled);
|
|
d->init();
|
|
}
|
|
|
|
QJsonObject SettingsManager::getGlobalSettings()
|
|
{
|
|
return d->m_settingsData.value(QStringLiteral("Global")).toObject();
|
|
}
|
|
|
|
QJsonObject SettingsManager::getAllAppSettings()
|
|
{
|
|
return d->m_settingsData.value(QStringLiteral("Applications")).toObject();
|
|
}
|
|
|
|
QJsonObject SettingsManager::getAppSettings(const QString &appDesktopName)
|
|
{
|
|
if(appDesktopName == QStringLiteral("default") || appDesktopName.isEmpty()) {
|
|
return d->m_applicationDefaultSettings;
|
|
}
|
|
QJsonValue value = d->m_settingsData.value(QStringLiteral("Applications")).toObject().value(appDesktopName);
|
|
if(value.isUndefined()) {
|
|
return {};
|
|
}
|
|
return value.toObject();
|
|
}
|
|
|
|
|
|
QJsonObject SettingsManager::getAppDefaultSettings()
|
|
{
|
|
return d->m_applicationDefaultSettings;
|
|
}
|
|
|
|
SettingsManager *SettingsManager::self()
|
|
{
|
|
std::call_once(flag, [ & ] {
|
|
s_self = new SettingsManager();
|
|
});
|
|
return s_self;
|
|
}
|
|
|
|
bool SettingsManager::setGlobalSettings(SettingsProperty::Property key, const QVariant &value)
|
|
{
|
|
if(!GLOBAL_SETTINGS.contains(key)) {
|
|
return false;
|
|
}
|
|
auto info = SettingsPropertiesInfo(key);
|
|
QString valueToSet = info.valueToString(value);
|
|
|
|
QJsonObject data = d->m_settingsData.value(QStringLiteral("Global")).toObject();
|
|
data.insert(info.name(), valueToSet);
|
|
d->m_settingsData.insert(QStringLiteral("Global"), data);
|
|
QLockFile lockFile(SETTINGS_FILE_PATH + QStringLiteral("ukui-notification-settings.json.lock"));
|
|
lockFile.lock();
|
|
d->save2SettingsFile(d->m_settingsData);
|
|
lockFile.unlock();
|
|
return true;
|
|
}
|
|
|
|
bool SettingsManager::setAppSettings(const QString &appDesktopName, SettingsProperty::Property key, const QVariant &value)
|
|
{
|
|
if(!SINGLE_APPLICATION_SETTINGS.contains(key)) {
|
|
return false;
|
|
}
|
|
|
|
QJsonObject appsData = d->m_settingsData.value(QStringLiteral("Applications")).toObject();
|
|
QJsonValue dataValue = appsData.value(appDesktopName);
|
|
if(dataValue.isUndefined()) {
|
|
return false;
|
|
}
|
|
QJsonObject oneAppData = dataValue.toObject();
|
|
auto info = SettingsPropertiesInfo(key);
|
|
QString valueToSet = info.valueToString(value);
|
|
oneAppData.insert(info.name(), valueToSet);
|
|
appsData.insert(appDesktopName, oneAppData);
|
|
d->m_settingsData.insert(QStringLiteral("Applications"), appsData);
|
|
|
|
QLockFile lockFile(SETTINGS_FILE_PATH + QStringLiteral("ukui-notification-settings.json.lock"));
|
|
lockFile.lock();
|
|
d->save2SettingsFile(d->m_settingsData);
|
|
lockFile.unlock();
|
|
return true;
|
|
}
|
|
|
|
|
|
|