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() LauncherItemInfoList DBusAdaptorLauncher::GetAllItemInfos()
{ {
parent()->initItems();
return parent()->getAllItemInfos(); return parent()->getAllItemInfos();
} }
@ -107,11 +108,11 @@ bool DBusAdaptorLauncher::RequestSendToDesktop(const QString &id)
return parent()->requestSendToDesktop(id); return parent()->requestSendToDesktop(id);
} }
void DBusAdaptorLauncher::RequestUninstall(const QString &id, bool unused) void DBusAdaptorLauncher::RequestUninstall(const QString &desktop, bool unused)
{ {
Q_UNUSED(unused); Q_UNUSED(unused);
parent()->requestUninstall(id); parent()->requestUninstall(desktop);
} }
void DBusAdaptorLauncher::SetDisableScaling(const QString &id, bool value) 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" " <arg direction=\"out\" type=\"b\" name=\"ok\"/>\n"
" </method>\n" " </method>\n"
" <method name=\"RequestUninstall\">\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" " <arg direction=\"in\" type=\"b\" name=\"unused\"/>\n"
" </method>\n" " </method>\n"
" <method name=\"SetDisableScaling\">\n" " <method name=\"SetDisableScaling\">\n"
@ -134,7 +134,7 @@ public Q_SLOTS: // METHODS
bool IsItemOnDesktop(const QString &id); bool IsItemOnDesktop(const QString &id);
bool RequestRemoveFromDesktop(const QString &id); bool RequestRemoveFromDesktop(const QString &id);
bool RequestSendToDesktop(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 SetDisableScaling(const QString &id, bool value);
void SetUseProxy(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) Launcher::Launcher(QObject *parent)
: SynModule(parent) : SynModule(parent)
, m_removeState(false)
, m_appInfo(DesktopInfo("")) , m_appInfo(DesktopInfo(""))
{ {
registeModule("launcher"); registeModule("launcher");
@ -130,7 +129,7 @@ void Launcher::setFullscreen(bool isFull)
LauncherItemInfoList Launcher::getAllItemInfos() LauncherItemInfoList Launcher::getAllItemInfos()
{ {
LauncherItemInfoList allItemList; LauncherItemInfoList allItemList;
for (auto item : m_desktopAndItemMap) for (auto &item : m_desktopAndItemMap)
allItemList.push_back(item.info); allItemList.push_back(item.info);
return allItemList; return allItemList;
@ -279,10 +278,18 @@ bool Launcher::requestSendToDesktop(QString appId)
* @brief Launcher::requestUninstall * @brief Launcher::requestUninstall
* @param appId * @param appId
*/ */
void Launcher::requestUninstall(QString appId) void Launcher::requestUninstall(const QString &desktop)
{ {
if (itemsMap.find(appId) == itemsMap.end()) { bool exist = false;
qDebug() << QString(" %1 uninstall faill ...").arg(appId); 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; return;
} }
@ -296,14 +303,19 @@ void Launcher::requestUninstall(QString appId)
QString result = QString::fromUtf8(process.readAllStandardOutput()); QString result = QString::fromUtf8(process.readAllStandardOutput());
process.close(); process.close();
if (result != launcherExe) { if (result != launcherExe) {
qDebug() << result << " has no right to uninstall " << appId; qWarning() << result << " has no right to uninstall " << desktop;
return; 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()); DesktopInfo info(item.info.path.toStdString());
if (!info.isValidDesktop()) { 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; return;
} }
@ -436,29 +448,13 @@ void Launcher::onHandleUninstall(const QDBusMessage &message)
#ifdef QT_DEBUG #ifdef QT_DEBUG
qInfo() << "changedProps: " << changedProps << ", status: " << status; qInfo() << "changedProps: " << changedProps << ", status: " << status;
#endif #endif
const QString &appId = QString::fromStdString(m_appInfo.getId()); const QString &desktop = QString::fromStdString(m_appInfo.getFileName());
if (status == "succeed" || status == "end") { if (status == "succeed" || status == "end") {
// 移除desktop文件 removeDesktop(desktop);
Item appItem = Item(); removeAutoStart(desktop);
for (const Item &item : m_desktopAndItemMap) { Q_EMIT uninstallSuccess(desktop);
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);
} else if (status == "failed") { } else if (status == "failed") {
m_removeState = false; Q_EMIT uninstallFailed(desktop, QString());
QString msg = QString("uninstall %1 result %2").arg(m_appInfo.getName().c_str()).arg(false);
Q_EMIT uninstallFailed(appId, msg);
} }
} }
@ -693,6 +689,8 @@ void Launcher::loadNameMap()
*/ */
void Launcher::initItems() void Launcher::initItems()
{ {
itemsMap.clear();
m_desktopAndItemMap.clear();
std::vector<DesktopInfo> infos = AppsDir::getAllDesktopInfos(); std::vector<DesktopInfo> infos = AppsDir::getAllDesktopInfos();
for (auto &app : infos) { for (auto &app : infos) {
if (!app.isExecutableOk() if (!app.isExecutableOk()
@ -965,6 +963,11 @@ end:
return ty; return ty;
} }
bool Launcher::isLingLongApp(const QString &filePath)
{
return filePath.contains("/persistent/linglong");
}
/** /**
* @brief Launcher::doUninstall * @brief Launcher::doUninstall
* @param info * @param info
@ -973,46 +976,48 @@ end:
*/ */
void Launcher::doUninstall(DesktopInfo &info, const Item &item) void Launcher::doUninstall(DesktopInfo &info, const Item &item)
{ {
// 查询包名 if (isLingLongApp(QString::fromStdString(info.getFileName()))) {
QString pkg = queryPkgName(item.info.id, item.info.path); QProcess process;
if (pkg.isEmpty()) // 获取 appId
pkg = queryPkgNameWithDpkg(item.info.path); QStringList args;
QString appId = item.exec.section(' ', 2, 2);
args.append("uninstall");
args.append(appId);
if (pkg.isEmpty()) { int retCode = QProcess::execute("ll-cli", args);
qDebug() << "uninstall failed, becase package name is Empty"; if (retCode != 0) {
return; 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); QDBusReply<QDBusObjectPath> reply = lastoreDbus.call(QDBus::Block, "RemovePackage", name, pkg);
if (!reply.isValid() || reply.value().path().isEmpty()) { if (!reply.isValid() || reply.value().path().isEmpty()) {
qDebug() << "RemovePackage failed: " << reply.error(); qWarning() << "RemovePackage failed: " << reply.error();
return; return;
} }
@ -1106,27 +1111,20 @@ void Launcher::uninstallApp(const QString &name, const QString &pkg)
"PropertiesChanged","sa{sv}as", this, SLOT(onHandleUninstall(const QDBusMessage &))); "PropertiesChanged","sa{sv}as", this, SLOT(onHandleUninstall(const QDBusMessage &)));
} }
/** /** 移除desktop文件
* @brief Launcher::removeDesktop desktop文件 * @brief Launcher::removeDesktop
* @param item * @param desktop
* @return
*/ */
bool Launcher::removeDesktop(const Item &item) void Launcher::removeDesktop(const QString &desktop)
{ {
// 移除desktop文件 QFile file(desktop);
QFile file(item.info.path);
if (!file.exists()) { if (!file.exists()) {
qDebug() << "file not exist...item info: " << item.info; qDebug() << "file not exist...item info: " << desktop;
return false; return;
} }
bool ret = file.remove(); m_desktopAndItemMap.remove(desktop);
std::thread thread([ this, item, ret ] { file.remove();
notifyUninstallDone(item, ret);
});
thread.detach();
return ret;
} }
/** /**
@ -1138,21 +1136,33 @@ void Launcher::notifyUninstallDone(const Item &item, bool result)
{ {
QString msg; QString msg;
if (result) if (result)
msg = QString("%1 removed successfully").arg(item.info.name); msg = QString(tr("Removed successfully"));
else 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"); 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(desktop);
QFile file(filePath); 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); void setSynConfig(QByteArray ba);
QByteArray getSyncConfig(); QByteArray getSyncConfig();
void initItems();
const QMap<QString, Item> *getItems(); const QMap<QString, Item> *getItems();
int getDisplayMode(); int getDisplayMode();
@ -101,15 +103,15 @@ public:
bool isItemOnDesktop(QString appId); bool isItemOnDesktop(QString appId);
bool requestRemoveFromDesktop(QString appId); bool requestRemoveFromDesktop(QString appId);
bool requestSendToDesktop(QString appId); bool requestSendToDesktop(QString appId);
void requestUninstall(QString appId); void requestUninstall(const QString &desktop);
void setDisableScaling(QString appId, bool value); void setDisableScaling(QString appId, bool value);
void setUseProxy(QString appId, bool value); void setUseProxy(QString appId, bool value);
Q_SIGNALS: Q_SIGNALS:
void itemChanged(QString status, LauncherItemInfo itemInfo, qint64 ty); void itemChanged(QString status, LauncherItemInfo itemInfo, qint64 ty);
void newAppLaunched(QString appId); void newAppLaunched(QString appId);
void uninstallSuccess(QString appId); void uninstallSuccess(const QString &desktop);
void uninstallFailed(QString appId, QString errMsg); void uninstallFailed(const QString &desktop, QString errMsg);
void displayModeChanged(int mode); void displayModeChanged(int mode);
void fullScreenChanged(bool isFull); void fullScreenChanged(bool isFull);
@ -129,7 +131,6 @@ private:
void loadPkgCategoryMap(); void loadPkgCategoryMap();
void handleAppHiddenChanged(); void handleAppHiddenChanged();
void loadNameMap(); void loadNameMap();
void initItems();
QString getAppIdByFilePath(QString filePath, QStringList dirs); QString getAppIdByFilePath(QString filePath, QStringList dirs);
bool isDeepinCustomDesktopFile(QString fileName); bool isDeepinCustomDesktopFile(QString fileName);
Item NewItemWithDesktopInfo(DesktopInfo &info); Item NewItemWithDesktopInfo(DesktopInfo &info);
@ -141,13 +142,14 @@ private:
Item getItemByPath(QString itemPath); Item getItemByPath(QString itemPath);
void emitItemChanged(const Item *item, QString status); void emitItemChanged(const Item *item, QString status);
AppType getAppType(DesktopInfo &info, const Item &item); AppType getAppType(DesktopInfo &info, const Item &item);
bool isLingLongApp(const QString &filePath);
void doUninstall(DesktopInfo &info, const Item &item); void doUninstall(DesktopInfo &info, const Item &item);
void uninstallFlatpak(DesktopInfo &info, const Item &item); void uninstallFlatpak(DesktopInfo &info, const Item &item);
bool uninstallWineApp(const Item &item); bool uninstallWineApp(const Item &item);
void uninstallApp(const QString &name, const QString &pkg); 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 notifyUninstallDone(const Item &item, bool result);
void removeAutoStart(); void removeAutoStart(const QString &desktop);
private: private:
QMap<QString, Item> itemsMap; // appId, Item QMap<QString, Item> itemsMap; // appId, Item
@ -160,7 +162,6 @@ private:
QStringList appDirs; QStringList appDirs;
QMap<QString, Item> m_desktopAndItemMap; // desktoppath,Item QMap<QString, Item> m_desktopAndItemMap; // desktoppath,Item
bool m_removeState; // 卸载状态
DesktopInfo m_appInfo; // 卸载应用 DesktopInfo m_appInfo; // 卸载应用
}; };