feat: AM 默认程序迁移

默认程序迁移到AM中

Log: 默认程序迁移到AM
Task: https://pms.uniontech.com/task-view-140029.html
Influence: 默认程序
Change-Id: I0824c503b6ab844f09b3bf3cf740565b1e4215e5
This commit is contained in:
echengqi 2022-06-15 14:14:43 +08:00
parent 2b00b9b291
commit dfa232bb98
31 changed files with 1907 additions and 66 deletions

View File

@ -0,0 +1,30 @@
<interface name='org.deepin.daemon.Mime'>
<method name='AddUserApp'>
<arg type='as' name='mimeTypes' direction='in'/>
<arg type='s' name='desktopId' direction='in'/>
</method>
<method name='DeleteApp'>
<arg type='as' name='mimeTypes' direction='in'/>
<arg type='s' name='desktopId' direction='in'/>
</method>
<method name='DeleteUserApp'>
<arg type='s' name='desktopId' direction='in'/>
</method>
<method name='GetDefaultApp'>
<arg type='s' name='mimeType' direction='in'/>
<arg type='s' name='defaultApp' direction='out'/>
</method>
<method name='ListApps'>
<arg type='s' name='mimeType' direction='in'/>
<arg type='s' name='apps' direction='out'/>
</method>
<method name='ListUserApps'>
<arg type='s' name='mimeType' direction='in'/>
<arg type='s' name='userApps' direction='out'/>
</method>
<method name='SetDefaultApp'>
<arg type='as' name='mimeTypes' direction='in'/>
<arg type='s' name='desktopId' direction='in'/>
</method>
<signal name="Change"></signal>
</interface>

View File

@ -37,6 +37,10 @@
<method name='TryAgain'>
<arg type='b' name='launch' direction='in' />
</method>
<method name='IsPidVirtualMachine'>
<arg type='i' name='pid' direction='in' />
<arg type='b' name='isVM' direction='out' />
</method>
<signal name='AutostartChanged'>
<arg type='s' name='status' />
<arg type='s' name='filePath' />

1
debian/control vendored
View File

@ -17,6 +17,7 @@ Build-Depends:
libxcb-ewmh-dev,
libx11-dev,
libglib2.0-dev,
libgsettings-qt-dev,
Standards-Version: 4.1.3
Homepage: https://www.deepin.org

410
src/lib/appinfo.cpp Normal file
View File

@ -0,0 +1,410 @@
#include "appinfo.h"
#include "utils.h"
#include "dlocale.h"
#include "appinfocommon.h"
#include <string>
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#include <string.h>
#include <QDir>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
bool AppInfoManger::onceInit = false;
std::vector<std::string> AppInfoManger::xdgDataDirs;
std::vector<std::string> AppInfoManger::xdgAppDirs;
AppInfoManger::AppInfoManger()
{
canDelete = false;
}
std::vector<std::string> AppInfoManger::getStringList(std::string session, std::string key)
{
return keyFile.getStrList(session, key);
}
std::string AppInfoManger::toJson()
{
QJsonDocument doc;
QJsonObject obj;
obj["Id"] = desktopId.c_str();
obj["Name"] = appName.c_str();
obj["DisplayName"] = displayName.c_str();
obj["Description"] = comment.c_str();
obj["Icon"] = icon.c_str();
obj["Exec"] = cmdline.c_str();
obj["CanDelete"] = canDelete;
if (!obj.isEmpty()) {
doc.setObject(obj);
}
return doc.toJson(QJsonDocument::Compact).toStdString();
}
std::string AppInfoManger::getFileName()
{
return fileName;
}
std::shared_ptr<AppInfoManger> AppInfoManger::loadByDesktopId(std::string desktopId)
{
std::shared_ptr<AppInfoManger> appInfo;
if (!hasEnding(desktopId, AppinfoCommon::DesktopExt)) {
desktopId += AppinfoCommon::DesktopExt;
}
if (QDir::isAbsolutePath(desktopId.c_str())) {
appInfo = AppInfoManger::initAppInfoByFile(desktopId);
if (appInfo) {
appInfo->desktopId = AppInfoManger::getDesktopIdFile(desktopId);
}
return appInfo;
}
std::vector<std::string> appDirs = AppInfoManger::getXdgAppsDirs();
for (auto iter : appDirs) {
appInfo = AppInfoManger::initAppInfoByFile(iter + "/" + desktopId);
if (appInfo) {
appInfo->desktopId = desktopId;
return appInfo;
}
}
return appInfo;
}
std::shared_ptr<AppInfoManger> AppInfoManger::initAppInfoByFile(std::string fileName)
{
std::shared_ptr<AppInfoManger> appInfo;
KeyFile keyFile;
bool bSuccess = keyFile.loadFile(fileName);
if (!bSuccess) {
return appInfo;
}
std::string type = keyFile.getStr(AppinfoCommon::MainSection, AppinfoCommon::KeyType);
if (type != AppinfoCommon::TypeApplication) {
return appInfo;
}
appInfo = std::make_shared<AppInfoManger>();
appInfo->appName = getAppName(keyFile);
appInfo->icon = AppInfoManger::getIconByKeyFile(keyFile);
appInfo->displayName = appInfo->appName;
appInfo->comment = keyFile.getLocaleStr(AppinfoCommon::MainSection, AppinfoCommon::KeyComment);
appInfo->cmdline = keyFile.getStr(AppinfoCommon::MainSection, AppinfoCommon::KeyExec);
appInfo->fileName = fileName;
appInfo->keyFile = keyFile;
if (!appInfo->shouldShow()) {
return nullptr;
}
return appInfo;
}
std::string AppInfoManger::getIconByKeyFile(KeyFile& keyFile)
{
std::string icon = keyFile.getStr(AppinfoCommon::MainSection, AppinfoCommon::KeyIcon);
if (!QDir::isAbsolutePath(icon.c_str())) {
if (hasEnding(icon, ".png")) {
icon = icon.substr(0, icon.length() - strlen(".png"));
}
if (hasEnding(icon, ".xpm")) {
icon = icon.substr(0, icon.length() - strlen(".xpm"));
}
if (hasEnding(icon, ".svg")) {
icon = icon.substr(0, icon.length() - strlen(".svg"));
}
}
return icon;
}
std::string AppInfoManger::getDesktopIdFile(std::string fileName)
{
if (hasEnding(fileName, AppinfoCommon::DesktopExt)) {
fileName = fileName.substr(0, fileName.size() - strlen(AppinfoCommon::DesktopExt.c_str()) + 1);
}
auto index = fileName.find("/applications/");
if (index == fileName.npos) {
return "";
}
std::string dir = fileName.substr(0, index);
std::vector<std::string> dataDIrs = AppInfoManger::getXdgDataDirs();
if (std::find(dataDIrs.begin(), dataDIrs.end(), dir) != dataDIrs.end()) {
return fileName.substr(index + 14, fileName.size() - (index + 14 + 1));
}
return fileName;
}
bool AppInfoManger::shouldShow()
{
if (!keyFile.getStr(AppinfoCommon::MainSection, AppinfoCommon::KeyNoDisplay).empty()) {
return false;
}
if (!keyFile.getStr(AppinfoCommon::MainSection, AppinfoCommon::KeyHidden).empty()) {
return false;
}
QString deskEnv = getenv("XDG_CURRENT_DESKTOP");
auto envList = deskEnv.split(":");
std::vector<std::string> onlyShowIn = keyFile.getStrList(AppinfoCommon::MainSection, AppinfoCommon::KeyOnlyShowIn);
std::vector<std::string> notShowIn = keyFile.getStrList(AppinfoCommon::MainSection, AppinfoCommon::KeyNotShowIn);
for (auto iter : envList) {
if (std::find(onlyShowIn.begin(), onlyShowIn.end(), iter.toStdString()) != onlyShowIn.end()) {
return true;
}
if (std::find(notShowIn.begin(), notShowIn.end(), iter.toStdString()) != notShowIn.end()) {
return false;
}
}
return onlyShowIn.empty();
}
std::string AppInfoManger::getDefaultApp(std::string mimeType, bool supportUri)
{
GAppInfo* gAppInfo = g_app_info_get_default_for_type(mimeType.c_str(), supportUri);
if (gAppInfo == nullptr) {
return "";
}
if (supportUri && !g_app_info_supports_uris(gAppInfo)) {
return "";
}
return g_app_info_get_id(gAppInfo);
}
std::vector<std::string> AppInfoManger::getAppList(std::string mimeType)
{
std::vector<std::string> retVector;
GList* appInfoList = g_app_info_get_all_for_type(mimeType.c_str());
while (appInfoList) {
GAppInfo* gAppInfo = static_cast<GAppInfo*>(appInfoList->data);
const char* appId = g_app_info_get_id(gAppInfo);
if (appId) {
retVector.push_back(appId);
}
appInfoList = appInfoList->next;
}
return retVector;
}
bool AppInfoManger::getDefaultApp(std::string mimeType, std::string desktopId)
{
GDesktopAppInfo* gDesktopAppInfo = g_desktop_app_info_new(desktopId.c_str());
if (gDesktopAppInfo == nullptr) {
return false;
}
GAppInfo* gAppInfo = G_APP_INFO(gDesktopAppInfo);
GError* err;
g_app_info_set_as_default_for_type(gAppInfo, mimeType.c_str(), &err);
if (err != nullptr) {
return false;
}
return true;
}
std::string AppInfoManger::getAppName(KeyFile& keyFile)
{
std::string name;
std::string xDeepinVendor = keyFile.getStr(AppinfoCommon::MainSection, AppinfoCommon::DeepinVendor);
if (xDeepinVendor == "deepin") {
name = keyFile.getLocaleStr(AppinfoCommon::MainSection, AppinfoCommon::KeyGenericName);
} else {
name = keyFile.getLocaleStr(AppinfoCommon::MainSection, AppinfoCommon::KeyName);
}
if (name.empty()) {
name = AppInfoManger::getDesktopIdFile(keyFile.getFilePath());
}
return name;
}
std::vector<std::string>& AppInfoManger::getXdgDataDirs()
{
if (!AppInfoManger::onceInit) {
AppInfoManger::onceInit = true;
AppInfoManger::xdgDataDirs.push_back(getUserDataDir());
for (auto iter : getSystemDataDirs()) {
xdgDataDirs.push_back(iter);
}
for (auto dataDir : AppInfoManger::xdgDataDirs) {
AppInfoManger::xdgAppDirs.push_back(dataDir + "/applications");
}
}
return AppInfoManger::xdgDataDirs;
}
std::vector<std::string>& AppInfoManger::getXdgAppsDirs()
{
if (!AppInfoManger::onceInit) {
AppInfoManger::onceInit = true;
AppInfoManger::xdgDataDirs.push_back(getUserDataDir());
for (auto iter : getSystemDataDirs()) {
xdgDataDirs.push_back(iter);
}
for (auto dataDir : AppInfoManger::xdgDataDirs) {
AppInfoManger::xdgAppDirs.push_back(dataDir + "/applications");
}
}
return AppInfoManger::xdgAppDirs;
}
std::vector<std::shared_ptr<AppInfoManger>> AppInfoManger::getAll(std::map<std::string, std::vector<std::string>> skipDirs)
{
std::vector<std::shared_ptr<AppInfoManger>> ret;
std::vector<std::string> xdgAppDirs = AppInfoManger::getXdgAppsDirs();
std::vector<std::pair<std::string, std::map<std::string, int>>> appPathNameInfos;
for (auto iter : xdgAppDirs) {
std::map<std::string, int> tempMap;
if (skipDirs.count(iter) != 0) {
walk(iter, skipDirs[iter], tempMap);
} else {
std::vector<std::string> temp;
walk(iter, temp, tempMap);
}
appPathNameInfos.push_back(std::make_pair(iter, tempMap));
}
std::map<std::string, int> recordMap;
for (auto appPathNameInfo : appPathNameInfos) {
for (auto appName : appPathNameInfo.second) {
std::string tempAppName = appName.first;
if (hasBeginWith(appName.first, "./")) {
tempAppName = appName.first.substr(appName.first.find_first_of("./") + 2, appName.first.size() - 2);
}
if (recordMap.count(tempAppName)) {
continue;
}
std::shared_ptr<AppInfoManger> appInfo = AppInfoManger::loadByDesktopId(appPathNameInfo.first + "/" + tempAppName);
if (!appInfo) {
continue;
}
recordMap[tempAppName] = 0;
if (appInfo->shouldShow()) {
ret.push_back(appInfo);
}
}
}
return ret;
}
std::string AppInfoManger::getDesktopId()
{
return desktopId;
}
std::string AppInfoManger::getAppName()
{
return appName;
}
std::string AppInfoManger::getDisplayName()
{
return displayName;
}
std::string AppInfoManger::getComment()
{
return comment;
}
std::string AppInfoManger::getIcon()
{
return icon;
}
std::string AppInfoManger::getCmdline()
{
return cmdline;
}
bool AppInfoManger::getCanDelete()
{
return canDelete;
}
void AppInfoManger::setCanDelete(bool bCanDelete)
{
canDelete = bCanDelete;
}
std::vector<std::string> AppInfoManger::getCategories()
{
return keyFile.getStrList(AppinfoCommon::MainSection, AppinfoCommon::KeyCategories);
}
void AppInfoManger::setDesktopId(std::string desktopId)
{
this->desktopId = desktopId;
}
std::string AppInfoManger::toJson(std::vector<std::shared_ptr<AppInfoManger>> appInfos)
{
QJsonDocument doc;
QJsonObject obj;
QJsonArray arr;
for (auto iter : appInfos) {
obj["Id"] = iter->getDesktopId().c_str();
obj["Name"] = iter->getAppName().c_str();
obj["DisplayName"] = iter->getDisplayName().c_str();
obj["Description"] = iter->getComment().c_str();
obj["Icon"] = iter->getIcon().c_str();
obj["Exec"] = iter->getCmdline().c_str();
obj["CanDelete"] = iter->getCanDelete();
arr.push_back(obj);
}
if (!arr.empty()) {
doc.setArray(arr);
}
return doc.toJson(QJsonDocument::Compact).toStdString();
}

