SPDX-FileCopyrightText: 2023 Alexander Lohnau <alexander.lohnau@gmx.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "KRunnerPlugininstallerRcJob.h"
#include "ScriptConfirmationDialog.h"
#include <KDesktopFile>
#include <QApplication>
#include <QDebug>
#include <QDir>
#include <QFileInfo>
static QString installDBusServicePath(const QString &dbusService)
{
const QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
QDir dbusDir(dataLocation + "/dbus-1/services/");
dbusDir.mkpath(("."));
return dbusDir.filePath(dbusService + ".service");
}
static QString installMetaDataPath(const QString &filePath)
{
const QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
QDir krunnerPluginsDir(dataLocation + "/krunner/dbusplugins/");
krunnerPluginsDir.mkpath(("."));
return krunnerPluginsDir.filePath(QFileInfo(filePath).fileName());
}
static InstallerInfo getInstallerInfo(const QFileInfo &info)
{
const QDir rootDir = info.absoluteDir();
QString installerConfigFile = info.absoluteFilePath();
Q_ASSERT(installerConfigFile.endsWith("krunner-plugininstallerrc"));
KConfig cfg(installerConfigFile);
KConfigGroup grp = cfg.group(QStringLiteral(""));
const QString exec = grp.readEntry("Exec").replace(QStringLiteral("%{PROJECTDIR}"), info.absolutePath());
const QString metaDataFile = grp.readEntry("MetaDataFile");
KDesktopFile desktopFile(rootDir.absoluteFilePath(metaDataFile));
QString dbusService = desktopFile.desktopGroup().readEntry("X-Plasma-DBusRunner-Service");
return {exec, dbusService, rootDir.absoluteFilePath(metaDataFile)};
}
void KRunnerPluginInstallerRcJob::executeOperation(const QFileInfo &fileInfo, const QString & , bool install)
{
const InstallerInfo info = getInstallerInfo(fileInfo);
if (info.exec.isEmpty() || info.desktopFilePath.isEmpty()) {
Q_EMIT error("The provided installer file is invalid. Please contact the author.");
return;
}
if (install) {
if (m_skipConfirmDialog || ScriptConfirmationDialog(QString(), install, fileInfo.absolutePath(), info).exec() == QDialog::Accepted) {
doInstall(info);
} else {
Q_EMIT error(QString());
}
} else {
doUninstall(info);
}
}
void KRunnerPluginInstallerRcJob::doInstall(const InstallerInfo &info)
{
QFile serviceFile(installDBusServicePath(info.dbusService));
if (serviceFile.open(QIODevice::WriteOnly)) {
serviceFile.write(
QLatin1String("# autogenerated by krunner-plugininstaller\n[D-BUS Service]\nName=%1\nExec=%2\n").arg(info.dbusService, info.exec).toLocal8Bit());
serviceFile.close();
qInfo() << "Wrote autostart file" << serviceFile.fileName();
} else {
Q_EMIT error(serviceFile.errorString());
return;
}
const QString targetFilePath = installMetaDataPath(info.desktopFilePath);
if (QFileInfo::exists(targetFilePath)) {
qInfo() << "Trying to remove old desktop file" << targetFilePath;
QFile::remove(targetFilePath);
}
if (!QFile::copy(info.desktopFilePath, targetFilePath)) {
qWarning() << "Failed to copy " << info.desktopFilePath << targetFilePath;
Q_EMIT error(i18n("Failed to copy file %1 to %2", info.desktopFilePath, targetFilePath));
} else {
qInfo() << "Copied desktop file to" << targetFilePath;
Q_EMIT finished();
}
}
void KRunnerPluginInstallerRcJob::doUninstall(const InstallerInfo &info)
{
QFile dbusFile(installDBusServicePath(info.dbusService));
QFile metaDataFile(installMetaDataPath(info.desktopFilePath));
if (metaDataFile.remove()) {
if (dbusFile.remove()) {
Q_EMIT finished();
} else {
Q_EMIT error(xi18nc("@info", "Failed to remove file %1:<nl/>%2", dbusFile.fileName(), dbusFile.errorString()));
}
} else {
Q_EMIT error(xi18nc("@info", "Failed to remove file %1:<nl/>%2", metaDataFile.fileName(), metaDataFile.errorString()));
}
}