feat: add ProcessGuesser1 service
Signed-off-by: ComixHe <heyuming@deepin.org>
This commit is contained in:
		
							
								
								
									
										9
									
								
								api/dbus/org.desktopspec.ProcessGuesser1.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								api/dbus/org.desktopspec.ProcessGuesser1.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "https://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
 | 
			
		||||
<node>
 | 
			
		||||
    <interface name="org.desktopspec.ProcessGuesser1">
 | 
			
		||||
        <method name="GuessApplicationId">
 | 
			
		||||
            <arg type="h" name="pidfd" direction="in" />
 | 
			
		||||
            <arg type="s" name="appId" direction="out" />
 | 
			
		||||
        </method>
 | 
			
		||||
    </interface>
 | 
			
		||||
</node>
 | 
			
		||||
@ -14,6 +14,7 @@ qt_add_dbus_adaptor(dde_am_dbus_SOURCE ${PROJECT_SOURCE_DIR}/api/dbus/org.deskto
 | 
			
		||||
qt_add_dbus_adaptor(dde_am_dbus_SOURCE ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.ObjectManager1.xml dbus/applicationmanager1service.h ApplicationManager1Service AMobjectmanager1adaptor AMObjectManagerAdaptor)
 | 
			
		||||
qt_add_dbus_adaptor(dde_am_dbus_SOURCE ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.ObjectManager1.xml dbus/applicationservice.h ApplicationService APPobjectmanager1adaptor APPObjectManagerAdaptor)
 | 
			
		||||
qt_add_dbus_adaptor(dde_am_dbus_SOURCE ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.MimeManager1.xml dbus/mimemanager1service.h MimeManager1Service)
 | 
			
		||||
qt_add_dbus_adaptor(dde_am_dbus_SOURCE ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.ProcessGuesser1.xml dbus/processguesser1service.h ProcessGuesser1Service)
 | 
			
		||||
 | 
			
		||||
target_sources(dde_am_dbus PRIVATE
 | 
			
		||||
    ${dde_am_dbus_SOURCE}
 | 
			
		||||
 | 
			
		||||
@ -9,8 +9,10 @@
 | 
			
		||||
#include "propertiesForwarder.h"
 | 
			
		||||
#include "applicationHooks.h"
 | 
			
		||||
#include "desktopfilegenerator.h"
 | 
			
		||||
#include "processguesser1service.h"
 | 
			
		||||
#include <QFile>
 | 
			
		||||
#include <QDBusMessage>
 | 
			
		||||
#include <QStringBuilder>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
ApplicationManager1Service::~ApplicationManager1Service() = default;
 | 
			
		||||
@ -28,6 +30,8 @@ void ApplicationManager1Service::initService(QDBusConnection &connection) noexce
 | 
			
		||||
        qFatal("%s", connection.lastError().message().toLocal8Bit().data());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    new (std::nothrow) ProcessGuesser1Service{connection, this};
 | 
			
		||||
 | 
			
		||||
    if (auto *tmp = new (std::nothrow) ApplicationManager1Adaptor{this}; tmp == nullptr) {
 | 
			
		||||
        qCritical() << "new Application Manager Adaptor failed.";
 | 
			
		||||
        std::terminate();
 | 
			
		||||
@ -397,37 +401,15 @@ QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidf
 | 
			
		||||
 | 
			
		||||
    Q_ASSERT_X(static_cast<bool>(m_identifier), "Identify", "Broken Identifier.");
 | 
			
		||||
 | 
			
		||||
    QString fdFilePath = QString{"/proc/self/fdinfo/%1"}.arg(pidfd.fileDescriptor());
 | 
			
		||||
    QFile fdFile{fdFilePath};
 | 
			
		||||
    if (!fdFile.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text)) {
 | 
			
		||||
        qWarning() << "open " << fdFilePath << "failed: " << fdFile.errorString();
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
    auto content = fdFile.readAll();
 | 
			
		||||
    QTextStream stream{content};
 | 
			
		||||
    QString appPid;
 | 
			
		||||
    while (!stream.atEnd()) {
 | 
			
		||||
        auto line = stream.readLine();
 | 
			
		||||
        if (line.startsWith("Pid")) {
 | 
			
		||||
            appPid = line.split(":").last().trimmed();
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (appPid.isEmpty()) {
 | 
			
		||||
        qWarning() << "can't find pid which corresponding with the instance of this application.";
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
    bool ok;
 | 
			
		||||
    auto pid = appPid.toUInt(&ok);
 | 
			
		||||
    if (!ok) {
 | 
			
		||||
        qWarning() << "AppId is failed to convert to uint.";
 | 
			
		||||
    auto pid = getPidFromPidFd(pidfd);
 | 
			
		||||
    if (pid == 0) {
 | 
			
		||||
        sendErrorReply(QDBusError::Failed, "pid is invalid");
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto ret = m_identifier->Identify(pid);
 | 
			
		||||
 | 
			
		||||
    if (ret.ApplicationId.isEmpty()) {
 | 
			
		||||
        qInfo() << "Identify failed.";
 | 
			
		||||
        sendErrorReply(QDBusError::Failed, "Identify failed.");
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -436,14 +418,14 @@ QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidf
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (app == m_applicationList.cend()) {
 | 
			
		||||
        qWarning() << "can't find application:" << ret.ApplicationId;
 | 
			
		||||
        sendErrorReply(QDBusError::Failed, "can't find application:" % ret.ApplicationId);
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto instancePath = (*app)->findInstance(ret.InstanceId);
 | 
			
		||||
 | 
			
		||||
    if (auto path = instancePath.path(); path.isEmpty()) {
 | 
			
		||||
        qWarning() << "can't find instance:" << path;
 | 
			
		||||
        sendErrorReply(QDBusError::Failed, "can't find instance:" % path);
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -457,7 +439,6 @@ QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidf
 | 
			
		||||
void ApplicationManager1Service::updateApplication(const QSharedPointer<ApplicationService> &destApp,
 | 
			
		||||
                                                   DesktopFile desktopFile) noexcept
 | 
			
		||||
{
 | 
			
		||||
    // TODO: add propertyChanged
 | 
			
		||||
    if (auto app = m_applicationList.find(destApp->applicationPath()); app == m_applicationList.cend()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -20,7 +20,7 @@
 | 
			
		||||
 | 
			
		||||
class ApplicationService;
 | 
			
		||||
 | 
			
		||||
class ApplicationManager1Service final : public QObject, public QDBusContext
 | 
			
		||||
class ApplicationManager1Service final : public QObject, protected QDBusContext
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
public:
 | 
			
		||||
@ -43,6 +43,7 @@ public:
 | 
			
		||||
    findApplicationsByIds(const QStringList &appIds) const noexcept;
 | 
			
		||||
    void updateApplication(const QSharedPointer<ApplicationService> &destApp, DesktopFile desktopFile) noexcept;
 | 
			
		||||
 | 
			
		||||
    [[nodiscard]] const auto &Applications() const noexcept { return m_applicationList; }
 | 
			
		||||
    [[nodiscard]] JobManager1Service &jobManager() noexcept { return *m_jobManager; }
 | 
			
		||||
    [[nodiscard]] const JobManager1Service &jobManager() const noexcept { return *m_jobManager; }
 | 
			
		||||
    [[nodiscard]] const QStringList &applicationHooks() const noexcept { return m_hookElements; }
 | 
			
		||||
 | 
			
		||||
@ -928,6 +928,12 @@ QVariant ApplicationService::findEntryValue(const QString &group,
 | 
			
		||||
    bool ok{false};
 | 
			
		||||
 | 
			
		||||
    switch (type) {
 | 
			
		||||
    case EntryValueType::Raw: {
 | 
			
		||||
        auto valStr = val.toString();
 | 
			
		||||
        if (!valStr.isEmpty()) {
 | 
			
		||||
            ret = QVariant::fromValue(valStr);
 | 
			
		||||
        }
 | 
			
		||||
    } break;
 | 
			
		||||
    case EntryValueType::String: {
 | 
			
		||||
        auto valStr = toString(val);
 | 
			
		||||
        if (!valStr.isEmpty()) {
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,7 @@
 | 
			
		||||
QString getDeepinWineScaleFactor(const QString &appId) noexcept;
 | 
			
		||||
double getScaleFactor() noexcept;
 | 
			
		||||
 | 
			
		||||
class ApplicationService : public QObject, public QDBusContext
 | 
			
		||||
class ApplicationService : public QObject, protected QDBusContext
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
public:
 | 
			
		||||
@ -118,6 +118,10 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
    void resetEntry(DesktopEntry *newEntry) noexcept;
 | 
			
		||||
    void detachAllInstance() noexcept;
 | 
			
		||||
    [[nodiscard]] QVariant findEntryValue(const QString &group,
 | 
			
		||||
                                          const QString &valueKey,
 | 
			
		||||
                                          EntryValueType type,
 | 
			
		||||
                                          const QLocale &locale = getUserLocale()) const noexcept;
 | 
			
		||||
 | 
			
		||||
    [[nodiscard]] LaunchTask unescapeExec(const QString &str, const QStringList &fields) noexcept;
 | 
			
		||||
    [[nodiscard]] static QStringList unescapeExecArgs(const QString &str) noexcept;
 | 
			
		||||
@ -168,10 +172,6 @@ private:
 | 
			
		||||
    DesktopFile m_desktopSource;
 | 
			
		||||
    QSharedPointer<DesktopEntry> m_entry{nullptr};
 | 
			
		||||
    QMap<QDBusObjectPath, QSharedPointer<InstanceService>> m_Instances;
 | 
			
		||||
    [[nodiscard]] QVariant findEntryValue(const QString &group,
 | 
			
		||||
                                          const QString &valueKey,
 | 
			
		||||
                                          EntryValueType type,
 | 
			
		||||
                                          const QLocale &locale = getUserLocale()) const noexcept;
 | 
			
		||||
    void updateAfterLaunch(bool isLaunch) noexcept;
 | 
			
		||||
    static bool shouldBeShown(const std::unique_ptr<DesktopEntry> &entry) noexcept;
 | 
			
		||||
    [[nodiscard]] bool autostartCheck(const QString &linkPath) const noexcept;
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,7 @@
 | 
			
		||||
 | 
			
		||||
class ApplicationManager1Service;
 | 
			
		||||
 | 
			
		||||
class MimeManager1Service : public QObject, public QDBusContext
 | 
			
		||||
class MimeManager1Service : public QObject, protected QDBusContext
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										111
									
								
								src/dbus/processguesser1service.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								src/dbus/processguesser1service.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,111 @@
 | 
			
		||||
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 | 
			
		||||
//
 | 
			
		||||
// SPDX-License-Identifier: LGPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#include "processguesser1adaptor.h"
 | 
			
		||||
#include "applicationservice.h"
 | 
			
		||||
#include "global.h"
 | 
			
		||||
 | 
			
		||||
ProcessGuesser1Service::ProcessGuesser1Service(QDBusConnection &connection, ApplicationManager1Service *parent) noexcept
 | 
			
		||||
    : QObject(parent)
 | 
			
		||||
{
 | 
			
		||||
    if (!connection.registerService("org.desktopspec.ProcessGuesser1")) {
 | 
			
		||||
        qFatal("%s", connection.lastError().message().toLocal8Bit().data());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (auto *tmp = new (std::nothrow) ProcessGuesser1Adaptor{this}; tmp == nullptr) {
 | 
			
		||||
        qFatal("new Process Guesser Adaptor failed.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!registerObjectToDBus(this, "/org/desktopspec/ProcessGuesser1", "org.desktopspec.ProcessGuesser1")) {
 | 
			
		||||
        std::terminate();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ProcessGuesser1Service::checkTryExec(QString tryExec) noexcept
 | 
			
		||||
{
 | 
			
		||||
    if (!tryExec.isEmpty()) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QFileInfo exeBin{tryExec};
 | 
			
		||||
    if (!exeBin.isAbsolute()) {
 | 
			
		||||
        tryExec = QStandardPaths::findExecutable(tryExec);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!tryExec.isEmpty()) {
 | 
			
		||||
        exeBin.setFile(tryExec);
 | 
			
		||||
        if (!exeBin.exists() or !exeBin.isFile() or !exeBin.isExecutable()) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString ProcessGuesser1Service::GuessApplicationId(const QDBusUnixFileDescriptor &pidfd) noexcept
 | 
			
		||||
{
 | 
			
		||||
    if (!pidfd.isValid()) {
 | 
			
		||||
        sendErrorReply(QDBusError::InvalidArgs);
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto pid = getPidFromPidFd(pidfd);
 | 
			
		||||
    if (pid == 0) {
 | 
			
		||||
        sendErrorReply(QDBusError::Failed, "Pid is invalid");
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QString exePath = QString{"/proc/%1/exe"}.arg(pid);
 | 
			
		||||
    QFileInfo info{exePath};
 | 
			
		||||
 | 
			
		||||
    if (!info.exists()) {
 | 
			
		||||
        sendErrorReply(QDBusError::Failed, "Pid is invalid.");
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
    const auto &binary = info.symLinkTarget();
 | 
			
		||||
 | 
			
		||||
    const auto &applications = myParent()->Applications();
 | 
			
		||||
    QString appId;
 | 
			
		||||
 | 
			
		||||
    for (const QSharedPointer<ApplicationService> &app : applications) {
 | 
			
		||||
        auto exec = app->findEntryValue(DesktopFileEntryKey, "Exec", EntryValueType::Raw).toString();
 | 
			
		||||
        if (exec.isEmpty()) {  // NOTE: Exec is not required in desktop file.
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        auto execList = ApplicationService::unescapeExecArgs(exec);
 | 
			
		||||
        if (execList.isEmpty()) {
 | 
			
		||||
            sendErrorReply(QDBusError::InternalError);
 | 
			
		||||
            return {};
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        auto execBin = execList.first();
 | 
			
		||||
        QFileInfo execInfo{execBin};
 | 
			
		||||
        if (!execInfo.isAbsolute()) {
 | 
			
		||||
            execBin = QStandardPaths::findExecutable(execBin);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!execBin.isEmpty() and execBin == binary) {
 | 
			
		||||
            if (!appId.isEmpty()) {
 | 
			
		||||
                sendErrorReply(QDBusError::Failed, "Multiple binary have been detected.");
 | 
			
		||||
                return {};
 | 
			
		||||
            }
 | 
			
		||||
            appId = app->id();
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        auto tryExec = app->findEntryValue(DesktopFileEntryKey, "TryExec", EntryValueType::String).toString();
 | 
			
		||||
        if (!checkTryExec(tryExec)) {
 | 
			
		||||
            sendErrorReply(QDBusError::Failed, "Couldn't find the binary which corresponding with process.");
 | 
			
		||||
            return {};
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (appId.isEmpty()) {
 | 
			
		||||
        sendErrorReply(QDBusError::Failed, "Couldn't found application.");
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return appId;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								src/dbus/processguesser1service.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/dbus/processguesser1service.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 | 
			
		||||
//
 | 
			
		||||
// SPDX-License-Identifier: LGPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#ifndef PROCESSGUESSER1SERVICE_H
 | 
			
		||||
#define PROCESSGUESSER1SERVICE_H
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QDBusContext>
 | 
			
		||||
#include <QDBusUnixFileDescriptor>
 | 
			
		||||
#include "applicationmanager1service.h"
 | 
			
		||||
 | 
			
		||||
class ProcessGuesser1Service : public QObject, protected QDBusContext
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
public:
 | 
			
		||||
    ProcessGuesser1Service(QDBusConnection &connection, ApplicationManager1Service *parent) noexcept;
 | 
			
		||||
    ~ProcessGuesser1Service() override = default;
 | 
			
		||||
    ProcessGuesser1Service(const ProcessGuesser1Service &) = delete;
 | 
			
		||||
    ProcessGuesser1Service(ProcessGuesser1Service &&) = delete;
 | 
			
		||||
    ProcessGuesser1Service &operator=(const ProcessGuesser1Service &) = delete;
 | 
			
		||||
    ProcessGuesser1Service &operator=(ProcessGuesser1Service &&) = delete;
 | 
			
		||||
    ApplicationManager1Service *myParent() { return dynamic_cast<ApplicationManager1Service *>(QObject::parent()); }
 | 
			
		||||
    [[nodiscard]] const ApplicationManager1Service *myParent() const
 | 
			
		||||
    {
 | 
			
		||||
        return dynamic_cast<ApplicationManager1Service *>(QObject::parent());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
public Q_SLOTS:
 | 
			
		||||
    QString GuessApplicationId(const QDBusUnixFileDescriptor &pidfd) noexcept;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    [[nodiscard]] static bool checkTryExec(QString tryExec) noexcept;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -17,7 +17,7 @@
 | 
			
		||||
 | 
			
		||||
enum class EntryContext { Unknown, EntryOuter, Entry, Done };
 | 
			
		||||
 | 
			
		||||
enum class EntryValueType { String, LocaleString, Boolean, IconString };
 | 
			
		||||
enum class EntryValueType { String, LocaleString, Boolean, IconString, Raw };
 | 
			
		||||
 | 
			
		||||
struct DesktopFileGuard;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										35
									
								
								src/global.h
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								src/global.h
									
									
									
									
									
								
							@ -16,6 +16,7 @@
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QRegularExpression>
 | 
			
		||||
#include <QDBusObjectPath>
 | 
			
		||||
#include <QDBusUnixFileDescriptor>
 | 
			
		||||
#include <QDBusArgument>
 | 
			
		||||
#include <QDBusMessage>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
@ -576,4 +577,38 @@ inline QByteArray getCurrentSessionId()
 | 
			
		||||
    return id.value<QDBusVariant>().variant().toByteArray();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline uint getPidFromPidFd(const QDBusUnixFileDescriptor &pidfd) noexcept
 | 
			
		||||
{
 | 
			
		||||
    QString fdFilePath = QString{"/proc/self/fdinfo/%1"}.arg(pidfd.fileDescriptor());
 | 
			
		||||
    QFile fdFile{fdFilePath};
 | 
			
		||||
    if (!fdFile.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text)) {
 | 
			
		||||
        qWarning() << "open " << fdFilePath << "failed: " << fdFile.errorString();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto content = fdFile.readAll();
 | 
			
		||||
    QTextStream stream{content};
 | 
			
		||||
    QString appPid;
 | 
			
		||||
    while (!stream.atEnd()) {
 | 
			
		||||
        auto line = stream.readLine();
 | 
			
		||||
        if (line.startsWith("Pid")) {
 | 
			
		||||
            appPid = line.split(":").last().trimmed();
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (appPid.isEmpty()) {
 | 
			
		||||
        qWarning() << "can't find pid which corresponding with the instance of this application.";
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    bool ok{false};
 | 
			
		||||
    auto pid = appPid.toUInt(&ok);
 | 
			
		||||
    if (!ok) {
 | 
			
		||||
        qWarning() << "AppId is failed to convert to uint.";
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return pid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user