56
src/lib/appinfo.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef APPINFO_H
#define APPINFO_H
#include "keyfile.h"
#include <vector>
#include <memory>
class AppInfoManger
{
public:
AppInfoManger();
std::vector<std::string> getStringList(std::string session, std::string key);
std::string toJson();
std::string getFileName();
static std::shared_ptr<AppInfoManger> loadByDesktopId(std::string desktopId);
static std::string getDefaultApp(std::string mimeType, bool supportUri);
static std::vector<std::string> getAppList(std::string mimeType);
static bool getDefaultApp(std::string mimeType, std::string desktopId);
static std::vector<std::string>& getXdgDataDirs();
static std::vector<std::string>& getXdgAppsDirs();
static std::vector<std::shared_ptr<AppInfoManger>> getAll(std::map<std::string, std::vector<std::string>> skipDirs);
std::string getDesktopId();
std::string getAppName();
std::string getDisplayName();
std::string getComment();
std::string getIcon();
std::string getCmdline();
bool getCanDelete();
void setCanDelete(bool bCanDelete);
std::vector<std::string> getCategories();
void setDesktopId(std::string desktopId);
static std::string toJson(std::vector<std::shared_ptr<AppInfoManger>> appInfos);
private:
static std::shared_ptr<AppInfoManger> initAppInfoByFile(std::string fileName);
static std::string getAppName(KeyFile& keyFile);
static std::string getIconByKeyFile(KeyFile& keyFile);
static std::string getDesktopIdFile(std::string fileName);
bool shouldShow();
private:
std::string desktopId;
std::string appName;
std::string displayName;
std::string comment;
std::string icon;
std::string cmdline;
bool canDelete;
std::string fileName;
KeyFile keyFile;
static std::vector<std::string> xdgDataDirs;
static std::vector<std::string> xdgAppDirs;
static bool onceInit;
};
#endif // APPINFO_H

40
src/lib/appinfocommon.cpp Normal file
View File

@ -0,0 +1,40 @@
#include "appinfocommon.h"
const std::string AppinfoCommon::MainSection = "Desktop Entry";
const std::string AppinfoCommon::KeyType = "Type";
const std::string AppinfoCommon::KeyVersion = "Version";
const std::string AppinfoCommon::KeyName = "Name";
const std::string AppinfoCommon::KeyGenericName = "GenericName";
const std::string AppinfoCommon::KeyNoDisplay = "NoDisplay";
const std::string AppinfoCommon::KeyComment = "Comment";
const std::string AppinfoCommon::KeyIcon = "Icon";
const std::string AppinfoCommon::KeyHidden = "Hidden";
const std::string AppinfoCommon::KeyOnlyShowIn = "OnlyShowIn";
const std::string AppinfoCommon::KeyNotShowIn = "NotShowIn";
const std::string AppinfoCommon::KeyTryExec = "TryExec";
const std::string AppinfoCommon::KeyExec = "Exec";
const std::string AppinfoCommon::KeyPath = "Path";
const std::string AppinfoCommon::KeyTerminal = "Terminal";
const std::string AppinfoCommon::KeyMimeType = "MimeType";
const std::string AppinfoCommon::KeyCategories = "Categories";
const std::string AppinfoCommon::KeyKeywords = "Keywords";
const std::string AppinfoCommon::KeyStartupNotify = "StartupNotify";
const std::string AppinfoCommon::KeyStartupWMClass = "StartupWMClass";
const std::string AppinfoCommon::KeyURL = "URL";
const std::string AppinfoCommon::KeyActions = "Actions";
const std::string AppinfoCommon::KeyDBusActivatable = "DBusActivatable";
const std::string AppinfoCommon::TypeApplication = "Application";
const std::string AppinfoCommon::TypeLink = "Link";
const std::string AppinfoCommon::TypeDirectory = "Directory";
const std::string AppinfoCommon::EnvDesktopEnv = "XDG_CURRENT_DESKTOP";
const std::string AppinfoCommon::DesktopExt = ".desktop";
const std::string AppinfoCommon::GsSchemaStartdde = "com.deepin.dde.startdde";
const std::string AppinfoCommon::EnableInvoker = "ENABLE_TURBO_INVOKER";
const std::string AppinfoCommon::TurboInvokerFailedMsg = "Failed to invoke: Booster:";
const std::string AppinfoCommon::TurboInvokerErrMsg = "deepin-turbo-invoker: error";
const std::string AppinfoCommon::SectionDefaultApps = "Default Applications";
const std::string AppinfoCommon::SectionAddedAssociations = "Added Associations";
const std::string AppinfoCommon::DeepinVendor = "X-Deepin-Vendor";
const std::string AppinfoCommon::AppMimeTerminal = "application/x-terminal";

