feat: 启动器支持玲珑应用卸载功能实现

1. 使用命令行方式实现玲珑应用卸载
2. 当linglong-bin版本大于3.3.14, ll-cli uninstall appId,才是同步执行,根据卸载后返回的字段信息确认卸载状态;否则为异步方式进行调用卸载的,这种情况下,AM 是无法得到卸载应用的状态的。

Log:
Influence: 启动器支持玲珑应用卸载
Task: https://pms.uniontech.com/task-view-207481.html
Change-Id: Ia809babd2d6f5508e1ea06a60315c40397d3d944
This commit is contained in:
songwentao 2022-10-31 17:02:24 +08:00
parent 6c06ed86b7
commit ecc94f01c8
4 changed files with 115 additions and 103 deletions

View File

@ -69,6 +69,7 @@ void DBusAdaptorLauncher::setFullscreen(bool value)
LauncherItemInfoList DBusAdaptorLauncher::GetAllItemInfos()
{
parent()->initItems();
return parent()->getAllItemInfos();
}
@ -107,11 +108,11 @@ bool DBusAdaptorLauncher::RequestSendToDesktop(const QString &id)
return parent()->requestSendToDesktop(id);
}
void DBusAdaptorLauncher::RequestUninstall(const QString &id, bool unused)
void DBusAdaptorLauncher::RequestUninstall(const QString &desktop, bool unused)
{
Q_UNUSED(unused);
parent()->requestUninstall(id);
parent()->requestUninstall(desktop);
}
void DBusAdaptorLauncher::SetDisableScaling(const QString &id, bool value)

View File

@ -78,7 +78,7 @@ class DBusAdaptorLauncher: public QDBusAbstractAdaptor
" <arg direction=\"out\" type=\"b\" name=\"ok\"/>\n"
" </method>\n"
" <method name=\"RequestUninstall\">\n"
" <arg direction=\"in\" type=\"s\" name=\"id\"/>\n"
" <arg direction=\"in\" type=\"s\" name=\"desktop\"/>\n"
" <arg direction=\"in\" type=\"b\" name=\"unused\"/>\n"
" </method>\n"
" <method name=\"SetDisableScaling\">\n"
@ -134,7 +134,7 @@ public Q_SLOTS: // METHODS
bool IsItemOnDesktop(const QString &id);
bool RequestRemoveFromDesktop(const QString &id);
bool RequestSendToDesktop(const QString &id);
void RequestUninstall(const QString &id, bool unused);
void RequestUninstall(const QString &desktop, bool unused);
void SetDisableScaling(const QString &id, bool value);
void SetUseProxy(const QString &id, bool value);

View File

