@ -8,10 +8,10 @@
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
#include <QStandardPaths>
 | 
			
		||||
 | 
			
		||||
bool ApplicationFilter::hiddenCheck(const std::unique_ptr<DesktopEntry> &entry) noexcept
 | 
			
		||||
bool ApplicationFilter::hiddenCheck(const DesktopEntry &entry) noexcept
 | 
			
		||||
{
 | 
			
		||||
    bool hidden{false};
 | 
			
		||||
    auto hiddenVal = entry->value(DesktopFileEntryKey, "Hidden");
 | 
			
		||||
    auto hiddenVal = entry.value(DesktopFileEntryKey, DesktopEntryHidden);
 | 
			
		||||
 | 
			
		||||
    if (hiddenVal.has_value()) {
 | 
			
		||||
        bool ok{false};
 | 
			
		||||
@ -24,9 +24,9 @@ bool ApplicationFilter::hiddenCheck(const std::unique_ptr<DesktopEntry> &entry)
 | 
			
		||||
    return hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ApplicationFilter::tryExecCheck(const std::unique_ptr<DesktopEntry> &entry) noexcept
 | 
			
		||||
bool ApplicationFilter::tryExecCheck(const DesktopEntry &entry) noexcept
 | 
			
		||||
{
 | 
			
		||||
    auto tryExecVal = entry->value(DesktopFileEntryKey, "TryExec");
 | 
			
		||||
    auto tryExecVal = entry.value(DesktopFileEntryKey, "TryExec");
 | 
			
		||||
    if (tryExecVal.has_value()) {
 | 
			
		||||
        auto executable = toString(tryExecVal.value());
 | 
			
		||||
        if (executable.isEmpty()) {
 | 
			
		||||
@ -44,7 +44,7 @@ bool ApplicationFilter::tryExecCheck(const std::unique_ptr<DesktopEntry> &entry)
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ApplicationFilter::showInCheck(const std::unique_ptr<DesktopEntry> &entry) noexcept
 | 
			
		||||
bool ApplicationFilter::showInCheck(const DesktopEntry &entry) noexcept
 | 
			
		||||
{
 | 
			
		||||
    auto desktops = QString::fromLocal8Bit(qgetenv("XDG_CURRENT_DESKTOP")).split(':', Qt::SkipEmptyParts);
 | 
			
		||||
    if (desktops.isEmpty()) {
 | 
			
		||||
@ -53,7 +53,7 @@ bool ApplicationFilter::showInCheck(const std::unique_ptr<DesktopEntry> &entry)
 | 
			
		||||
    desktops.removeDuplicates();
 | 
			
		||||
 | 
			
		||||
    bool showInCurrentDE{true};
 | 
			
		||||
    auto onlyShowInVal = entry->value(DesktopFileEntryKey, "OnlyShowIn");
 | 
			
		||||
    auto onlyShowInVal = entry.value(DesktopFileEntryKey, "OnlyShowIn");
 | 
			
		||||
    while (onlyShowInVal.has_value()) {
 | 
			
		||||
        auto deStr = toString(onlyShowInVal.value());
 | 
			
		||||
        if (deStr.isEmpty()) {
 | 
			
		||||
@ -75,7 +75,7 @@ bool ApplicationFilter::showInCheck(const std::unique_ptr<DesktopEntry> &entry)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool notShowInCurrentDE{false};
 | 
			
		||||
    auto notShowInVal = entry->value(DesktopFileEntryKey, "NotShowIn");
 | 
			
		||||
    auto notShowInVal = entry.value(DesktopFileEntryKey, "NotShowIn");
 | 
			
		||||
    while (notShowInVal.has_value()) {
 | 
			
		||||
        auto deStr = toString(notShowInVal.value());
 | 
			
		||||
        if (deStr.isEmpty()) {
 | 
			
		||||
@ -98,3 +98,18 @@ bool ApplicationFilter::showInCheck(const std::unique_ptr<DesktopEntry> &entry)
 | 
			
		||||
 | 
			
		||||
    return !showInCurrentDE or notShowInCurrentDE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ApplicationFilter::hiddenCheck(const std::unique_ptr<DesktopEntry> &entry) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return hiddenCheck(*entry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ApplicationFilter::tryExecCheck(const std::unique_ptr<DesktopEntry> &entry) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return tryExecCheck(*entry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ApplicationFilter::showInCheck(const std::unique_ptr<DesktopEntry> &entry) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return showInCheck(*entry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,9 @@ namespace ApplicationFilter {
 | 
			
		||||
bool hiddenCheck(const std::unique_ptr<DesktopEntry> &entry) noexcept;
 | 
			
		||||
bool tryExecCheck(const std::unique_ptr<DesktopEntry> &entry) noexcept;
 | 
			
		||||
bool showInCheck(const std::unique_ptr<DesktopEntry> &entry) noexcept;
 | 
			
		||||
bool hiddenCheck(const DesktopEntry &entry) noexcept;
 | 
			
		||||
bool tryExecCheck(const DesktopEntry &entry) noexcept;
 | 
			
		||||
bool showInCheck(const DesktopEntry &entry) noexcept;
 | 
			
		||||
 | 
			
		||||
}  // namespace ApplicationFilter
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -23,6 +23,8 @@ constexpr auto DDEApplicationManager1MimeManager1ObjectPath = u8"/org/desktopspe
 | 
			
		||||
constexpr auto DesktopFileEntryKey = u8"Desktop Entry";
 | 
			
		||||
constexpr auto DesktopFileActionKey = u8"Desktop Action ";
 | 
			
		||||
constexpr auto DesktopFileDefaultKeyLocale = "default";
 | 
			
		||||
constexpr auto X_Deepin_GenerateSource = u8"X-Deepin-GenerateSource";
 | 
			
		||||
constexpr auto DesktopEntryHidden = u8"Hidden";
 | 
			
		||||
 | 
			
		||||
constexpr auto ApplicationManagerServerDBusName =
 | 
			
		||||
#ifdef DDE_AM_USE_DEBUG_DBUS_NAME
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@
 | 
			
		||||
//
 | 
			
		||||
// SPDX-License-Identifier: LGPL-3.0-or-later
 | 
			
		||||
#include "applicationadaptor.h"
 | 
			
		||||
#include "applicationchecker.h"
 | 
			
		||||
#include "dbus/applicationmanager1adaptor.h"
 | 
			
		||||
#include "applicationservice.h"
 | 
			
		||||
#include "dbus/AMobjectmanager1adaptor.h"
 | 
			
		||||
@ -79,6 +80,8 @@ void ApplicationManager1Service::initService(QDBusConnection &connection) noexce
 | 
			
		||||
 | 
			
		||||
    scanApplications();
 | 
			
		||||
 | 
			
		||||
    auto needLaunch = scanAutoStart();
 | 
			
		||||
 | 
			
		||||
    scanInstances();
 | 
			
		||||
 | 
			
		||||
    loadHooks();
 | 
			
		||||
@ -112,16 +115,20 @@ void ApplicationManager1Service::initService(QDBusConnection &connection) noexce
 | 
			
		||||
 | 
			
		||||
    constexpr auto XSettings = "org.deepin.dde.XSettings1";
 | 
			
		||||
 | 
			
		||||
    auto *watcher =
 | 
			
		||||
        new QDBusServiceWatcher{XSettings, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration, this};
 | 
			
		||||
    auto *watcher = new (std::nothrow)
 | 
			
		||||
        QDBusServiceWatcher{XSettings, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration, this};
 | 
			
		||||
 | 
			
		||||
    auto *sigCon = new QMetaObject::Connection{};
 | 
			
		||||
    auto *sigCon = new (std::nothrow) QMetaObject::Connection{};
 | 
			
		||||
 | 
			
		||||
    auto singleSlot = [this, watcher, sigCon]() {
 | 
			
		||||
    auto singleSlot = [watcher, sigCon, autostartList = std::move(needLaunch)]() {
 | 
			
		||||
        QObject::disconnect(*sigCon);
 | 
			
		||||
        delete sigCon;
 | 
			
		||||
        qDebug() << XSettings << "is registered.";
 | 
			
		||||
        scanAutoStart();
 | 
			
		||||
 | 
			
		||||
        for (const auto &app : autostartList) {
 | 
			
		||||
            app->Launch({}, {}, {});
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        watcher->deleteLater();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -236,23 +243,29 @@ void ApplicationManager1Service::scanApplications() noexcept
 | 
			
		||||
{
 | 
			
		||||
    const auto &desktopFileDirs = getDesktopFileDirs();
 | 
			
		||||
 | 
			
		||||
    std::map<QString, DesktopFile> fileMap;
 | 
			
		||||
    applyIteratively(
 | 
			
		||||
        QList<QDir>(desktopFileDirs.crbegin(), desktopFileDirs.crend()),
 | 
			
		||||
        [this](const QFileInfo &info) -> bool {
 | 
			
		||||
        [&fileMap](const QFileInfo &info) -> bool {
 | 
			
		||||
            ParserError err{ParserError::NoError};
 | 
			
		||||
            auto ret = DesktopFile::searchDesktopFileByPath(info.absoluteFilePath(), err);
 | 
			
		||||
            if (!ret.has_value()) {
 | 
			
		||||
                qWarning() << "failed to search File:" << err;
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            if (!this->addApplication(std::move(ret).value())) {
 | 
			
		||||
                qWarning() << "add Application failed, skip...";
 | 
			
		||||
            }
 | 
			
		||||
            auto file = std::move(ret).value();
 | 
			
		||||
            fileMap.insert_or_assign(file.desktopId(), std::move(file));
 | 
			
		||||
            return false;  // means to apply this function to the rest of the files
 | 
			
		||||
        },
 | 
			
		||||
        QDir::Readable | QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot,
 | 
			
		||||
        {"*.desktop"},
 | 
			
		||||
        QDir::Name | QDir::DirsLast);
 | 
			
		||||
 | 
			
		||||
    for (auto &&[k, v] : std::move(fileMap)) {
 | 
			
		||||
        if (!addApplication(std::move(v))) {
 | 
			
		||||
            qWarning() << "add Application" << k << " failed, skip...";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ApplicationManager1Service::scanInstances() noexcept
 | 
			
		||||
@ -278,32 +291,117 @@ void ApplicationManager1Service::scanInstances() noexcept
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ApplicationManager1Service::scanAutoStart() noexcept
 | 
			
		||||
QList<QSharedPointer<ApplicationService>> ApplicationManager1Service::scanAutoStart() noexcept
 | 
			
		||||
{
 | 
			
		||||
    QList<QSharedPointer<ApplicationService>> ret;
 | 
			
		||||
    auto autostartDirs = getAutoStartDirs();
 | 
			
		||||
    QStringList needToLaunch;
 | 
			
		||||
    std::map<QString, DesktopFile> autostartItems;
 | 
			
		||||
 | 
			
		||||
    applyIteratively(
 | 
			
		||||
        QList<QDir>{autostartDirs.cbegin(), autostartDirs.cend()},
 | 
			
		||||
        [&needToLaunch](const QFileInfo &info) {
 | 
			
		||||
            if (info.isSymbolicLink()) {
 | 
			
		||||
                needToLaunch.emplace_back(info.symLinkTarget());
 | 
			
		||||
        QList<QDir>{autostartDirs.crbegin(), autostartDirs.crend()},
 | 
			
		||||
        [&autostartItems](const QFileInfo &info) {
 | 
			
		||||
            ParserError err{ParserError::InternalError};
 | 
			
		||||
            auto desktopSource = DesktopFile::searchDesktopFileByPath(info.absoluteFilePath(), err);
 | 
			
		||||
            if (err != ParserError::NoError) {
 | 
			
		||||
                qWarning() << "skip" << info.absoluteFilePath();
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            auto file = std::move(desktopSource).value();
 | 
			
		||||
            autostartItems.insert_or_assign(file.desktopId(), std::move(file));
 | 
			
		||||
            return false;
 | 
			
		||||
        },
 | 
			
		||||
        QDir::Readable | QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot,
 | 
			
		||||
        QDir::Readable | QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot,
 | 
			
		||||
        {"*.desktop"},
 | 
			
		||||
        QDir::Name | QDir::DirsLast);
 | 
			
		||||
 | 
			
		||||
    while (!needToLaunch.isEmpty()) {
 | 
			
		||||
        const auto &filePath = needToLaunch.takeFirst();
 | 
			
		||||
        auto appIt =
 | 
			
		||||
            std::find_if(m_applicationList.constKeyValueBegin(),
 | 
			
		||||
                         m_applicationList.constKeyValueEnd(),
 | 
			
		||||
                         [&filePath](const auto &pair) { return pair.second->m_desktopSource.sourcePath() == filePath; });
 | 
			
		||||
        if (appIt != m_applicationList.constKeyValueEnd()) {
 | 
			
		||||
            appIt->second->Launch({}, {}, {});
 | 
			
		||||
    for (auto &it : autostartItems) {
 | 
			
		||||
        auto desktopFile = std::move(it.second);
 | 
			
		||||
 | 
			
		||||
        DesktopFileGuard guard{desktopFile};
 | 
			
		||||
        if (!guard.try_open()) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        auto &file = desktopFile.sourceFileRef();
 | 
			
		||||
        QTextStream stream{&file};
 | 
			
		||||
        DesktopEntry tmp;
 | 
			
		||||
        auto err = tmp.parse(stream);
 | 
			
		||||
        if (err != ParserError::NoError) {
 | 
			
		||||
            qWarning() << "parse autostart file" << desktopFile.sourcePath() << " error:" << err;
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        QSharedPointer<ApplicationService> app{nullptr};
 | 
			
		||||
        auto asApplication = tmp.value(DesktopFileEntryKey, X_Deepin_GenerateSource).value_or(DesktopEntry::Value{});
 | 
			
		||||
        if (!asApplication.isNull()) {  // modified by application manager
 | 
			
		||||
            auto appSource = asApplication.toString();
 | 
			
		||||
 | 
			
		||||
            QFileInfo sourceInfo{appSource};
 | 
			
		||||
            if ((!sourceInfo.exists() or !sourceInfo.isFile()) and !file.remove()) {
 | 
			
		||||
                qWarning() << "remove invalid autostart file error:" << file.error();
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // add original application
 | 
			
		||||
            auto desktopSource = DesktopFile::searchDesktopFileByPath(appSource, err);
 | 
			
		||||
            if (err != ParserError::NoError) {
 | 
			
		||||
                qWarning() << "search autostart application failed:" << err;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            auto source = std::move(desktopSource).value();
 | 
			
		||||
 | 
			
		||||
            if (source.desktopId().isEmpty()) {
 | 
			
		||||
                qWarning() << X_Deepin_GenerateSource << "is" << appSource
 | 
			
		||||
                           << ", but couldn't find it in applications, maybe this autostart file has been modified, skip.";
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // add application directly, it wouldn't add the same application twice.
 | 
			
		||||
            app = addApplication(std::move(source));
 | 
			
		||||
            if (!app) {
 | 
			
		||||
                qWarning() << "add autostart application failed, skip.";
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        auto shouldLaunch = tmp.value(DesktopFileEntryKey, DesktopEntryHidden).value_or(DesktopEntry::Value{});
 | 
			
		||||
        if (!shouldLaunch.isNull() and (shouldLaunch.toString().compare("true", Qt::CaseInsensitive) == 0)) {
 | 
			
		||||
            qInfo() << "shouldn't launch this autoStart item.";
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (app) {
 | 
			
		||||
            ret.append(app);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // maybe some application generate autostart desktop by itself
 | 
			
		||||
        if (ApplicationFilter::tryExecCheck(tmp) or ApplicationFilter::showInCheck(tmp)) {
 | 
			
		||||
            qInfo() << "autostart application couldn't pass check.";
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (auto appIt = std::find_if(m_applicationList.cbegin(),
 | 
			
		||||
                                      m_applicationList.cend(),
 | 
			
		||||
                                      [&desktopFile](const auto &app) { return desktopFile.desktopId() == app->id(); });
 | 
			
		||||
            appIt != m_applicationList.cend()) {
 | 
			
		||||
            qInfo() << "app already exists. use it to launch instance.";
 | 
			
		||||
            ret.append(*appIt);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        guard.close();
 | 
			
		||||
        // new application
 | 
			
		||||
        auto newApp = addApplication(std::move(desktopFile));
 | 
			
		||||
        if (!newApp) {
 | 
			
		||||
            qWarning() << "add autostart application failed, skip.";
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ret.append(newApp);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ApplicationManager1Service::loadHooks() noexcept
 | 
			
		||||
@ -337,36 +435,39 @@ QList<QDBusObjectPath> ApplicationManager1Service::list() const
 | 
			
		||||
    return m_applicationList.keys();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ApplicationManager1Service::addApplication(DesktopFile desktopFileSource) noexcept
 | 
			
		||||
QSharedPointer<ApplicationService> ApplicationManager1Service::addApplication(DesktopFile desktopFileSource) noexcept
 | 
			
		||||
{
 | 
			
		||||
    auto source = desktopFileSource.sourcePath();
 | 
			
		||||
    QSharedPointer<ApplicationService> application =
 | 
			
		||||
        ApplicationService::createApplicationService(std::move(desktopFileSource), this, m_storage);
 | 
			
		||||
    if (!application) {
 | 
			
		||||
        return false;
 | 
			
		||||
        qWarning() << "can't create application" << source;
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (m_applicationList.constFind(application->applicationPath()) != m_applicationList.cend()) {
 | 
			
		||||
    if (auto app = m_applicationList.constFind(application->applicationPath()); app != m_applicationList.cend()) {
 | 
			
		||||
        qInfo() << "this application already exists."
 | 
			
		||||
                << "desktop source:" << application->desktopFileSource().sourcePath();
 | 
			
		||||
        return false;
 | 
			
		||||
                << "current desktop source:" << application->desktopFileSource().sourcePath()
 | 
			
		||||
                << "exists app source:" << app->data()->desktopFileSource().sourcePath();
 | 
			
		||||
        return *app;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto *ptr = application.data();
 | 
			
		||||
 | 
			
		||||
    if (auto *adaptor = new (std::nothrow) ApplicationAdaptor{ptr}; adaptor == nullptr) {
 | 
			
		||||
        qCritical() << "new ApplicationAdaptor failed.";
 | 
			
		||||
        return false;
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!registerObjectToDBus(ptr, application->applicationPath().path(), ApplicationInterface)) {
 | 
			
		||||
        return false;
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    m_applicationList.insert(application->applicationPath(), application);
 | 
			
		||||
 | 
			
		||||
    emit listChanged();
 | 
			
		||||
    emit InterfacesAdded(application->applicationPath(), getChildInterfacesAndPropertiesFromObject(ptr));
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
    return application;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ApplicationManager1Service::removeOneApplication(const QDBusObjectPath &application) noexcept
 | 
			
		||||
 | 
			
		||||
@ -36,7 +36,7 @@ public:
 | 
			
		||||
    [[nodiscard]] QList<QDBusObjectPath> list() const;
 | 
			
		||||
 | 
			
		||||
    void initService(QDBusConnection &connection) noexcept;
 | 
			
		||||
    bool addApplication(DesktopFile desktopFileSource) noexcept;
 | 
			
		||||
    QSharedPointer<ApplicationService> addApplication(DesktopFile desktopFileSource) noexcept;
 | 
			
		||||
    void removeOneApplication(const QDBusObjectPath &application) noexcept;
 | 
			
		||||
    void removeAllApplication() noexcept;
 | 
			
		||||
    [[nodiscard]] QMap<QDBusObjectPath, QSharedPointer<ApplicationService>>
 | 
			
		||||
@ -74,7 +74,7 @@ private:
 | 
			
		||||
    void scanMimeInfos() noexcept;
 | 
			
		||||
    void scanApplications() noexcept;
 | 
			
		||||
    void scanInstances() noexcept;
 | 
			
		||||
    void scanAutoStart() noexcept;
 | 
			
		||||
    QList<QSharedPointer<ApplicationService>> scanAutoStart() noexcept;
 | 
			
		||||
    void loadHooks() noexcept;
 | 
			
		||||
    void addInstanceToApplication(const QString &unitName, const QDBusObjectPath &systemdUnitPath);
 | 
			
		||||
    void removeInstanceFromApplication(const QString &unitName, const QDBusObjectPath &systemdUnitPath);
 | 
			
		||||
 | 
			
		||||
@ -6,10 +6,14 @@
 | 
			
		||||
#include "APPobjectmanager1adaptor.h"
 | 
			
		||||
#include "applicationchecker.h"
 | 
			
		||||
#include "applicationmanagerstorage.h"
 | 
			
		||||
#include "constant.h"
 | 
			
		||||
#include "global.h"
 | 
			
		||||
#include "iniParser.h"
 | 
			
		||||
#include "propertiesForwarder.h"
 | 
			
		||||
#include "dbus/instanceadaptor.h"
 | 
			
		||||
#include "launchoptions.h"
 | 
			
		||||
#include "desktopentry.h"
 | 
			
		||||
#include "desktopfileparser.h"
 | 
			
		||||
#include <QUuid>
 | 
			
		||||
#include <QStringList>
 | 
			
		||||
#include <QList>
 | 
			
		||||
@ -19,6 +23,11 @@
 | 
			
		||||
#include <QStandardPaths>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <new>
 | 
			
		||||
#include <qdbuserror.h>
 | 
			
		||||
#include <qfileinfo.h>
 | 
			
		||||
#include <qlogging.h>
 | 
			
		||||
#include <qnamespace.h>
 | 
			
		||||
#include <qtmetamacros.h>
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include <wordexp.h>
 | 
			
		||||
 | 
			
		||||
@ -102,6 +111,7 @@ QSharedPointer<ApplicationService> ApplicationService::createApplicationService(
 | 
			
		||||
    DesktopFileGuard guard{app->desktopFileSource()};
 | 
			
		||||
 | 
			
		||||
    if (!guard.try_open()) {
 | 
			
		||||
        qDebug() << "open source desktop failed.";
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -139,14 +149,17 @@ QSharedPointer<ApplicationService> ApplicationService::createApplicationService(
 | 
			
		||||
bool ApplicationService::shouldBeShown(const std::unique_ptr<DesktopEntry> &entry) noexcept
 | 
			
		||||
{
 | 
			
		||||
    if (ApplicationFilter::hiddenCheck(entry)) {
 | 
			
		||||
        qDebug() << "hidden check failed.";
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ApplicationFilter::tryExecCheck(entry)) {
 | 
			
		||||
        qDebug() << "tryExec check failed";
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ApplicationFilter::showInCheck(entry)) {
 | 
			
		||||
        qDebug() << "showIn check failed.";
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -541,46 +554,76 @@ void ApplicationService::setScaleFactor(double value) noexcept
 | 
			
		||||
    emit scaleFactorChanged();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ApplicationService::autostartCheck(const QString &linkPath) const noexcept
 | 
			
		||||
bool ApplicationService::autostartCheck(const QString &filePath) noexcept
 | 
			
		||||
{
 | 
			
		||||
    QFileInfo info{linkPath};
 | 
			
		||||
    qDebug() << "current check autostart file:" << filePath;
 | 
			
		||||
 | 
			
		||||
    if (info.exists()) {
 | 
			
		||||
        if (info.isSymbolicLink() and info.symLinkTarget() == m_desktopSource.sourcePath()) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        qWarning() << "same name desktop file exists:" << linkPath << "but this may not created by AM.";
 | 
			
		||||
    QFile file{filePath};
 | 
			
		||||
    if (!file.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text)) {
 | 
			
		||||
        qWarning() << "open" << filePath << "failed:" << file.errorString();
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
    QTextStream stream{&file};
 | 
			
		||||
    DesktopEntry s;
 | 
			
		||||
    if (auto err = s.parse(stream); err != ParserError::NoError) {
 | 
			
		||||
        qWarning() << "parse" << filePath << "failed:" << err;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto hiddenVal = s.value(DesktopFileEntryKey, DesktopEntryHidden);
 | 
			
		||||
    if (!hiddenVal) {
 | 
			
		||||
        qDebug() << "no hidden in autostart desktop";
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto hidden = hiddenVal.value().toString();
 | 
			
		||||
    return hidden.compare("false", Qt::CaseInsensitive) == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ApplicationService::isAutoStart() const noexcept
 | 
			
		||||
{
 | 
			
		||||
    auto path = getAutoStartDirs().first();
 | 
			
		||||
    auto linkName = QDir{path}.filePath(m_desktopSource.desktopId() + ".desktop");
 | 
			
		||||
    return autostartCheck(linkName);
 | 
			
		||||
    auto autostartDirs = getAutoStartDirs();
 | 
			
		||||
    auto sourcePath = m_desktopSource.sourcePath();
 | 
			
		||||
    auto userAutostart = QDir{autostartDirs.first()}.filePath(id() + ".desktop");
 | 
			
		||||
 | 
			
		||||
    QFileInfo info{userAutostart};
 | 
			
		||||
    auto isOverride = info.exists() and info.isFile();
 | 
			
		||||
 | 
			
		||||
    if (std::any_of(autostartDirs.cbegin(), autostartDirs.cend(), [&sourcePath](const QString &dir) {
 | 
			
		||||
            return sourcePath.startsWith(dir);
 | 
			
		||||
        })) {  // load from autostart
 | 
			
		||||
        return isOverride ? autostartCheck(userAutostart) : autostartCheck(sourcePath);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return isOverride and autostartCheck(userAutostart);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ApplicationService::setAutoStart(bool autostart) noexcept
 | 
			
		||||
{
 | 
			
		||||
    auto path = getAutoStartDirs().first();
 | 
			
		||||
    auto linkName = QDir{path}.filePath(m_desktopSource.desktopId() + ".desktop");
 | 
			
		||||
    auto &file = m_desktopSource.sourceFileRef();
 | 
			
		||||
    if (isAutoStart() == autostart) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (autostart) {
 | 
			
		||||
        if (!autostartCheck(linkName) and !file.link(linkName)) {
 | 
			
		||||
            qWarning() << "link to autostart failed:" << file.errorString();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        if (autostartCheck(linkName)) {
 | 
			
		||||
            QFile linkFile{linkName};
 | 
			
		||||
            if (!linkFile.remove()) {
 | 
			
		||||
                qWarning() << "remove link failed:" << linkFile.errorString();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    auto fileName = QDir{getAutoStartDirs().first()}.filePath(m_desktopSource.desktopId() + ".desktop");
 | 
			
		||||
    QFile autostartFile{fileName};
 | 
			
		||||
    if (!autostartFile.open(QFile::WriteOnly | QFile::Text | QFile::Truncate)) {
 | 
			
		||||
        qWarning() << "open file" << fileName << "failed:" << autostartFile.error();
 | 
			
		||||
        sendErrorReply(QDBusError::Failed);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto newEntry = *m_entry;
 | 
			
		||||
    newEntry.insert(DesktopFileEntryKey, X_Deepin_GenerateSource, m_desktopSource.sourcePath());
 | 
			
		||||
    newEntry.insert(DesktopFileEntryKey, DesktopEntryHidden, !autostart);
 | 
			
		||||
 | 
			
		||||
    auto hideAutostart = toString(newEntry.data()).toLocal8Bit();
 | 
			
		||||
    auto writeBytes = autostartFile.write(hideAutostart);
 | 
			
		||||
 | 
			
		||||
    if (writeBytes != hideAutostart.size() or !autostartFile.flush()) {
 | 
			
		||||
        qWarning() << "incomplete write:" << autostartFile.error();
 | 
			
		||||
        sendErrorReply(QDBusError::Failed, "set failed: filesystem error.");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    emit autostartChanged();
 | 
			
		||||
@ -1021,7 +1064,7 @@ double getScaleFactor() noexcept
 | 
			
		||||
QString getDeepinWineScaleFactor(const QString &appId) noexcept
 | 
			
		||||
{
 | 
			
		||||
    qCritical() << "Don't using env to control the window scale factor,  this function"
 | 
			
		||||
                   "should via using graphisc server(Wayland Compositor/Xorg Xft) in deepin wine.";
 | 
			
		||||
                   "should via using graphic server(Wayland Compositor/Xorg Xft) in deepin wine.";
 | 
			
		||||
 | 
			
		||||
    QString factor{"1.0"};
 | 
			
		||||
    auto objectPath = QString{"/dde_launcher/org_deepin_dde_launcher/%1"}.arg(getCurrentUID());
 | 
			
		||||
 | 
			
		||||
@ -177,7 +177,7 @@ private:
 | 
			
		||||
    QMap<QDBusObjectPath, QSharedPointer<InstanceService>> m_Instances;
 | 
			
		||||
    void updateAfterLaunch(bool isLaunch) noexcept;
 | 
			
		||||
    static bool shouldBeShown(const std::unique_ptr<DesktopEntry> &entry) noexcept;
 | 
			
		||||
    [[nodiscard]] bool autostartCheck(const QString &linkPath) const noexcept;
 | 
			
		||||
    [[nodiscard]] static bool autostartCheck(const QString &filePath) noexcept;
 | 
			
		||||
    [[nodiscard]] ApplicationManager1Service *parent() { return dynamic_cast<ApplicationManager1Service *>(QObject::parent()); }
 | 
			
		||||
    [[nodiscard]] const ApplicationManager1Service *parent() const
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
@ -111,18 +111,31 @@ std::optional<DesktopFile> DesktopFile::searchDesktopFileByPath(const QString &d
 | 
			
		||||
        return std::nullopt;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QString path{desktopFile};
 | 
			
		||||
    QString id;
 | 
			
		||||
 | 
			
		||||
    const auto &XDGDataDirs = getDesktopFileDirs();
 | 
			
		||||
    auto idGen = std::any_of(XDGDataDirs.cbegin(), XDGDataDirs.cend(), [&desktopFile](const QString &suffixPath) {
 | 
			
		||||
    const auto &autostartDirs = getAutoStartDirs();
 | 
			
		||||
    auto IsCommonApp = std::any_of(XDGDataDirs.cbegin(), XDGDataDirs.cend(), [&desktopFile](const QString &suffixPath) {
 | 
			
		||||
        return desktopFile.startsWith(suffixPath);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (idGen) {
 | 
			
		||||
    auto IsAutostartApp = std::any_of(autostartDirs.cbegin(), autostartDirs.cend(), [&desktopFile](const QString &suffixPath) {
 | 
			
		||||
        return desktopFile.startsWith(suffixPath);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    QString path{desktopFile};
 | 
			
		||||
    QString id;
 | 
			
		||||
 | 
			
		||||
    if (IsCommonApp or IsAutostartApp) {
 | 
			
		||||
        auto tmp = path.chopped(sizeof(desktopSuffix) - 1);
 | 
			
		||||
        auto components = tmp.split(QDir::separator()).toList();
 | 
			
		||||
        auto it = std::find(components.cbegin(), components.cend(), "applications");
 | 
			
		||||
        auto components = tmp.split(QDir::separator(), Qt::SkipEmptyParts).toList();
 | 
			
		||||
        decltype(components)::const_iterator it;
 | 
			
		||||
        if (auto appIt = std::find(components.cbegin(), components.cend(), "applications"); appIt != components.cend()) {
 | 
			
		||||
            it = appIt;
 | 
			
		||||
 | 
			
		||||
        } else if (auto autostartIt = std::find(components.cbegin(), components.cend(), "autostart");
 | 
			
		||||
                   autostartIt != components.cend()) {
 | 
			
		||||
            it = autostartIt;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        QString FileId;
 | 
			
		||||
        ++it;
 | 
			
		||||
        while (it != components.cend()) {
 | 
			
		||||
@ -236,6 +249,16 @@ std::optional<DesktopEntry::Value> DesktopEntry::value(const QString &groupKey,
 | 
			
		||||
    return *it;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DesktopEntry::insert(const QString &key, const QString &valueKey, Value &&val) noexcept
 | 
			
		||||
{
 | 
			
		||||
    auto outer = m_entryMap.find(key);
 | 
			
		||||
    if (outer == m_entryMap.end()) {
 | 
			
		||||
        outer = m_entryMap.insert(key, {});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    outer->insert(valueKey, val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString unescape(const QString &str, bool shellMode) noexcept
 | 
			
		||||
{
 | 
			
		||||
    QString unescapedStr;
 | 
			
		||||
 | 
			
		||||
@ -78,6 +78,10 @@ struct DesktopFileGuard
 | 
			
		||||
 | 
			
		||||
    bool try_open()
 | 
			
		||||
    {
 | 
			
		||||
        if (!fileRef.m_fileSource) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (fileRef.m_fileSource->isOpen()) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
@ -90,13 +94,19 @@ struct DesktopFileGuard
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~DesktopFileGuard()
 | 
			
		||||
    void close()
 | 
			
		||||
    {
 | 
			
		||||
        if (!fileRef.m_fileSource) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (fileRef.m_fileSource->isOpen()) {
 | 
			
		||||
            fileRef.m_fileSource->close();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~DesktopFileGuard() { close(); }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    const DesktopFile &fileRef;
 | 
			
		||||
};
 | 
			
		||||
@ -116,6 +126,8 @@ public:
 | 
			
		||||
    [[nodiscard]] ParserError parse(QTextStream &stream) noexcept;
 | 
			
		||||
    [[nodiscard]] std::optional<QMap<QString, Value>> group(const QString &key) const noexcept;
 | 
			
		||||
    [[nodiscard]] std::optional<Value> value(const QString &key, const QString &valueKey) const noexcept;
 | 
			
		||||
    void insert(const QString &key, const QString &valueKey, Value &&val) noexcept;
 | 
			
		||||
    [[nodiscard]] const auto &data() const noexcept { return m_entryMap; }
 | 
			
		||||
 | 
			
		||||
    friend bool operator==(const DesktopEntry &lhs, const DesktopEntry &rhs);
 | 
			
		||||
    friend bool operator!=(const DesktopEntry &lhs, const DesktopEntry &rhs);
 | 
			
		||||
 | 
			
		||||
@ -403,7 +403,12 @@ inline QStringList getXDGDataDirs()
 | 
			
		||||
        XDGDataDirs.append("/usr/share");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    XDGDataDirs.push_front(getXDGDataHome());
 | 
			
		||||
    auto XDGDataHome = getXDGDataHome();
 | 
			
		||||
    if (XDGDataDirs.contains(XDGDataHome)) {
 | 
			
		||||
        XDGDataDirs.removeAll(XDGDataHome);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    XDGDataDirs.push_front(XDGDataHome);
 | 
			
		||||
    return XDGDataDirs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -416,6 +421,7 @@ inline QStringList getDesktopFileDirs()
 | 
			
		||||
        }
 | 
			
		||||
        str.append("applications");
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return XDGDataDirs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user