48
src/lib/appinfocommon.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef APPINFOCOMMON_H
#define APPINFOCOMMON_H
#include <string>
class AppinfoCommon
{
public:
const static std::string MainSection;
const static std::string KeyType;
const static std::string KeyVersion;
const static std::string KeyName;
const static std::string KeyGenericName;
const static std::string KeyNoDisplay;
const static std::string KeyComment;
const static std::string KeyIcon;
const static std::string KeyHidden;
const static std::string KeyOnlyShowIn;
const static std::string KeyNotShowIn;
const static std::string KeyTryExec;
const static std::string KeyExec;
const static std::string KeyPath;
const static std::string KeyTerminal;
const static std::string KeyMimeType;
const static std::string KeyCategories;
const static std::string KeyKeywords;
const static std::string KeyStartupNotify;
const static std::string KeyStartupWMClass;
const static std::string KeyURL;
const static std::string KeyActions;
const static std::string KeyDBusActivatable;
const static std::string TypeApplication;
const static std::string TypeLink;
const static std::string TypeDirectory;
const static std::string EnvDesktopEnv;
const static std::string DesktopExt;
const static std::string GsSchemaStartdde;
const static std::string EnableInvoker;
const static std::string TurboInvokerFailedMsg;
const static std::string TurboInvokerErrMsg;
const static std::string SectionDefaultApps;
const static std::string SectionAddedAssociations;
const static std::string DeepinVendor ;
const static std::string AppMimeTerminal;
};
#endif // APPINFOCOMMON_H

View File

@ -44,8 +44,8 @@ public:
static std::string userAutoStartDir();
private:
static void filterNotAbs(std::vector<std::string> &dirs);
static void addSuffixSlash(std::vector<std::string> &dirs);
static void filterNotAbs(std::vector<std::string>& dirs);
static void addSuffixSlash(std::vector<std::string>& dirs);
};
#endif // BASEDIR_H

View File

@ -54,6 +54,10 @@ public:
bool saveToFile(const std::string &filePath);
bool loadFile(const std::string &filePath);
std::vector<std::string> getMainKeys();
std::string getFilePath()
{
return m_filePath;
}
// for test
void print();

160
src/lib/terminalinfo.cpp Normal file
View File

@ -0,0 +1,160 @@
#include "terminalinfo.h"
#include "utils.h"
#include "appinfocommon.h"
#include <QVariant>
TerminalInfo& TerminalInfo::getInstanceTerminal()
{
static TerminalInfo terminal;
return terminal;
}
TerminalInfo::TerminalInfo()
: gsSchemaDefaultTerminal("com.deepin.desktop.default-applications.terminal")
, gsKeyExec("exec")
, gsKeyExecArg("exec-arg")
, gsKeyAppId("app-id")
, categoryTerminalEmulator("TerminalEmulator")
, execXTerminalEmulator("x-terminal-emulator")
, defaultTerminal(new QGSettings(gsSchemaDefaultTerminal.c_str()))
{
init();
}
void TerminalInfo::resetTerminal()
{
defaultTerminal->reset(gsKeyExec.c_str());
defaultTerminal->reset(gsKeyExecArg.c_str());
defaultTerminal->reset(gsKeyExecArg.c_str());
}
std::string TerminalInfo::getPresetTerminalPath()
{
std::string path;
for (auto term : terms) {
path = lookPath(term);
if (!path.empty()) {
return path;
}
}
return "";
}
void TerminalInfo::init()
{
termBlackList = {"guake",
"tilda",
"org.kde.yakuake",
"qterminal_drop",
"Terminal"
};
execArgMap = {{"gnome-terminal", "-x"},
{"mate-terminal", "-x"},
{"terminator", "-x"},
{"xfce4-terminal", "-x"}
};
terms = {"deepin-terminal",
"gnome-terminal",
"terminator",
"xfce4-terminal",
"rxvt",
"xterm"
};
}
std::shared_ptr<AppInfoManger> TerminalInfo::getDefaultTerminal()
{
std::string appId = defaultTerminal->get(gsKeyAppId.c_str()).toString().toStdString();
if (!hasEnding(appId, AppinfoCommon::DesktopExt)) {
appId += AppinfoCommon::DesktopExt;
}
std::vector<std::shared_ptr<AppInfoManger>> appInfos = getTerminalInfos();
for (auto iter : appInfos) {
if (iter->getDesktopId() == appId) {
return iter;
}
}
for (auto appInfo : appInfos) {
for (auto term : terms) {
if (appInfo->getCmdline() == term) {
return appInfo;
}
}
}
return nullptr;
}
bool TerminalInfo::setDefaultTerminal(std::string id)
{
std::vector<std::shared_ptr<AppInfoManger>> appInfos = getTerminalInfos();
for (auto iter : appInfos) {
if (iter->getDesktopId() == id) {
std::string cmdline = iter->getCmdline();
std::string exec = cmdline.substr(0, cmdline.find(" "));
defaultTerminal->set(gsKeyExec.c_str(), exec.c_str());
std::string arg = "-e";
if (execArgMap.count(exec) != 0) {
arg = execArgMap[exec];
}
defaultTerminal->set(gsKeyExecArg.c_str(), arg.c_str());
if (hasEnding(id, AppinfoCommon::DesktopExt)) {
id = id.substr(0, id.find(AppinfoCommon::DesktopExt));
}
defaultTerminal->set(gsKeyAppId.c_str(), id.c_str());
return true;
}
}
return false;
}
std::vector<std::shared_ptr<AppInfoManger>> TerminalInfo::getTerminalInfos()
{
std::map<std::string, std::vector<std::string>> skipDirs;
std::vector<std::shared_ptr<AppInfoManger>> appInfos = AppInfoManger::getAll(skipDirs);
std::vector<std::shared_ptr<AppInfoManger>>::iterator iter = appInfos.begin();
while (iter != appInfos.end()) {
if (isTerminalApp(*iter)) {
(*iter)->setDesktopId((*iter)->getDesktopId() + AppinfoCommon::DesktopExt);
iter++;
} else {
iter = appInfos.erase(iter);
}
}
return appInfos;
}
bool TerminalInfo::isTerminalApp(std::shared_ptr<AppInfoManger> appInfo)
{
if (std::find(termBlackList.begin(), termBlackList.end(), appInfo->getDesktopId()) != termBlackList.end()) {
return false;
}
std::vector<std::string> categories = appInfo->getCategories();
if (std::find(categories.begin(), categories.end(), categoryTerminalEmulator) == categories.end()) {
return false;
}
std::string cmdline = appInfo->getCmdline();
if (cmdline.find(execXTerminalEmulator) != std::string::npos) {
return false;
}
return true;
}

43
src/lib/terminalinfo.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef TERMINALINFO_H
#define TERMINALINFO_H
#include "appinfo.h"
#include <memory>
#include <vector>
#include <map>
#include <QGSettings>
class TerminalInfo
{
public:
static TerminalInfo& getInstanceTerminal();
void resetTerminal();
std::string getPresetTerminalPath();
bool setDefaultTerminal(std::string id);
std::shared_ptr<AppInfoManger> getDefaultTerminal();
std::vector<std::shared_ptr<AppInfoManger>> getTerminalInfos();
TerminalInfo(const TerminalInfo& term) = delete;
TerminalInfo& operator=(const TerminalInfo& term) = delete;
private:
TerminalInfo();
void init();
bool isTerminalApp(std::shared_ptr<AppInfoManger> appInfo);
private:
std::vector<std::string> termBlackList;
std::map<std::string, std::string> execArgMap;
std::vector<std::string> terms;
const std::string gsSchemaDefaultTerminal;
const std::string gsKeyExec;
const std::string gsKeyExecArg;
const std::string gsKeyAppId;
const std::string categoryTerminalEmulator;
const std::string execXTerminalEmulator;
std::shared_ptr<QGSettings> defaultTerminal;
};
#endif // TERMINALINFO_H

198
src/lib/utils.cpp Normal file
View File

