fix: 修复设置开机自启动应用重启后失效问题

1. 修复获取自启动列表为空的问题
2. 修复重启后自启动应用没有启动问题

Log:
Influence: 设置自启动后重启应用也会保持生效
Bug: https://pms.uniontech.com/bug-view-172263.html
Change-Id: Id95f4248fe2d29b3a6d03e9b44bee54671e9c5f6
This commit is contained in:
songwentao 2022-11-24 17:29:29 +08:00
parent 8be1b299e6
commit 885ad9b07a
3 changed files with 165 additions and 57 deletions

View File

@ -217,8 +217,10 @@ bool KeyFile::loadFile(const std::string &filePath)
std::string lastSection; std::string lastSection;
m_fp = fopen(filePath.data(), "r"); m_fp = fopen(filePath.data(), "r");
if (!m_fp) if (!m_fp) {
perror("open file failed: ");
return false; return false;
}
char line[MAX_LINE_LEN] = {0}; char line[MAX_LINE_LEN] = {0};
while (fgets(line, MAX_LINE_LEN, m_fp)) { while (fgets(line, MAX_LINE_LEN, m_fp)) {

View File

@ -46,33 +46,25 @@ StartManager::StartManager(QObject *parent)
, minMemAvail(0) , minMemAvail(0)
, maxSwapUsed(0) , maxSwapUsed(0)
, dbusHandler(new StartManagerDBusHandler(this)) , dbusHandler(new StartManagerDBusHandler(this))
, fileWatcher(new QFileSystemWatcher(this)) , m_autostartFileWatcher(new QFileSystemWatcher(this))
, m_autostartFiles(getAutostartList())
, m_isDBusCalled(false)
{ {
am = static_cast<ApplicationManager *>(parent);
if (!am) {
qWarning() << "StartManager init error";
}
// load sysMemLimitConfig
loadSysMemLimitConfig(); loadSysMemLimitConfig();
getDesktopToAutostartMap();
m_autostartFiles = getAutostartList();
// listen autostart files
listenAutostartFileEvents(); listenAutostartFileEvents();
startAutostartProgram();
// start autostart
// TODO only running once when starting system
//startAutostartProgram();
} }
bool StartManager::addAutostart(const QString &desktop) bool StartManager::addAutostart(const QString &desktop)
{ {
setIsDBusCalled(true);
return setAutostart(desktop, true); return setAutostart(desktop, true);
} }
bool StartManager::removeAutostart(const QString &desktop) bool StartManager::removeAutostart(const QString &desktop)
{ {
setIsDBusCalled(true);
return setAutostart(desktop, false); return setAutostart(desktop, false);
} }
@ -171,30 +163,90 @@ void StartManager::runCommandWithOptions(QString exe, QStringList args, QMap<QSt
doRunCommandWithOptions(exe, args, options); doRunCommandWithOptions(exe, args, options);
} }
void StartManager::onAutoStartupPathChange(const QString &dirPath) void StartManager::onAutoStartupPathChange(const QString &path)
{ {
QStringList autostartFilesList = getAutostartList(); const QStringList &autostartFilesList = getAutostartList();
QSet<QString> newAutostartFiles = QSet<QString>::fromList(autostartFilesList); const QSet<QString> newAutostartFiles = QSet<QString>(autostartFilesList.begin(), autostartFilesList.end());
QSet<QString> oldAutostartFiles = QSet<QString>::fromList(m_autostartFiles); const QSet<QString> oldAutostartFiles = QSet<QString>(m_autostartFiles.begin(), m_autostartFiles.end());
// 添加 const QSet<QString> newFiles = newAutostartFiles - oldAutostartFiles;
QSet<QString> newFiles = newAutostartFiles - oldAutostartFiles; const QSet<QString> deletedFiles = oldAutostartFiles - newAutostartFiles;
QStringList newFile = newFiles.toList();
// 移除 QString desktopFullPath;
QSet<QString> deletedFiles = oldAutostartFiles - newAutostartFiles; QDir autostartDir(BaseDir::userAutoStartDir().c_str());
QStringList deleteFile = deletedFiles.toList(); if (deletedFiles.size() && !isDBusCalled()) {
for (const QString &path : deletedFiles) {
QFileInfo info(path);
const QString &autostartDesktopPath = autostartDir.path() + QString("/") + info.fileName();
// 更新autostartFiles记录 for (const std::string &appDir : BaseDir::appDirs()) {
QDir dir(appDir.c_str());
dir.setFilter(QDir::Files);
dir.setNameFilters({ "*.desktop" });
for (const auto &entry : dir.entryInfoList()) {
const QString &desktopPath = entry.absoluteFilePath();
if (desktopPath.contains(info.baseName())) {
desktopFullPath = desktopPath;
break;
}
}
if (!desktopFullPath.isEmpty())
break;
}
m_autostartFiles.removeAll(autostartDesktopPath);
autostartDir.remove(info.fileName());
if (m_desktopDirToAutostartDirMap.keys().contains(desktopFullPath)) {
m_desktopDirToAutostartDirMap.remove(desktopFullPath);
Q_EMIT autostartChanged(autostartDeleted, desktopFullPath);
}
}
} else if (newFiles.size() && !isDBusCalled()) {
for (const QString &path : newFiles) {
QFileInfo info(path);
const QString &autostartDesktopPath = autostartDir.path() + QString("/") + info.fileName();
m_autostartFiles.push_back(autostartDesktopPath);
const bool ret = QFile::copy(info.filePath(), autostartDesktopPath);
if (!ret)
qWarning() << "add to autostart list failed...";
/* 设置为自启动时手动将Hidden字段写入到自启动目录的desktop文件中并设置为false只有这样
* , 沿V20阶段的约定规范 */
KeyFile kf;
kf.loadFile(autostartDesktopPath.toStdString());
kf.setKey(MainSection, KeyXDeepinCreatedBy.toStdString(), AMServiceName.toStdString());
kf.setKey(MainSection, KeyXDeepinAppID.toStdString(), info.baseName().toStdString());
kf.setBool(MainSection, KeyHidden, "false");
kf.saveToFile(autostartDesktopPath.toStdString());
for (const std::string &appDir : BaseDir::appDirs()) {
QDir dir(appDir.c_str());
dir.setFilter(QDir::Files);
dir.setNameFilters({ "*.desktop" });
for (const auto &entry : dir.entryInfoList()) {
const QString &desktopPath = entry.absoluteFilePath();
if (desktopPath.contains(info.baseName())) {
desktopFullPath = desktopPath;
break;
}
}
if (!desktopFullPath.isEmpty())
break;
}
if (!m_desktopDirToAutostartDirMap.keys().contains(desktopFullPath)) {
m_desktopDirToAutostartDirMap[desktopFullPath] = autostartDesktopPath;
Q_EMIT autostartChanged(autostartAdded, desktopFullPath);
}
}
}
// 如果是用户通过启动器或者使用dbus接口调用方式添加或者删除自启动则文件监控的不发送信号
// 如果是用户直接删除自启动目录下的文件就发送信号
m_autostartFiles = autostartFilesList; m_autostartFiles = autostartFilesList;
for (auto &file : newFile) {
Q_EMIT autostartChanged(autostartAdded, file);
}
for (auto &file : deleteFile) {
Q_EMIT autostartChanged(autostartDeleted, file);
}
} }
bool StartManager::setAutostart(const QString &desktop, const bool value) bool StartManager::setAutostart(const QString &desktop, const bool value)
@ -232,8 +284,13 @@ bool StartManager::setAutostart(const QString &desktop, const bool value)
} }
const QString &autostartDesktopPath = autostartDir.path() + QString("/") + info.fileName(); const QString &autostartDesktopPath = autostartDir.path() + QString("/") + info.fileName();
if (value && !m_autostartFiles.contains(desktopFullPath)) { if (value && !m_autostartFiles.contains(autostartDesktopPath)) {
m_autostartFiles.push_back(desktopFullPath); m_autostartFiles.push_back(autostartDesktopPath);
// 建立映射关系
if (!m_desktopDirToAutostartDirMap.keys().contains(desktopFullPath))
m_desktopDirToAutostartDirMap[desktopFullPath] = autostartDesktopPath;
const bool ret = QFile::copy(info.filePath(), autostartDesktopPath); const bool ret = QFile::copy(info.filePath(), autostartDesktopPath);
if (!ret) if (!ret)
qWarning() << "add to autostart list failed..."; qWarning() << "add to autostart list failed...";
@ -246,8 +303,12 @@ bool StartManager::setAutostart(const QString &desktop, const bool value)
kf.setKey(MainSection, KeyXDeepinAppID.toStdString(), appId.toStdString()); kf.setKey(MainSection, KeyXDeepinAppID.toStdString(), appId.toStdString());
kf.setBool(MainSection, KeyHidden, "false"); kf.setBool(MainSection, KeyHidden, "false");
kf.saveToFile(autostartDesktopPath.toStdString()); kf.saveToFile(autostartDesktopPath.toStdString());
} else if (!value && m_autostartFiles.contains(desktopFullPath)) { } else if (!value && m_autostartFiles.contains(autostartDesktopPath)) {
m_autostartFiles.removeAll(desktopFullPath); // 删除映射关系
if (m_desktopDirToAutostartDirMap.keys().contains(desktopFullPath))
m_desktopDirToAutostartDirMap.remove(desktopFullPath);
m_autostartFiles.removeAll(autostartDesktopPath);
autostartDir.remove(info.fileName()); autostartDir.remove(info.fileName());
} else { } else {
qWarning() << "error happen..."; qWarning() << "error happen...";
@ -255,6 +316,7 @@ bool StartManager::setAutostart(const QString &desktop, const bool value)
} }
Q_EMIT autostartChanged(value ? autostartAdded : autostartDeleted, desktopFullPath); Q_EMIT autostartChanged(value ? autostartAdded : autostartDeleted, desktopFullPath);
setIsDBusCalled(false);
return true; return true;
} }
@ -431,33 +493,73 @@ void StartManager::loadSysMemLimitConfig()
void StartManager::listenAutostartFileEvents() void StartManager::listenAutostartFileEvents()
{ {
for (auto autostartDir : BaseDir::autoStartDirs()) { m_autostartFileWatcher->addPath(BaseDir::userAutoStartDir().c_str());
fileWatcher->addPath(autostartDir.c_str()); connect(m_autostartFileWatcher, &QFileSystemWatcher::directoryChanged, this, &StartManager::onAutoStartupPathChange, Qt::QueuedConnection);
}
connect(fileWatcher, &QFileSystemWatcher::directoryChanged, this, &StartManager::onAutoStartupPathChange, Qt::QueuedConnection);
} }
void StartManager::startAutostartProgram() void StartManager::startAutostartProgram()
{ {
auto func = [&] (QString file, uint64_t delayTime) { for (const QString &desktopFile : autostartList()) {
QThread::sleep(uint64_t(delayTime));
this->launchApp(file, 0, QStringList());
};
for (QString desktopFile : autostartList()) {
DesktopInfo info(desktopFile.toStdString()); DesktopInfo info(desktopFile.toStdString());
if (!info.isValidDesktop()) if (!info.isValidDesktop())
continue; continue;
int delayTime = info.getKeyFile()->getInt(MainSection, KeyXGnomeAutostartDelay.toStdString()); launchApp(desktopFile);
QTimer::singleShot(0, this, [&, desktopFile, delayTime] {
QThread::sleep(uint64_t(delayTime));
this->launchApp(desktopFile, 0, QStringList());
});
} }
} }
QStringList StartManager::getAutostartList() QStringList StartManager::getAutostartList()
{ {
return m_autostartFiles; QStringList autostartList;
for (const std::string &autostartDir : BaseDir::autoStartDirs()) {
QDir dir(autostartDir.c_str());
if (!dir.exists())
continue;
dir.setFilter(QDir::Files);
dir.setNameFilters({ "*.desktop" });
for (const auto &entry : dir.entryInfoList()) {
if (autostartList.contains(entry.absoluteFilePath()))
continue;
autostartList.push_back(entry.absoluteFilePath());
}
}
return autostartList;
}
QMap<QString, QString> StartManager::getDesktopToAutostartMap()
{
// 获取已加入到自启动列表应用的desktop全路径
QDir autostartDir(BaseDir::userAutoStartDir().c_str());
autostartDir.setFilter(QDir::Files);
autostartDir.setNameFilters({ "*.desktop" });
for (const auto &entry : autostartDir.entryInfoList()) {
const QFileInfo &fileInfo(entry.absoluteFilePath());
for (const std::string &appDir : BaseDir::appDirs()) {
QDir dir(appDir.c_str());
dir.setFilter(QDir::Files);
dir.setNameFilters({ "*.desktop" });
for (const auto &entry : dir.entryInfoList()) {
const QString &desktopPath = entry.absoluteFilePath();
if (desktopPath.contains(fileInfo.baseName()) &&
m_desktopDirToAutostartDirMap.find(desktopPath) == m_desktopDirToAutostartDirMap.end()) {
m_desktopDirToAutostartDirMap.insert(desktopPath, entry.absoluteFilePath());
}
}
}
}
return m_desktopDirToAutostartDirMap;
}
void StartManager::setIsDBusCalled(const bool state)
{
m_isDBusCalled = state;
}
bool StartManager::isDBusCalled() const
{
return m_isDBusCalled;
} }

View File

@ -70,13 +70,17 @@ private:
void listenAutostartFileEvents(); void listenAutostartFileEvents();
void startAutostartProgram(); void startAutostartProgram();
QStringList getAutostartList(); QStringList getAutostartList();
QMap<QString, QString> getDesktopToAutostartMap();
void setIsDBusCalled(const bool state);
bool isDBusCalled() const;
uint64_t minMemAvail; uint64_t minMemAvail;
uint64_t maxSwapUsed; uint64_t maxSwapUsed;
StartManagerDBusHandler *dbusHandler; StartManagerDBusHandler *dbusHandler;
QStringList m_autostartFiles; QStringList m_autostartFiles;
QFileSystemWatcher *fileWatcher; QMap<QString, QString> m_desktopDirToAutostartDirMap; // Desktop全路径和自启动目录
ApplicationManager *am; QFileSystemWatcher *m_autostartFileWatcher;
bool m_isDBusCalled;
}; };
#endif // STARTMANAGER_H #endif // STARTMANAGER_H