feat: replace exec during autostart process
create directory of user applciation if dosen't exists Signed-off-by: ComixHe <heyuming@deepin.org>
This commit is contained in:
parent
2fb5567eaf
commit
71b3b0a6c0
@ -12,6 +12,7 @@
|
|||||||
#include "desktopfilegenerator.h"
|
#include "desktopfilegenerator.h"
|
||||||
#include "processguesser1service.h"
|
#include "processguesser1service.h"
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QHash>
|
||||||
#include <QDBusMessage>
|
#include <QDBusMessage>
|
||||||
#include <QStringBuilder>
|
#include <QStringBuilder>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -123,13 +124,13 @@ void ApplicationManager1Service::initService(QDBusConnection &connection) noexce
|
|||||||
|
|
||||||
auto *sigCon = new (std::nothrow) QMetaObject::Connection{};
|
auto *sigCon = new (std::nothrow) QMetaObject::Connection{};
|
||||||
|
|
||||||
auto singleSlot = [watcher, sigCon, autostartList = std::move(needLaunch)]() {
|
auto singleSlot = [watcher, sigCon, autostartMap = std::move(needLaunch)]() {
|
||||||
QObject::disconnect(*sigCon);
|
QObject::disconnect(*sigCon);
|
||||||
delete sigCon;
|
delete sigCon;
|
||||||
qDebug() << XSettings << "is registered.";
|
qDebug() << XSettings << "is registered.";
|
||||||
|
|
||||||
for (const auto &app : autostartList) {
|
for (const auto &[app, realExec] : autostartMap.asKeyValueRange()) {
|
||||||
app->Launch({}, {}, {});
|
app->Launch({}, {}, {}, realExec);
|
||||||
}
|
}
|
||||||
|
|
||||||
watcher->deleteLater();
|
watcher->deleteLater();
|
||||||
@ -294,9 +295,9 @@ void ApplicationManager1Service::scanInstances() noexcept
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QSharedPointer<ApplicationService>> ApplicationManager1Service::scanAutoStart() noexcept
|
QHash<QSharedPointer<ApplicationService>, QString> ApplicationManager1Service::scanAutoStart() noexcept
|
||||||
{
|
{
|
||||||
QList<QSharedPointer<ApplicationService>> ret;
|
QHash<QSharedPointer<ApplicationService>, QString> ret;
|
||||||
auto autostartDirs = getAutoStartDirs();
|
auto autostartDirs = getAutoStartDirs();
|
||||||
std::map<QString, DesktopFile> autostartItems;
|
std::map<QString, DesktopFile> autostartItems;
|
||||||
|
|
||||||
@ -374,7 +375,9 @@ QList<QSharedPointer<ApplicationService>> ApplicationManager1Service::scanAutoSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (app) {
|
if (app) {
|
||||||
ret.append(app);
|
auto realExec = tmp.value(DesktopFileEntryKey, "Exec").value_or(QString{""}).toString();
|
||||||
|
qInfo() << "launch normal autostart application " << app->id() << " by " << realExec;
|
||||||
|
ret.insert(app, realExec);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,8 +391,9 @@ QList<QSharedPointer<ApplicationService>> ApplicationManager1Service::scanAutoSt
|
|||||||
m_applicationList.cend(),
|
m_applicationList.cend(),
|
||||||
[&desktopFile](const auto &app) { return desktopFile.desktopId() == app->id(); });
|
[&desktopFile](const auto &app) { return desktopFile.desktopId() == app->id(); });
|
||||||
appIt != m_applicationList.cend()) {
|
appIt != m_applicationList.cend()) {
|
||||||
qInfo() << "app already exists. use it to launch instance.";
|
auto realExec = tmp.value(DesktopFileEntryKey, "Exec").value_or(QString{""}).toString();
|
||||||
ret.append(*appIt);
|
qInfo() << "launch exist autostart application " << (*appIt)->id() << " by " << realExec;
|
||||||
|
ret.insert(*appIt, realExec);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,7 +405,9 @@ QList<QSharedPointer<ApplicationService>> ApplicationManager1Service::scanAutoSt
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.append(newApp);
|
auto realExec = newApp->m_entry->value(DesktopFileEntryKey, "Exec").value_or(QString{""}).toString();
|
||||||
|
qInfo() << "launch new autostart application " << newApp->id() << " by " << realExec;
|
||||||
|
ret.insert(newApp, realExec);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -642,7 +648,14 @@ QString ApplicationManager1Service::addUserApplication(const QVariantMap &deskto
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QDir xdgDataHome{getXDGDataHome() + "/applications"};
|
QDir xdgDataHome;
|
||||||
|
QString dir{getXDGDataHome() + "/applications"};
|
||||||
|
if (!xdgDataHome.mkpath(dir)) {
|
||||||
|
sendErrorReply(QDBusError::Failed, "couldn't create directory of user applications.");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
xdgDataHome.setPath(dir);
|
||||||
const auto &filePath = xdgDataHome.filePath(name);
|
const auto &filePath = xdgDataHome.filePath(name);
|
||||||
|
|
||||||
if (QFileInfo info{filePath}; info.exists() and info.isFile()) {
|
if (QFileInfo info{filePath}; info.exists() and info.isFile()) {
|
||||||
|
@ -74,7 +74,7 @@ private:
|
|||||||
void scanMimeInfos() noexcept;
|
void scanMimeInfos() noexcept;
|
||||||
void scanApplications() noexcept;
|
void scanApplications() noexcept;
|
||||||
void scanInstances() noexcept;
|
void scanInstances() noexcept;
|
||||||
QList<QSharedPointer<ApplicationService>> scanAutoStart() noexcept;
|
QHash<QSharedPointer<ApplicationService>, QString> scanAutoStart() noexcept;
|
||||||
void loadHooks() noexcept;
|
void loadHooks() noexcept;
|
||||||
void addInstanceToApplication(const QString &unitName, const QDBusObjectPath &systemdUnitPath);
|
void addInstanceToApplication(const QString &unitName, const QDBusObjectPath &systemdUnitPath);
|
||||||
void removeInstanceFromApplication(const QString &unitName, const QDBusObjectPath &systemdUnitPath);
|
void removeInstanceFromApplication(const QString &unitName, const QDBusObjectPath &systemdUnitPath);
|
||||||
|
@ -173,9 +173,10 @@ bool ApplicationService::shouldBeShown(const std::unique_ptr<DesktopEntry> &entr
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringList &fields, const QVariantMap &options)
|
QDBusObjectPath
|
||||||
|
ApplicationService::Launch(const QString &action, const QStringList &fields, const QVariantMap &options, const QString &realExec)
|
||||||
{
|
{
|
||||||
QString execStr;
|
QString execStr{};
|
||||||
bool ok;
|
bool ok;
|
||||||
const auto &supportedActions = actions();
|
const auto &supportedActions = actions();
|
||||||
auto optionsMap = options;
|
auto optionsMap = options;
|
||||||
@ -190,7 +191,16 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL
|
|||||||
optionsMap.insert("env", oldEnv);
|
optionsMap.insert("env", oldEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!action.isEmpty() and !supportedActions.isEmpty()) { // break trick
|
if (!realExec.isNull()) { // we want to replace exec of this applications.
|
||||||
|
if (realExec.isEmpty()) {
|
||||||
|
qWarning() << "try to replace exec but it's empty.";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
execStr = realExec;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (execStr.isEmpty() and !action.isEmpty() and !supportedActions.isEmpty()) { // break trick
|
||||||
if (auto index = supportedActions.indexOf(action); index == -1) {
|
if (auto index = supportedActions.indexOf(action); index == -1) {
|
||||||
qWarning() << "can't find " << action << " in supported actions List. application will use default action to launch.";
|
qWarning() << "can't find " << action << " in supported actions List. application will use default action to launch.";
|
||||||
break;
|
break;
|
||||||
@ -215,7 +225,9 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL
|
|||||||
if (!Actions) {
|
if (!Actions) {
|
||||||
QString msg{"application can't be executed."};
|
QString msg{"application can't be executed."};
|
||||||
qWarning() << msg;
|
qWarning() << msg;
|
||||||
sendErrorReply(QDBusError::Failed, msg);
|
if (calledFromDBus()) {
|
||||||
|
sendErrorReply(QDBusError::Failed, msg);
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +235,9 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL
|
|||||||
if (execStr.isEmpty()) {
|
if (execStr.isEmpty()) {
|
||||||
QString msg{"maybe entry actions's format is invalid, abort launch."};
|
QString msg{"maybe entry actions's format is invalid, abort launch."};
|
||||||
qWarning() << msg;
|
qWarning() << msg;
|
||||||
sendErrorReply(QDBusError::Failed, msg);
|
if (calledFromDBus()) {
|
||||||
|
sendErrorReply(QDBusError::Failed, msg);
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -235,14 +249,18 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL
|
|||||||
auto cmds = generateCommand(optionsMap);
|
auto cmds = generateCommand(optionsMap);
|
||||||
auto task = unescapeExec(execStr, fields);
|
auto task = unescapeExec(execStr, fields);
|
||||||
if (!task) {
|
if (!task) {
|
||||||
sendErrorReply(QDBusError::InternalError, "Invalid Command.");
|
if (calledFromDBus()) {
|
||||||
|
sendErrorReply(QDBusError::InternalError, "Invalid Command.");
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [bin, execCmds, res] = std::move(task);
|
auto [bin, execCmds, res] = std::move(task);
|
||||||
if (bin.isEmpty()) {
|
if (bin.isEmpty()) {
|
||||||
qCritical() << "error command is detected, abort.";
|
qCritical() << "error command is detected, abort.";
|
||||||
sendErrorReply(QDBusError::Failed);
|
if (calledFromDBus()) {
|
||||||
|
sendErrorReply(QDBusError::Failed);
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,20 +610,30 @@ bool ApplicationService::autostartCheck(const QString &filePath) noexcept
|
|||||||
|
|
||||||
bool ApplicationService::isAutoStart() const noexcept
|
bool ApplicationService::isAutoStart() const noexcept
|
||||||
{
|
{
|
||||||
auto autostartDirs = getAutoStartDirs();
|
auto appId = id();
|
||||||
auto sourcePath = m_desktopSource.sourcePath();
|
auto dirs = getAutoStartDirs();
|
||||||
auto userAutostart = QDir{autostartDirs.first()}.filePath(id() + ".desktop");
|
QString destDesktopFile;
|
||||||
|
|
||||||
QFileInfo info{userAutostart};
|
applyIteratively(
|
||||||
auto isOverride = info.exists() and info.isFile();
|
QList<QDir>(dirs.crbegin(), dirs.crend()),
|
||||||
|
[&appId, &destDesktopFile](const QFileInfo &file) {
|
||||||
|
auto filePath = file.absoluteFilePath();
|
||||||
|
if (appId == getAutostartAppIdFromAbsolutePath(filePath)) {
|
||||||
|
destDesktopFile = filePath;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
QDir::Readable | QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot,
|
||||||
|
{"*.desktop"},
|
||||||
|
QDir::Name | QDir::DirsLast);
|
||||||
|
|
||||||
if (std::any_of(autostartDirs.cbegin(), autostartDirs.cend(), [&sourcePath](const QString &dir) {
|
if (destDesktopFile.isEmpty()) {
|
||||||
return sourcePath.startsWith(dir);
|
qDebug() << "couldn't find autostart desktopFile.";
|
||||||
})) { // load from autostart
|
return false;
|
||||||
return isOverride ? autostartCheck(userAutostart) : autostartCheck(sourcePath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return isOverride and autostartCheck(userAutostart);
|
return autostartCheck(destDesktopFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplicationService::setAutoStart(bool autostart) noexcept
|
void ApplicationService::setAutoStart(bool autostart) noexcept
|
||||||
|
@ -133,7 +133,9 @@ private Q_SLOTS:
|
|||||||
void onGlobalScaleFactorChanged() noexcept;
|
void onGlobalScaleFactorChanged() noexcept;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
QDBusObjectPath Launch(const QString &action, const QStringList &fields, const QVariantMap &options);
|
// NOTE: 'realExec' only for internal implementation
|
||||||
|
QDBusObjectPath
|
||||||
|
Launch(const QString &action, const QStringList &fields, const QVariantMap &options, const QString &realExec = {});
|
||||||
[[nodiscard]] ObjectMap GetManagedObjects() const;
|
[[nodiscard]] ObjectMap GetManagedObjects() const;
|
||||||
[[nodiscard]] bool SendToDesktop() const noexcept;
|
[[nodiscard]] bool SendToDesktop() const noexcept;
|
||||||
[[nodiscard]] bool RemoveFromDesktop() const noexcept;
|
[[nodiscard]] bool RemoveFromDesktop() const noexcept;
|
||||||
|
14
src/global.h
14
src/global.h
@ -630,4 +630,18 @@ inline uint getPidFromPidFd(const QDBusUnixFileDescriptor &pidfd) noexcept
|
|||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline QString getAutostartAppIdFromAbsolutePath(const QString &path)
|
||||||
|
{
|
||||||
|
constexpr decltype(auto) desktopSuffix{u8".desktop"};
|
||||||
|
auto tmp = path.chopped(sizeof(desktopSuffix) - 1);
|
||||||
|
auto components = tmp.split(QDir::separator(), Qt::SkipEmptyParts);
|
||||||
|
auto location = std::find(components.cbegin(), components.cend(), "autostart");
|
||||||
|
if (location == components.cend()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto appId = QStringList{location + 1, components.cend()}.join('-');
|
||||||
|
return appId;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user