@ -0,0 +1,198 @@
#include "utils.h"
#define HOME "HOME"
#include <unistd.h>
#include <fcntl.h>
std::string getUserDir(const char* envName);
std::vector<std::string> getSystemDirs(const char* envName);
std::string getUserHomeDir()
{
const char* dir = getenv(HOME);
if (dir) {
return dir;
}
struct passwd* user = getpwent();
if (user) {
return user->pw_dir;
}
return "";
}
std::string getUserDataDir()
{
// default $HOME/.local/share
std::string userDataDir = getUserDir("XDG_DATA_HOME");
if (userDataDir.empty()) {
userDataDir = getUserHomeDir();
if (!userDataDir.empty()) {
userDataDir += "/.local/share";
}
}
return userDataDir;
}
std::string getUserConfigDir()
{
// default $HOME/.config
std::string userConfigDir = getUserDir("XDG_CONFIG_HOME");
if (userConfigDir.empty()) {
userConfigDir = getUserHomeDir();
if (!userConfigDir.empty()) {
userConfigDir += "/.config";
}
}
return userConfigDir;
}
std::string getUserDir(const char* envName)
{
const char* envDir = getenv(envName);
if (!envDir) {
return "";
}
if (!QDir::isAbsolutePath(envDir)) {
return "";
}
return envDir;
}
std::vector<std::string> getSystemDataDirs()
{
std::vector<std::string> systemDir = getSystemDirs("XDG_DATA_DIRS");
if (systemDir.empty()) {
systemDir.push_back({"/usr/local/share", "/usr/share"});
}
return systemDir;
}
std::vector<std::string> getSystemConfigDirs()
{
std::vector<std::string> systemDir = getSystemDirs("XDG_CONFIG_DIRS");
if (systemDir.empty()) {
systemDir.push_back("/etc/xdg");
}
return systemDir;
}
std::vector<std::string> getSystemDirs(const char* envName)
{
std::vector<std::string> dirVector;
const char* envDir = getenv(envName);
if (envDir == nullptr) {
return dirVector;
}
QString tempDirs(envDir);
auto tempList = tempDirs.split(":");
for (auto iter : tempList) {
if (QDir::isAbsolutePath(iter)) {
dirVector.push_back(iter.toStdString());
}
}
return dirVector;
}
std::string lookPath(std::string file)
{
std::string path;
if (file.find("/") != std::string::npos) {
if (access(path.c_str(), X_OK) != -1) {
return file;
} else {
return path;
}
}
char* pathEnv = getenv("PATH");
char* temp = strtok(pathEnv, ";");
while (temp) {
path = std::string(temp) + "/" + file;
if (access(path.c_str(), X_OK) != -1) {
return path;
} else {
path = "";
temp = strtok(nullptr, "/");
}
}
return path;
}
void walk(std::string root, std::vector<std::string>& skipdir, std::map<std::string, int>& retMap)
{
walk(root, ".", skipdir, retMap);
}
void walk(std::string root, std::string name, std::vector<std::string>& skipdir, std::map<std::string, int>& retMap)
{
QDir dir(root.c_str());
if (dir.exists()) {
if (std::find(skipdir.begin(), skipdir.end(), name) != skipdir.end()) {
return;
}
} else {
return;
}
if (hasEnding(name, ".desktop")) {
retMap[name] = 0;
}
std::string path = root + "/" + name;
QDir temp(path.c_str());
QStringList entryList = temp.entryList();
for (auto iter : entryList) {
QFile file(iter);
if (file.exists()) {
continue;
}
walk(root, name + "/" + iter.toStdString(), skipdir, retMap);
}
}
bool hasEnding(std::string const& fullString, std::string const& ending)
{
if (fullString.length() >= ending.length()) {
return fullString.compare(fullString.length() - ending.length(), ending.length(), ending) == 0;
} else {
return false;
}
}
bool hasBeginWith(std::string const& fullString, std::string const& ending)
{
if (fullString.length() >= ending.length()) {
return (0 == fullString.compare(0, ending.length(), ending));
} else {
return false;
}
}

32
src/lib/utils.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef UTILS_H
#define UTILS_H
#include <string>
#include <pwd.h>
#include <QDir>
#include <vector>
std::string getUserHomeDir();
std::string getUserDataDir();
std::string getUserConfigDir();
std::string getUserDir(const char* envName);
std::vector<std::string> getSystemDataDirs();
std::vector<std::string> getSystemConfigDirs();
std::vector<std::string> getSystemDirs(const char* envName);
std::string lookPath(std::string file);
void walk(std::string root, std::vector<std::string>& skipdir, std::map<std::string, int>& retMap);
void walk(std::string root, std::string name, std::vector<std::string>& skipdir, std::map<std::string, int>& retMap);
bool hasEnding(std::string const& fullString, std::string const& ending);
bool hasBeginWith(std::string const& fullString, std::string const& ending);
#endif // UTILS_H

View File

@ -8,8 +8,9 @@ set(SRCS
../modules/methods/task.hpp
../modules/methods/basic.h
../modules/methods/instance.hpp
../modules/methods/quit.hpp
../modules/methods/process_status.hpp
../modules/methods/registe.hpp
../modules/methods/use_mime_app_info.h
../modules/util/common.cpp
../modules/util/common.h
../modules/util/filesystem.cpp

View File

@ -24,7 +24,7 @@
#include "../modules/methods/basic.h"
#include "../modules/methods/instance.hpp"
#include "../modules/methods/quit.hpp"
#include "../modules/methods/process_status.hpp"
#include "../modules/methods/registe.hpp"
#include "../modules/methods/task.hpp"
#include "../modules/socket/client.h"
@ -311,7 +311,19 @@ int main(int argc, char* argv[])
} else {
qWarning() << "error app prefix:" << QString::fromStdString(app.prefix);
}
if(pid != -1)
{
Methods::ProcessStatus processSuccess;
processSuccess.code = 0;
processSuccess.id = task.id;
processSuccess.type = "success";
processSuccess.data = QString::number(pid);
QByteArray processArray;
Methods::toJson(processArray, processSuccess);
client.send(processArray);
}
// TODO: 启动线程,创建新的连接去接受服务器的消息
// TODO:信号处理有问题
@ -329,9 +341,10 @@ int main(int argc, char* argv[])
waitpid(pid, &exitCode, 0);
qInfo() << "app exitCode:" << exitCode;
Methods::Quit quit;
Methods::ProcessStatus quit;
quit.code = exitCode;
quit.id = task.id;
quit.type = "quit";
QByteArray quitArray;
Methods::toJson(quitArray, quit);
client.send(quitArray);

View File

@ -0,0 +1,48 @@
#ifndef PROCESS_STATUS_H_
#define PROCESS_STATUS_H_
#include <QDebug>
#include <QJsonObject>
#include <QJsonDocument>
namespace Methods {
struct ProcessStatus {
QString data;
QString type;
QString id;
int code;
};
inline void toJson(QByteArray& array, const ProcessStatus& processStatus)
{
QJsonObject obj {
{ "type", processStatus.type },
{ "data", processStatus.data },
{ "id", processStatus.id },
{ "code", processStatus.code }
};
array = QJsonDocument(obj).toJson();
}
inline void fromJson(const QByteArray& array, ProcessStatus& quit)
{
QJsonDocument doc = QJsonDocument::fromJson(array);
if (!doc.isObject()) {
qWarning() << "fromJson quit failed";
return;
}
QJsonObject obj = doc.object();
if (!obj.contains("id") || !obj.contains("data") || !obj.contains("code")) {
qWarning() << "id data code not exist in quit array";
return;
}
quit.id = obj.value("id").toString();
quit.data = obj.value("data").toString();
quit.code = obj.value("code").toInt();
quit.type = obj.value("type").toString();
}
} // namespace Methods
#endif // PROCESS_STATUS_H_

View File

@ -0,0 +1,70 @@
#ifndef USE_DEFAULT_APP_INFO_H
#define USE_DEFAULT_APP_INFO_H
#include <QVector>
#include <QJsonObject>
#include <QJsonArray>
#include <vector>
namespace Methods {
struct DefaultUserAppInfo {
QVariantList appId;
std::string appType;
QVariantList supportedType;
};
struct DefaultUserAppInfos {
std::vector<DefaultUserAppInfo> appInfos;
};
inline void toJson(QJsonObject& j, const DefaultUserAppInfo& userAppInfo)
{
j = QJsonObject{ { "appId", QJsonArray::fromVariantList(userAppInfo.appId) }, { "appType", userAppInfo.appType.c_str() }, { "supportedType", QJsonArray::fromVariantList(userAppInfo.supportedType) }};
}
inline void fromJson(const QJsonObject& j, DefaultUserAppInfo& userAppInfo)
{
if (j.contains("appId")) {
userAppInfo.appId = j.value("appId").toArray().toVariantList();
}
if (j.contains("appType")) {
userAppInfo.appType = j.value("appType").toString().toStdString();
}
if (j.contains("supportedType")) {
userAppInfo.supportedType = j.value("supportedType").toArray().toVariantList();
}
}
inline void toJson(QJsonObject& j, const DefaultUserAppInfos& userAppInfos)
{
QJsonObject tmpObj;
QJsonArray appInfoArray;
for (auto appInfo : userAppInfos.appInfos) {
toJson(tmpObj, appInfo);
appInfoArray.append(tmpObj);
}
j = QJsonObject {
{"appInfos", appInfoArray}
};
}
inline void fromJson(const QJsonObject& j, DefaultUserAppInfos& userAppInfos)
{
QJsonObject tmpObj = j;
if (j.contains("appInfos")) {
DefaultUserAppInfo userAppInfo;
for (auto appInfo : tmpObj.take("appInfos").toArray()) {
fromJson(appInfo.toObject(), userAppInfo);
userAppInfos.appInfos.push_back(userAppInfo);
}
}
}
} // namespace Methods
#endif // USE_DEFAULT_APP_INFO_H