@ -53,7 +53,6 @@ const QString LASTORE_INTERFACE = "org.deepin.lastore1.Manager";
Launcher::Launcher(QObject *parent)
: SynModule(parent)
, m_removeState(false)
, m_appInfo(DesktopInfo(""))
{
registeModule("launcher");
@ -130,7 +129,7 @@ void Launcher::setFullscreen(bool isFull)
LauncherItemInfoList Launcher::getAllItemInfos()
{
LauncherItemInfoList allItemList;
for (auto item : m_desktopAndItemMap)
for (auto &item : m_desktopAndItemMap)
allItemList.push_back(item.info);
return allItemList;
@ -279,10 +278,18 @@ bool Launcher::requestSendToDesktop(QString appId)
* @brief Launcher::requestUninstall
* @param appId
*/
void Launcher::requestUninstall(QString appId)
void Launcher::requestUninstall(const QString &desktop)
{
if (itemsMap.find(appId) == itemsMap.end()) {
qDebug() << QString(" %1 uninstall faill ...").arg(appId);
bool exist = false;
for (const Item &item : m_desktopAndItemMap.values()) {
if (item.info.path == desktop) {
exist = true;
break;
}
}
if (!exist) {
qWarning() << QString(" %1 uninstall faill ...").arg(desktop);
return;
}
@ -296,14 +303,19 @@ void Launcher::requestUninstall(QString appId)
QString result = QString::fromUtf8(process.readAllStandardOutput());
process.close();
if (result != launcherExe) {
qDebug() << result << " has no right to uninstall " << appId;
qWarning() << result << " has no right to uninstall " << desktop;
return;
}
const Item &item = itemsMap[appId];
if (!m_desktopAndItemMap.keys().contains(desktop)) {
qWarning() << QString("can't find desktopPath: %1").arg(desktop);
return;
}
const Item &item = m_desktopAndItemMap[desktop];
DesktopInfo info(item.info.path.toStdString());
if (!info.isValidDesktop()) {
qDebug() << QString("%1 desktop file is invalid...").arg(item.info.name);
qWarning() << QString("%1 desktop file is invalid...").arg(item.info.name);
return;
}
@ -436,29 +448,13 @@ void Launcher::onHandleUninstall(const QDBusMessage &message)
#ifdef QT_DEBUG
qInfo() << "changedProps: " << changedProps << ", status: " << status;
#endif
const QString &appId = QString::fromStdString(m_appInfo.getId());
const QString &desktop = QString::fromStdString(m_appInfo.getFileName());
if (status == "succeed" || status == "end") {
// 移除desktop文件
Item appItem = Item();
for (const Item &item : m_desktopAndItemMap) {
if (item.info.path == QString::fromStdString(m_appInfo.getFileName())) {
appItem = item;
qDebug() << QString("app-%1 removed successfully").arg(item.info.name);
break;
}
}
removeDesktop(appItem);
// 从自动启动目录中移除
removeAutoStart();
m_removeState = true;
Q_EMIT uninstallSuccess(appId);
removeDesktop(desktop);
removeAutoStart(desktop);
Q_EMIT uninstallSuccess(desktop);
} else if (status == "failed") {
m_removeState = false;
QString msg = QString("uninstall %1 result %2").arg(m_appInfo.getName().c_str()).arg(false);
Q_EMIT uninstallFailed(appId, msg);
Q_EMIT uninstallFailed(desktop, QString());
}
}
@ -693,6 +689,8 @@ void Launcher::loadNameMap()
*/
void Launcher::initItems()
{
itemsMap.clear();
m_desktopAndItemMap.clear();
std::vector<DesktopInfo> infos = AppsDir::getAllDesktopInfos();
for (auto &app : infos) {
if (!app.isExecutableOk()
@ -965,6 +963,11 @@ end:
return ty;
}
bool Launcher::isLingLongApp(const QString &filePath)
{
return filePath.contains("/persistent/linglong");
}
/**
* @brief Launcher::doUninstall
* @param info
@ -973,46 +976,48 @@ end:
*/
void Launcher::doUninstall(DesktopInfo &info, const Item &item)
{
// 查询包名
QString pkg = queryPkgName(item.info.id, item.info.path);
if (pkg.isEmpty())
pkg = queryPkgNameWithDpkg(item.info.path);
if (isLingLongApp(QString::fromStdString(info.getFileName()))) {
QProcess process;
// 获取 appId
QStringList args;
QString appId = item.exec.section(' ', 2, 2);
args.append("uninstall");
args.append(appId);
if (pkg.isEmpty()) {
qDebug() << "uninstall failed, becase package name is Empty";
return;
int retCode = QProcess::execute("ll-cli", args);
if (retCode != 0) {
Q_EMIT uninstallFailed(item.info.path, QString());
notifyUninstallDone(item, false);
qWarning() << QString("uninstall %1 failed...").arg(info.getFileName().c_str());
return;
}
Q_EMIT uninstallSuccess(item.info.path);
// 浮窗通知
notifyUninstallDone(item, true);
} else {
// 查询包名
QString pkg = queryPkgName(item.info.id, item.info.path);
if (pkg.isEmpty())
pkg = queryPkgNameWithDpkg(item.info.path);
if (pkg.isEmpty()) {
qWarning() << "uninstall failed, becase package name is Empty";
return;
}
// 检测包是否安装
QDBusInterface lastoreDbus = QDBusInterface(LASTORE_SERVICE, LASTORE_PATH, LASTORE_INTERFACE, QDBusConnection::systemBus());
QDBusReply<bool> reply = lastoreDbus.call("PackageExists", pkg);
// 包未安装时
if (!(reply.isValid() && reply.value()))
return;
// 卸载系统应用
uninstallApp(item.info.name, pkg);
}
// 检测包是否安装
QDBusInterface lastoreDbus = QDBusInterface(LASTORE_SERVICE, LASTORE_PATH, LASTORE_INTERFACE, QDBusConnection::systemBus());
QDBusReply<bool> reply = lastoreDbus.call("PackageExists", pkg);
// 包未安装时
if (!(reply.isValid() && reply.value()))
return;
// 卸载系统应用
m_desktopAndItemMap.remove(item.info.path);
uninstallApp(item.info.name, pkg);
// TODO: 不同类型的应用分别进行处理
// switch (getAppType(info, item)) {
// case (AppType::Flatpak):
// uninstallFlatpak(info, item); // 待测
// break;
// case (AppType::ChromeShortcut):
// removeDesktop(item);
// break;
// case (AppType::CrossOver):
// uninstallApp(item.info.name, "crossvoer"); // 待测
// break;
// case (AppType::WineApp):
// uninstallWineApp(item); // 待测
// break;
// case (AppType::Default):
// removeDesktop(item);
// break;
// }
}
/**
@ -1094,7 +1099,7 @@ void Launcher::uninstallApp(const QString &name, const QString &pkg)
QDBusReply<QDBusObjectPath> reply = lastoreDbus.call(QDBus::Block, "RemovePackage", name, pkg);
if (!reply.isValid() || reply.value().path().isEmpty()) {
qDebug() << "RemovePackage failed: " << reply.error();
qWarning() << "RemovePackage failed: " << reply.error();
return;
}
@ -1106,27 +1111,20 @@ void Launcher::uninstallApp(const QString &name, const QString &pkg)
"PropertiesChanged","sa{sv}as", this, SLOT(onHandleUninstall(const QDBusMessage &)));
}
/**
* @brief Launcher::removeDesktop desktop文件
* @param item
* @return
/** 移除desktop文件
* @brief Launcher::removeDesktop
* @param desktop
*/
bool Launcher::removeDesktop(const Item &item)
void Launcher::removeDesktop(const QString &desktop)
{
// 移除desktop文件
QFile file(item.info.path);
QFile file(desktop);
if (!file.exists()) {
qDebug() << "file not exist...item info: " << item.info;
return false;
qDebug() << "file not exist...item info: " << desktop;
return;
}
bool ret = file.remove();
std::thread thread([ this, item, ret ] {
notifyUninstallDone(item, ret);
});
thread.detach();
return ret;
m_desktopAndItemMap.remove(desktop);
file.remove();
}
/**
@ -1138,21 +1136,33 @@ void Launcher::notifyUninstallDone(const Item &item, bool result)
{
QString msg;
if (result)
msg = QString("%1 removed successfully").arg(item.info.name);
msg = QString(tr("Removed successfully"));
else
msg = QString("Failed to uninstall %1").arg(item.info.name);
msg = QString(tr("Failed to remove the app"));
QList<QVariant> argList;
argList << QString("deepin-app-store")
<< quint32(0)
<< QString("deepin-app-store")
<< msg
<< QString("")
<< QStringList("")
<< QVariantMap()
<< qint32(-1);
QDBusInterface interface = QDBusInterface("org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications");
interface.call("Notify", "deepin-app-store", 0, "deepin-appstore", msg, "", QVariant(), QVariant(), -1);
interface.callWithArgumentList(QDBus::Block, "Notify", argList);
}
void Launcher::removeAutoStart()
void Launcher::removeAutoStart(const QString &desktop)
{
QString filePath(QDir::homePath() + "/.config/autostart/" + m_appInfo.getName().c_str() + ".desktop");
QFile file(filePath);
QFile file(desktop);
if (!file.exists()) {
qDebug() << QString("desktop file %1 doesn't exist...").arg(desktop);
return;
}
if (file.exists())
file.remove();
file.remove();
}
/**

View File

@ -86,6 +86,8 @@ public:
// 设置配置
void setSynConfig(QByteArray ba);
QByteArray getSyncConfig();
void initItems();
const QMap<QString, Item> *getItems();
int getDisplayMode();
@ -101,15 +103,15 @@ public:
bool isItemOnDesktop(QString appId);
bool requestRemoveFromDesktop(QString appId);
bool requestSendToDesktop(QString appId);
void requestUninstall(QString appId);
void requestUninstall(const QString &desktop);
void setDisableScaling(QString appId, bool value);
void setUseProxy(QString appId, bool value);
Q_SIGNALS:
void itemChanged(QString status, LauncherItemInfo itemInfo, qint64 ty);
void newAppLaunched(QString appId);
void uninstallSuccess(QString appId);
void uninstallFailed(QString appId, QString errMsg);
void uninstallSuccess(const QString &desktop);
void uninstallFailed(const QString &desktop, QString errMsg);
void displayModeChanged(int mode);
void fullScreenChanged(bool isFull);
@ -129,7 +131,6 @@ private:
void loadPkgCategoryMap();
void handleAppHiddenChanged();
void loadNameMap();
void initItems();
QString getAppIdByFilePath(QString filePath, QStringList dirs);
bool isDeepinCustomDesktopFile(QString fileName);
Item NewItemWithDesktopInfo(DesktopInfo &info);
@ -141,13 +142,14 @@ private:
Item getItemByPath(QString itemPath);
void emitItemChanged(const Item *item, QString status);
AppType getAppType(DesktopInfo &info, const Item &item);
bool isLingLongApp(const QString &filePath);
void doUninstall(DesktopInfo &info, const Item &item);
void uninstallFlatpak(DesktopInfo &info, const Item &item);
bool uninstallWineApp(const Item &item);
void uninstallApp(const QString &name, const QString &pkg);
bool removeDesktop(const Item &item);
void removeDesktop(const QString &desktop);
void notifyUninstallDone(const Item &item, bool result);
void removeAutoStart();
void removeAutoStart(const QString &desktop);
private:
QMap<QString, Item> itemsMap; // appId, Item
@ -160,7 +162,6 @@ private:
QStringList appDirs;
QMap<QString, Item> m_desktopAndItemMap; // desktoppath,Item
bool m_removeState; // 卸载状态
DesktopInfo m_appInfo; // 卸载应用
};