View File

@ -0,0 +1,59 @@
#ifndef USE_MIME_APP_INFO_H
#define USE_MIME_APP_INFO_H
#include <QVector>
#include <QJsonObject>
#include <QJsonArray>
#include <vector>
namespace Methods {
struct UserAppInfo {
std::string deskopid;
QVariantList supportedMime;
};
struct UserAppInfos {
std::vector<UserAppInfo> appInfos;
};
inline void toJson(QJsonObject& j, const UserAppInfo& userAppInfo)
{
j = QJsonObject{ { "DesktopId", userAppInfo.deskopid.c_str() }, { "SupportedMime", QJsonArray::fromVariantList(userAppInfo.supportedMime) } };
}
inline void fromJson(const QJsonObject& j, UserAppInfo& userAppInfo)
{
if (j.contains("DesktopId")) {
userAppInfo.deskopid = j.value("DesktopId").toString().toStdString();
}
if (j.contains("SupportedMime")) {
userAppInfo.supportedMime = j.value("SupportedMime").toArray().toVariantList();
}
}
inline void toJson(QJsonArray& j, const UserAppInfos& userAppInfos)
{
QJsonObject tmpObj;
QJsonArray appInfoArray;
for (auto appInfo : userAppInfos.appInfos) {
toJson(tmpObj, appInfo);
appInfoArray.append(tmpObj);
}
j = appInfoArray;
}
inline void fromJson(const QJsonArray& j, UserAppInfos& userAppInfos)
{
QJsonArray tmpObj = j;
for (auto iter : tmpObj) {
UserAppInfo userAppInfo;
fromJson(iter.toObject(), userAppInfo);
userAppInfos.appInfos.push_back(userAppInfo);
}
}
} // namespace Methods
#endif // USE_MIME_APP_INFO_H

View File

@ -0,0 +1,426 @@
#include "mime_app.h"
#include "utils.h"
#include "../methods/use_mime_app_info.h"
#include "../methods/use_default_app_info.h"
#include "appinfo.h"
#include "terminalinfo.h"
#include "appinfocommon.h"
#include <qmutex.h>
#include <QSettings>
#include <QVector>
#include <QFileInfo>
#include <fstream>
#include <iostream>
#include <QJsonParseError>
#include <QDebug>
class MimeAppPrivate : public QObject
{
MimeApp *q_ptr = nullptr;
Q_DECLARE_PUBLIC(MimeApp)
private:
Methods::UserAppInfos userAppInfos;
std::string filename;
QMutex mutex;
public:
MimeAppPrivate(MimeApp *parent) : QObject(parent), q_ptr(parent)
{
std::string homeDir = getUserHomeDir();
if (!homeDir.empty()) {
homeDir += "/.config/deepin/dde-daemon/user_mime.json";
filename = homeDir;
}
}
void Init()
{
QFile file(filename.c_str());
if (!file.exists()) {
return;
}
if (!file.open(QIODevice::ReadOnly)) {
return;
}
QJsonParseError *error = new QJsonParseError;
QJsonDocument jdc = QJsonDocument::fromJson(file.readAll(), error);
Methods::fromJson(jdc.array(), userAppInfos);
file.close();
}
void Write()
{
QFile file(filename.c_str());
if (!file.exists()) {
return;
}
if (!file.open(QIODevice::WriteOnly)) {
return;
}
QJsonArray jsonArr;
Methods::toJson(jsonArr, userAppInfos);
QJsonDocument jdc;
jdc.setArray(jsonArr);
file.write(jdc.toJson(QJsonDocument::Compact)); //Indented:表示自动添加/n回车符
file.close();
}
bool Add(const std::string &desktopId, QStringList mimeTypes)
{
bool bAdd = false;
std::vector<Methods::UserAppInfo>::iterator iter = userAppInfos.appInfos.begin();
while (iter != userAppInfos.appInfos.end()) {
if (iter->deskopid == desktopId) {
for (auto mimeType : mimeTypes) {
if (std::find(iter->supportedMime.begin(), iter->supportedMime.end(), mimeType) != iter->supportedMime.end()) {
bAdd = true;
iter->supportedMime.push_back(mimeType);
}
}
return bAdd;
}
iter++;
}
bAdd = true;
Methods::UserAppInfo appInfo;
for (auto mimeType : mimeTypes) {
appInfo.supportedMime.push_back(mimeType);
}
userAppInfos.appInfos.push_back(appInfo);
return bAdd;
}
bool Delete(const std::string &desktopId)
{
std::vector<Methods::UserAppInfo>::iterator iter = userAppInfos.appInfos.begin();
while (iter != userAppInfos.appInfos.end()) {
if (iter->deskopid == desktopId) {
iter = userAppInfos.appInfos.erase(iter);
return true;
} else {
iter++;
}
}
return false;
}
bool DeleteMimeTypes(const std::string &desktopId, QStringList mimeTypes)
{
bool bDelete = false;
std::vector<Methods::UserAppInfo>::iterator iter = userAppInfos.appInfos.begin();
while (iter != userAppInfos.appInfos.end()) {
if (iter->deskopid == desktopId) {
for (auto mimeType : mimeTypes) {
if (std::find(iter->supportedMime.begin(), iter->supportedMime.end(), mimeType) == iter->supportedMime.end()) {
bDelete = true;
iter->supportedMime.push_back(mimeType);
}
}
}
iter++;
}
return bDelete;
}
std::vector<Methods::UserAppInfo> GetUserAppInfosByMimeType(std::string mimeType)
{
std::vector<Methods::UserAppInfo> retVector;
for (auto iter : userAppInfos.appInfos) {
if (std::find(iter.supportedMime.begin(), iter.supportedMime.end(), mimeType.c_str()) != iter.supportedMime.end()) {
retVector.push_back(iter);
}
}
return retVector;
}
~MimeAppPrivate() {}
};
MimeApp::MimeApp(QObject *parent) : QObject(parent), dd_ptr(new MimeAppPrivate(this))
{
Q_D(MimeApp);
d->Init();
initConfigData();
}
MimeApp::~MimeApp()
{
}
void MimeApp::deleteMimeAssociation(std::string mimeType, std::string desktopId)
{
Q_D(MimeApp);
KeyFile keyFile;
keyFile.loadFile(d->filename);
std::vector<std::string> sessions{AppinfoCommon::SectionDefaultApps, AppinfoCommon::SectionAddedAssociations};
for (auto iter : sessions) {
std::vector<std::string> apps = keyFile.getStrList(iter, mimeType);
std::vector<std::string>::iterator app = apps.begin();
while (app != apps.end()) {
if ((*app) == desktopId) {
app = apps.erase(app);
} else {
app++;
}
}
if (apps.empty()) {
//keyFile.DeleteKey(section, mimeType);
} else {
//keyFile.SetStringList(iter,mimeType,apps);
}
}
keyFile.saveToFile(d->filename);
}
void MimeApp::initConfigData()
{
std::string filename = findFilePath("/dde-daemon/mime/data.json");
QFile file(filename.c_str());
if (!file.exists()) {
return;
}
if (!file.open(QIODevice::ReadOnly)) {
return;
}
QJsonParseError *error = new QJsonParseError;
QJsonDocument jdc = QJsonDocument::fromJson(file.readAll(), error);
Methods::DefaultUserAppInfos defaultAppInfos;
Methods::fromJson(jdc.object(), defaultAppInfos);
file.close();
for (auto defaultApp : defaultAppInfos.appInfos) {
std::string validAppId;
for (auto type : defaultApp.supportedType) {
if (!validAppId.empty()) {
if (setDefaultApp(type.toString().toStdString(), validAppId)) {
continue;
}
}
for (auto appId : defaultApp.appId) {
if (setDefaultApp(type.toString().toStdString(), appId.toString().toStdString())) {
validAppId = appId.toString().toStdString();
break;
} else {
continue;
}
}
}
}
}
std::string MimeApp::findFilePath(std::string fileName)
{
std::string homeDir = getUserHomeDir();
std::string path = homeDir + "/.local/share" + fileName;
QFileInfo file(path.c_str());
if (file.isFile()) {
return path;
}
path = "/usr/local/share" + fileName;
file.setFile(path.c_str());
if (file.isFile()) {
return path;
}
return "/usr/share" + fileName;
}
void MimeApp::AddUserApp(QStringList mimeTypes, const QString &desktopId)
{
qInfo() << "AddUserApp mimeTypes: " << mimeTypes << ", desktopId: " << desktopId;
Q_D(MimeApp);
std::shared_ptr<AppInfoManger> appInfo = AppInfoManger::loadByDesktopId(desktopId.toStdString());
if (!appInfo) {
return;
}
bool bAdd = d->Add(desktopId.toStdString(), mimeTypes);
if (bAdd) {
d->Write();
}
return;
}
bool MimeApp::setDefaultApp(const std::string &mimeType, const std::string &desktopId)
{
qInfo() << "setDefaultApp mimeType: " << mimeType.c_str() << ", desktopId: " << desktopId.c_str();
Q_D(MimeApp);
KeyFile keyFile;
keyFile.loadFile(d->filename);
std::string curDeskTopId = keyFile.getStr(AppinfoCommon::SectionDefaultApps, mimeType);
if (curDeskTopId == desktopId) {
return true;
}
return AppInfoManger::getDefaultApp(mimeType, desktopId);
}
void MimeApp::DeleteApp(QStringList mimeTypes, const QString &desktopId)
{
qInfo() << "DeleteApp mimeTypes: " << mimeTypes << ", desktopId: " << desktopId;
Q_D(MimeApp);
if (d->DeleteMimeTypes(desktopId.toStdString(), mimeTypes)) {
d->Write();
return;
}
std::shared_ptr<AppInfoManger> appInfo = AppInfoManger::loadByDesktopId(desktopId.toStdString());
if (!appInfo) {
return;
}
std::vector<std::string> originMimeTypes = appInfo->getStringList(AppinfoCommon::MainSection, AppinfoCommon::KeyMimeType);
for (auto iter : mimeTypes) {
if (std::find(originMimeTypes.begin(), originMimeTypes.end(), iter.toStdString()) == originMimeTypes.end()) {
deleteMimeAssociation(iter.toStdString(), desktopId.toStdString());
}
}
}
void MimeApp::DeleteUserApp(const QString &desktopId)
{
qInfo() << "DeleteUserApp desktopId: " << desktopId;
Q_D(MimeApp);
bool bDelete = d->Delete(desktopId.toStdString());
if (bDelete) {
d->Write();
}
}
QString MimeApp::GetDefaultApp(const QString &mimeType)
{
qInfo() << "GetDefaultApp mimeType: " << mimeType;
std::shared_ptr<AppInfoManger> appInfo;
if (mimeType.toStdString().compare(AppinfoCommon::AppMimeTerminal) == 0) {
appInfo = TerminalInfo::getInstanceTerminal().getDefaultTerminal();
} else {
std::string appId = AppInfoManger::getDefaultApp(mimeType.toStdString(), false);
appInfo = AppInfoManger::loadByDesktopId(appId);
}
if (!appInfo) {
return "";
}
return appInfo->toJson().c_str();
}
QString MimeApp::ListApps(const QString &mimeType)
{
qInfo() << "ListApps mimeType: " << mimeType;
std::vector<std::shared_ptr<AppInfoManger>> appInfos;
if (mimeType.toStdString().compare(AppinfoCommon::AppMimeTerminal) == 0) {
appInfos = TerminalInfo::getInstanceTerminal().getTerminalInfos();
} else {
std::vector<std::string> appList = AppInfoManger::getAppList(mimeType.toStdString());
for (auto iter : appList) {
std::shared_ptr<AppInfoManger> appInfo = AppInfoManger::loadByDesktopId(iter);
if (appInfo) {
appInfos.push_back(appInfo);
}
}
}
std::string userAppDir = getUserDataDir() + "/applications";
std::vector<std::shared_ptr<AppInfoManger>>::iterator iter = appInfos.begin();
while (iter != appInfos.end()) {
QDir dir((*iter)->getFileName().c_str());
if (dir.path().toStdString() == userAppDir && hasBeginWith(dir.path().toStdString(), "deepin-custom-")) {
iter = appInfos.erase(iter);
} else {
iter++;
}
}
return AppInfoManger::toJson(appInfos).c_str();
}
QString MimeApp::ListUserApps(const QString &mimeType)
{
qInfo() << "ListUserApps mimeType: " << mimeType;
Q_D(MimeApp);
std::vector<std::shared_ptr<AppInfoManger>> retAppInfos;
std::vector<Methods::UserAppInfo> userAppInfos = d->GetUserAppInfosByMimeType(mimeType.toStdString());
std::vector<Methods::UserAppInfo>::iterator iter = userAppInfos.begin();
while (iter != userAppInfos.end()) {
std::shared_ptr<AppInfoManger> appInfo = AppInfoManger::loadByDesktopId(iter->deskopid);
if (appInfo) {
appInfo->setCanDelete(true);
retAppInfos.push_back(appInfo);
}
iter++;
}
return AppInfoManger::toJson(retAppInfos).c_str();
}
void MimeApp::SetDefaultApp(const QStringList &mimeTypes, const QString &desktopId)
{
qInfo() << "SetDefaultApp mimeTypes: " << mimeTypes << ", desktopId: " << desktopId;
bool bSuccess = false;
for (auto mime : mimeTypes) {
if (mime.toStdString().compare(AppinfoCommon::AppMimeTerminal) == 0) {
bSuccess = TerminalInfo::getInstanceTerminal().setDefaultTerminal(desktopId.toStdString());
} else {
bSuccess = AppInfoManger::getDefaultApp(mime.toStdString(), desktopId.toStdString());
}
if (!bSuccess) {
qWarning() << "SetDefaultApp faile";
break;
}
}
}

View File

@ -0,0 +1,40 @@
#ifndef MIME_APP_H
#define MIME_APP_H
#include "../../lib/dfile.h"
#include <QObject>
class MimeAppPrivate;
class MimeApp : public QObject
{
Q_OBJECT
QScopedPointer<MimeAppPrivate> dd_ptr;
Q_DECLARE_PRIVATE_D(qGetPtrHelper(dd_ptr), MimeApp)
public:
explicit MimeApp(QObject *parent = nullptr);
void deleteMimeAssociation(std::string mimeType, std::string desktopId);
void initConfigData();
bool setDefaultApp(const std::string &mimeType, const std::string &desktopId);
std::string findFilePath(std::string fileName);
~MimeApp() override;
Q_SIGNALS:
// Standard Notifications dbus implementation
void Change();
public: // PROPERTIES
public Q_SLOTS: // METHODS
void AddUserApp(QStringList mimeTypes, const QString &desktopId);
void DeleteApp(QStringList mimeTypes, const QString &desktopId);
void DeleteUserApp(const QString &desktopId);
QString GetDefaultApp(const QString &mimeType);
QString ListApps(const QString &mimeType);
QString ListUserApps(const QString &mimeType);
void SetDefaultApp(const QStringList &mimeTypes, const QString &desktopId);
private:
};
#endif // MIME_APP_H

View File

@ -62,7 +62,7 @@ void ServerPrivate::work()
}
if (buffer[readBytes - 1] == '\0') {
emit q_ptr->onReadyRead(socket, data);
Q_EMIT q_ptr->onReadyRead(socket, data);
data.clear();
}
}
@ -139,7 +139,7 @@ bool Server::listen(const std::string &host)
d_ptr->workThread = new QThread;
d_ptr->moveToThread(d_ptr->workThread);
d_ptr->workThread->start();
emit d_ptr->requestStart();
Q_EMIT d_ptr->requestStart();
return result;
}

View File

@ -37,7 +37,7 @@ public:
Q_SIGNALS:
public slots:
public Q_SLOTS:
};
#endif // STARTMANAGERDBUSHANDLER_H

View File

@ -7,7 +7,9 @@ find_package(DtkCore REQUIRED)
pkg_check_modules(XCB REQUIRED IMPORTED_TARGET xcb-icccm xcb-ewmh xcb)
pkg_check_modules(X11 REQUIRED IMPORTED_TARGET x11)
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0 gio-unix-2.0)
pkg_check_modules(GLib REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules(QGSettings REQUIRED IMPORTED_TARGET gsettings-qt)
qt5_add_dbus_adaptor(ADAPTER_SOURCES
../../dbus/org.desktopspec.ApplicationManager.xml
@ -24,6 +26,12 @@ qt5_add_dbus_adaptor(ADAPTER_SOURCES
impl/application_instance.h
ApplicationInstance)
qt5_add_dbus_adaptor(ADAPTER_SOURCES
../../dbus/org.deepin.daemon.Mime.xml
../modules/mimeapp/mime_app.h
MimeApp)
add_definitions(-DUSE_QT)
file(GLOB_RECURSE SRCS "*.h" "*.cpp" "../frameworkdbus/*.h" "../frameworkdbus/*.cpp"
@ -45,12 +53,17 @@ target_link_libraries(deepin-application-manager
PkgConfig::XCB
PkgConfig::X11
PkgConfig::GIO
PkgConfig::GLib
PkgConfig::QGSettings
${Qt5Gui_LIBRARIES}
)
target_include_directories(deepin-application-manager PUBLIC
PkgConfig::XCB
PkgConfig::X11
PkgConfig::GIO
PkgConfig::GLib
PkgConfig::QGSettings
../lib
../utils
../frameworkdbus
@ -62,3 +75,4 @@ target_include_directories(deepin-application-manager PUBLIC
# binary file
install(TARGETS deepin-application-manager DESTINATION bin)
add_definitions(-DQT_NO_KEYWORDS)

View File

@ -166,3 +166,9 @@ QString Application::prefix() const
return d->m_prefix;
}
QList<QSharedPointer<ApplicationInstance>>& Application::getAllInstances(){
Q_D(Application);
return d->instances;
}

View File

@ -51,6 +51,8 @@ public: // PROPERTIES
QString filePath() const;
QSharedPointer<ApplicationInstance> createInstance(QStringList files);
QList<QSharedPointer<ApplicationInstance>>& getAllInstances();
bool destoryInstance(QString hashId);
public Q_SLOTS: // METHODS
QString Comment(const QString &locale);

View File

@ -1,7 +1,9 @@
#include "application_instance.h"
#include "../applicationhelper.h"
#include "application.h"
#include "applicationinstanceadaptor.h"
#include <qdatetime.h>
#include <QCryptographicHash>
#include <QDateTime>
#include <QProcess>
@ -9,32 +11,30 @@
#include <QUuid>
#include <QtConcurrent/QtConcurrent>
#include "../applicationhelper.h"
#include "application.h"
#include "applicationinstanceadaptor.h"
#ifdef DEFINE_LOADER_PATH
#include "../../src/define.h"
#endif
class ApplicationInstancePrivate {
class ApplicationInstancePrivate
{
ApplicationInstance* q_ptr = nullptr;
Q_DECLARE_PUBLIC(ApplicationInstance);
Application* application;
ApplicationInstanceAdaptor* adapter;
QString m_path;
Application* application;
ApplicationInstanceAdaptor* adapter;
QString m_path;
QSharedPointer<modules::ApplicationHelper::Helper> helper;
QDateTime startupTime;
QString m_id;
QDateTime startupTime;
QString m_id;
uint32_t pid;
public:
ApplicationInstancePrivate(ApplicationInstance* parent) : q_ptr(parent)
{
startupTime = QDateTime::currentDateTime();
m_id = QString(QCryptographicHash::hash(QUuid::createUuid().toByteArray(), QCryptographicHash::Md5).toHex());
m_path = QString("/org/desktopspec/ApplicationInstance/%1").arg(m_id);
adapter = new ApplicationInstanceAdaptor(q_ptr);
m_id = QString(QCryptographicHash::hash(QUuid::createUuid().toByteArray(), QCryptographicHash::Md5).toHex());
m_path = QString("/org/desktopspec/ApplicationInstance/%1").arg(m_id);
adapter = new ApplicationInstanceAdaptor(q_ptr);
}
~ApplicationInstancePrivate()
@ -47,16 +47,18 @@ public:
{
#ifdef DEFINE_LOADER_PATH
const QString task_hash{ QString("DAM_TASK_HASH=%1").arg(m_id) };
const QString task_type{ "DAM_TASK_TYPE=freedesktop " };
QProcess* p = new QProcess(q_ptr);
p->connect(p, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), p, [=] {
const QString task_hash{QString("DAM_TASK_HASH=%1").arg(m_id)};
const QString task_type{"DAM_TASK_TYPE=freedesktop "};
QProcess* p = new QProcess(q_ptr);
p->connect(p, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), p, [ = ] {
qInfo().noquote() << p->readAllStandardOutput();
qWarning().noquote() << p->readAllStandardError();
});
p->connect(p, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), q_ptr, &ApplicationInstance::taskFinished);
p->connect(p, &QProcess::readyReadStandardOutput, p, [=] { qInfo() << p->readAllStandardOutput(); });
p->connect(p, &QProcess::readyReadStandardError, p, [=] { qWarning() << p->readAllStandardError(); });
p->connect(p, &QProcess::readyReadStandardOutput, p, [ = ]
{ qInfo() << p->readAllStandardOutput(); });
p->connect(p, &QProcess::readyReadStandardError, p, [ = ]
{ qWarning() << p->readAllStandardError(); });
p->setProgram(LOADER_PATH);
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert("DAM_TASK_HASH", m_id);
@ -65,11 +67,11 @@ public:
p->start();
p->waitForStarted();
if (p->state() == QProcess::ProcessState::NotRunning) {
emit q_ptr->taskFinished(p->exitCode());
Q_EMIT q_ptr->taskFinished(p->exitCode());
}
#else
qInfo() << "app manager load service:" << QString("org.desktopspec.application.instance@%1.service").arg(m_id);
QDBusInterface systemd("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager");
QDBusInterface systemd("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager");
QDBusReply<void> reply = systemd.call("StartUnit", QString("org.desktopspec.application.instance@%1.service").arg(m_id), "replace-irreversibly");
if (!reply.isValid()) {
qInfo() << reply.error();
@ -88,19 +90,28 @@ public:
}
void _kill() {}
uint32_t _getPid()
{
return pid;
}
void _success(const QString& data)
{
pid = data.toUInt();
}
};
ApplicationInstance::ApplicationInstance(Application* parent, QSharedPointer<modules::ApplicationHelper::Helper> helper, QStringList files)
: QObject(nullptr)
, dd_ptr(new ApplicationInstancePrivate(this))
, m_files(files)
: QObject(nullptr)
, dd_ptr(new ApplicationInstancePrivate(this))
, m_files(files)
{
Q_D(ApplicationInstance);
d->application = parent;
d->helper = helper;
d->helper = helper;
QTimer::singleShot(0, this, [=] {
QTimer::singleShot(0, this, [ = ] {
QDBusConnection::sessionBus().registerObject(d->m_path, "org.desktopspec.ApplicationInstance", this);
d->run();
});
@ -145,17 +156,17 @@ Methods::Task ApplicationInstance::taskInfo() const
Q_D(const ApplicationInstance);
Methods::Task task;
task.id = d->m_id;
task.id = d->m_id;
task.runId = d->application->id();
task.filePath = d->application->filePath();
task.date = QString::number(startuptime());
task.date = QString::number(startuptime());
task.arguments = m_files;
// TODO: debug to display environment
task.environments.insert( "DISPLAY", ":0" );
task.environments.insert("DISPLAY", ":0");
auto sysEnv = QProcessEnvironment::systemEnvironment();
for (const auto& key : sysEnv.keys()) {
task.environments.insert( key, sysEnv.value(key) );
task.environments.insert(key, sysEnv.value(key));
}
return task;
@ -174,3 +185,17 @@ void ApplicationInstance::Kill()
return d->_kill();
}
uint32_t ApplicationInstance::getPid()
{
Q_D(ApplicationInstance);
return d->_getPid();
}
void ApplicationInstance::Success(const QString& data)
{
Q_D(ApplicationInstance);
QDBusConnection::sessionBus().registerObject(d->m_path, "org.desktopspec.ApplicationInstance", this);
return d->_success(data);
}

View File

@ -41,6 +41,8 @@ Q_SIGNALS:
public Q_SLOTS: // METHODS
void Exit();
void Kill();
void Success(const QString& data);
uint32_t getPid();
};
#endif /* D6D05668_8A58_43AA_91C5_C6278643A1AF */

View File

@ -11,6 +11,7 @@
#include <map>
#include <mutex>
#include <thread>
#include <QProcess>
#include "../../modules/methods/basic.h"
#include "../../modules/methods/instance.hpp"
@ -21,20 +22,23 @@
#include "application.h"
#include "application_instance.h"
#include "applicationinstanceadaptor.h"
#include "../lib/keyfile.h"
ApplicationManagerPrivate::ApplicationManagerPrivate(ApplicationManager *parent)
ApplicationManagerPrivate::ApplicationManagerPrivate(ApplicationManager* parent)
: QObject(parent)
, q_ptr(parent)
, startManager(new StartManager(this))
, virtualMachePath("/usr/share/dde-daemon/supportVirsConf.ini")
, section("AppName")
, key("support")
{
const QString socketPath{QString("/run/user/%1/deepin-application-manager.socket").arg(getuid())};
connect(&server, &Socket::Server::onReadyRead, this, &ApplicationManagerPrivate::recvClientData, Qt::QueuedConnection);
server.listen(socketPath.toStdString());
const QString socketPath{QString("/run/user/%1/deepin-application-manager.socket").arg(getuid())};
connect(&server, &Socket::Server::onReadyRead, this, &ApplicationManagerPrivate::recvClientData, Qt::QueuedConnection);
server.listen(socketPath.toStdString());
}
ApplicationManagerPrivate::~ApplicationManagerPrivate()
{
}
bool ApplicationManagerPrivate::checkDMsgUid()
@ -48,7 +52,7 @@ bool ApplicationManagerPrivate::checkDMsgUid()
* @param socket
* @param data
*/
void ApplicationManagerPrivate::recvClientData(int socket, const std::vector<char> &data)
void ApplicationManagerPrivate::recvClientData(int socket, const std::vector<char>& data)
{
QByteArray jsonArray = data.data();
Methods::Basic basic;
@ -75,8 +79,9 @@ void ApplicationManagerPrivate::recvClientData(int socket, const std::vector<cha
// 退出
if (basic.type == "quit") {
Methods::Quit quit;
Methods::ProcessStatus quit;
Methods::fromJson(jsonArray, quit);
processInstanceStatus(quit);
server.close(socket);
std::cout << "client quit" << std::endl;
break;
@ -100,18 +105,26 @@ void ApplicationManagerPrivate::recvClientData(int socket, const std::vector<cha
write(socket, tmpArray.toStdString());
break;
}
if (basic.type == "success") {
Methods::ProcessStatus processSuccess;
Methods::fromJson(jsonArray, processSuccess);
processInstanceStatus(processSuccess);
std::cout << "client success" << std::endl;
break;
}
write(socket, jsonArray.toStdString());
} while (false);
}
void ApplicationManagerPrivate::write(int socket, const std::vector<char> &data)
void ApplicationManagerPrivate::write(int socket, const std::vector<char>& data)
{
std::vector<char> tmp = data;
tmp.push_back('\0');
server.write(socket, tmp);
}
void ApplicationManagerPrivate::write(int socket, const std::string &data)
void ApplicationManagerPrivate::write(int socket, const std::string& data)
{
std::vector<char> result;
std::copy(data.cbegin(), data.cend(), std::back_inserter(result));
@ -123,15 +136,54 @@ void ApplicationManagerPrivate::write(int socket, const char c)
return write(socket, std::vector<char>(c));
}
void ApplicationManagerPrivate::init()
{
KeyFile keyFile;
keyFile.loadFile(virtualMachePath);
virtualMachines = keyFile.getStrList(section, key);
if (virtualMachines.empty()) {
virtualMachines = {"hvm", "bochs", "virt", "vmware", "kvm", "cloud", "invented"};
}
}
ApplicationManager* ApplicationManager::instance() {
void ApplicationManagerPrivate::processInstanceStatus(Methods::ProcessStatus instanceStatus)
{
bool bFound = false;
auto application = applications.begin();
while (application != applications.end()) {
auto instance = (*application)->getAllInstances().begin();
while (instance != (*application)->getAllInstances().end()) {
if ((*instance)->hash() == instanceStatus.id) {
bFound = true;
}
if (bFound) {
if (instanceStatus.type == "success") {
(*instance)->Success(instanceStatus.data);
} else if (instanceStatus.type == "quit") {
(*instance)->Exit();
(*application)->getAllInstances().erase(instance);
} else {
qWarning() << "instance tyep : " << instanceStatus.type << "not found";
}
return;
}
instance++;
}
application++;
}
}
ApplicationManager* ApplicationManager::instance()
{
static ApplicationManager manager;
return &manager;
}
ApplicationManager::ApplicationManager(QObject *parent)
: QObject(parent)
, dd_ptr(new ApplicationManagerPrivate(this))
ApplicationManager::ApplicationManager(QObject* parent)
: QObject(parent)
, dd_ptr(new ApplicationManagerPrivate(this))
{
Q_D(ApplicationManager);
@ -140,7 +192,7 @@ ApplicationManager::ApplicationManager(QObject *parent)
ApplicationManager::~ApplicationManager() {}
void ApplicationManager::addApplication(const QList<QSharedPointer<Application>> &list)
void ApplicationManager::addApplication(const QList<QSharedPointer<Application>>& list)
{
Q_D(ApplicationManager);
@ -164,14 +216,14 @@ void ApplicationManager::launchAutostartApps()
*/
}
QDBusObjectPath ApplicationManager::GetInformation(const QString &id)
QDBusObjectPath ApplicationManager::GetInformation(const QString& id)
{
Q_D(ApplicationManager);
if (!d->checkDMsgUid())
return {};
for (const QSharedPointer<Application> &app : d->applications) {
for (const QSharedPointer<Application>& app : d->applications) {
if (app->id() == id) {
return app->path();
}
@ -179,13 +231,13 @@ QDBusObjectPath ApplicationManager::GetInformation(const QString &id)
return {};
}
QList<QDBusObjectPath> ApplicationManager::GetInstances(const QString &id)
QList<QDBusObjectPath> ApplicationManager::GetInstances(const QString& id)
{
Q_D(ApplicationManager);
if (!d->checkDMsgUid())
return {};
for (const auto &app : d->applications) {
for (const auto& app : d->applications) {
if (app->id() == id) {
return app->instances();
}
@ -200,7 +252,7 @@ QList<QDBusObjectPath> ApplicationManager::GetInstances(const QString &id)
* @param files
* @return
*/
QDBusObjectPath ApplicationManager::Launch(const QString &id, QStringList files)
QDBusObjectPath ApplicationManager::Launch(const QString& id, QStringList files)
{
qInfo() << "Launch " << id;
Q_D(ApplicationManager);
@ -208,14 +260,14 @@ QDBusObjectPath ApplicationManager::Launch(const QString &id, QStringList files)
return {};
// 创建一个实例
for (const QSharedPointer<Application> &app : d->applications) {
for (const QSharedPointer<Application>& app : d->applications) {
QString appId = app->id();
if (app->id() == id) {
// 创建任务所需的数据,并记录到任务队列,等待 loader 消耗
QSharedPointer<ApplicationInstance> instance{app->createInstance(files)};
const std::string hash{instance->hash().toStdString()};
connect(instance.get(), &ApplicationInstance::taskFinished, this, [=] {
for (auto it = d->tasks.begin(); it != d->tasks.end(); ++it) {
connect(instance.get(), &ApplicationInstance::taskFinished, this, [ = ] {
for (auto it = d->tasks.begin(); it != d->tasks.end(); ++it){
if (it->first == hash) {
d->tasks.erase(it);
break;
@ -343,7 +395,7 @@ QList<QDBusObjectPath> ApplicationManager::instances() const
QList<QDBusObjectPath> result;
for (const auto &app : d->applications) {
for (const auto& app : d->applications) {
result += app->instances();
}
@ -355,11 +407,48 @@ QList<QDBusObjectPath> ApplicationManager::list() const
Q_D(const ApplicationManager);
QList<QDBusObjectPath> result;
for (const QSharedPointer<Application> &app : d->applications) {
for (const QSharedPointer<Application>& app : d->applications) {
result << app->path();
}
return result;
}
// 如果app manager拥有全部进程信息可以在app manger里面获取
bool ApplicationManager::IsPidVirtualMachine(uint32_t pid)
{
Q_D(const ApplicationManager);
char buff[256];
ssize_t nbytes = readlink(QString("/proc/%1/exe").arg(pid).toStdString().c_str(), buff, 256);
if (nbytes == -1) {
return false;
}
std::string execPath(buff);
for (auto iter : d->virtualMachines) {
std::string::size_type idx = iter.find(execPath);
if (idx != std::string::npos) {
return true;
}
}
return false;
}
bool ApplicationManager::IsProcessExist(uint32_t pid)
{
Q_D(const ApplicationManager);
for (auto app : d->applications) {
for (auto instance : app->getAllInstances()) {
if (instance->getPid() == pid) {
return true;
}
}
}
return false;
}
#include "application_manager.moc"

View File

@ -3,6 +3,7 @@
#include "../../modules/startmanager/startmanager.h"
#include "../../modules/socket/server.h"
#include "../../modules/methods/process_status.hpp"
#include <QObject>
#include <QDBusObjectPath>
@ -22,6 +23,10 @@ class ApplicationManagerPrivate : public QObject
Socket::Server server;
std::multimap<std::string, QSharedPointer<ApplicationInstance>> tasks;
StartManager *startManager;
std::vector<std::string> virtualMachines;
const std::string virtualMachePath;
const std::string section;
const std::string key;
public:
ApplicationManagerPrivate(ApplicationManager *parent);
@ -29,6 +34,7 @@ public:
// 检测调用方身份
bool checkDMsgUid();
void init();
private:
void recvClientData(int socket, const std::vector<char> &data);
@ -38,6 +44,8 @@ private:
void write(int socket, const std::string &data);
void write(int socket, const char c);
void processInstanceStatus(Methods::ProcessStatus instanceStatus);
};
class ApplicationManager : public QObject, public QDBusContext
@ -55,6 +63,8 @@ public:
void addApplication(const QList<QSharedPointer<Application>> &list);
void launchAutostartApps();
void processInstanceStatus(Methods::ProcessStatus instanceStatus);
Q_SIGNALS:
void AutostartChanged(QString status, QString filePath);
@ -84,6 +94,8 @@ public Q_SLOTS: // METHODS
void RunCommand(QString exe, QStringList args);
void RunCommandWithOptions(QString exe, QStringList args, QMap<QString, QString> options);
void TryAgain(bool launch);
bool IsPidVirtualMachine(uint32_t pid);
bool IsProcessExist(uint32_t pid);
};
#endif /* A2862DC7_5DA3_4129_9796_671D88015BED */

View File

@ -5,10 +5,12 @@
#include "applicationmanageradaptor.h"
#include "applicationadaptor.h"
#include "applicationhelper.h"
#include "mimeadaptor.h"
#include "../modules/apps/appmanager.h"
#include "../modules/launcher/launchermanager.h"
#include "../modules/dock/dockmanager.h"
#include "../modules/startmanager/startmanager.h"
#include "../modules/mimeapp/mime_app.h"
#include <QDir>
#include <DLog>
@ -103,5 +105,11 @@ int main(int argc, char *argv[])
ApplicationManager::instance()->launchAutostartApps();
MimeApp* mimeApp = new MimeApp;
new MimeAdaptor(mimeApp);
QDBusConnection::sessionBus().registerService("org.deepin.daemon.Mime1");
QDBusConnection::sessionBus().registerObject("/org/deepin/daemon/Mime1", "org.deepin.daemon.Mime1", mimeApp);
return app.exec();
}

View File

@ -37,7 +37,7 @@ public:
// 记录模块对应类信息
static bool registe(QString moduleName, SynModuleBase *module);
public slots:
public Q_SLOTS:
// 获取配置信息
QByteArray GetSyncConfig(QString moduleName);
// 设置配置信息