File indexing completed on 2025-01-26 05:06:36
0001 /* 0002 SPDX-FileCopyrightText: 2023 Alexander Lohnau <alexander.lohnau@gmx.de> 0003 SPDX-License-Identifier: LGPL-2.0-or-later 0004 */ 0005 #include "KRunnerPlugininstallerRcJob.h" 0006 0007 #include "ScriptConfirmationDialog.h" 0008 #include <KDesktopFile> 0009 #include <QApplication> 0010 #include <QDebug> 0011 #include <QDir> 0012 #include <QFileInfo> 0013 0014 static QString installDBusServicePath(const QString &dbusService) 0015 { 0016 const QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); 0017 QDir dbusDir(dataLocation + "/dbus-1/services/"); 0018 dbusDir.mkpath((".")); 0019 return dbusDir.filePath(dbusService + ".service"); 0020 } 0021 0022 static QString installMetaDataPath(const QString &filePath) 0023 { 0024 const QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); 0025 QDir krunnerPluginsDir(dataLocation + "/krunner/dbusplugins/"); 0026 krunnerPluginsDir.mkpath((".")); 0027 // Get the filename in case the .krunner-plugininstallerrc has specified the file to be in a subdir 0028 return krunnerPluginsDir.filePath(QFileInfo(filePath).fileName()); 0029 } 0030 0031 static InstallerInfo getInstallerInfo(const QFileInfo &info) 0032 { 0033 const QDir rootDir = info.absoluteDir(); 0034 QString installerConfigFile = info.absoluteFilePath(); 0035 Q_ASSERT(installerConfigFile.endsWith("krunner-plugininstallerrc")); 0036 0037 KConfig cfg(installerConfigFile); 0038 KConfigGroup grp = cfg.group(QStringLiteral("")); 0039 const QString exec = grp.readEntry("Exec").replace(QStringLiteral("%{PROJECTDIR}"), info.absolutePath()); 0040 const QString metaDataFile = grp.readEntry("MetaDataFile"); 0041 KDesktopFile desktopFile(rootDir.absoluteFilePath(metaDataFile)); 0042 QString dbusService = desktopFile.desktopGroup().readEntry("X-Plasma-DBusRunner-Service"); 0043 0044 return {exec, dbusService, rootDir.absoluteFilePath(metaDataFile)}; 0045 } 0046 0047 void KRunnerPluginInstallerRcJob::executeOperation(const QFileInfo &fileInfo, const QString & /*mimeType*/, bool install) 0048 { 0049 const InstallerInfo info = getInstallerInfo(fileInfo); 0050 if (info.exec.isEmpty() || info.desktopFilePath.isEmpty() || info.desktopFilePath.isEmpty()) { 0051 Q_EMIT error("The provided installer file is invalid. Please contact the author."); 0052 return; 0053 } 0054 if (install) { 0055 if (m_skipConfirmDialog || ScriptConfirmationDialog(QString(), install, fileInfo.absolutePath(), info).exec() == QDialog::Accepted) { 0056 doInstall(info); 0057 } else { 0058 Q_EMIT error(QString()); 0059 } 0060 } else { 0061 doUninstall(info); 0062 } 0063 } 0064 0065 void KRunnerPluginInstallerRcJob::doInstall(const InstallerInfo &info) 0066 { 0067 QFile serviceFile(installDBusServicePath(info.dbusService)); 0068 0069 if (serviceFile.open(QIODevice::WriteOnly)) { 0070 serviceFile.write( 0071 QLatin1String("# autogenerated by krunner-plugininstaller\n[D-BUS Service]\nName=%1\nExec=%2\n").arg(info.dbusService, info.exec).toLocal8Bit()); 0072 serviceFile.close(); 0073 qInfo() << "Wrote autostart file" << serviceFile.fileName(); 0074 } else { 0075 Q_EMIT error(serviceFile.errorString()); 0076 return; 0077 } 0078 0079 const QString targetFilePath = installMetaDataPath(info.desktopFilePath); 0080 // In case we update an entry, simply remove a previous file 0081 if (QFileInfo::exists(targetFilePath)) { 0082 qInfo() << "Trying to remove old desktop file" << targetFilePath; 0083 QFile::remove(targetFilePath); 0084 } 0085 0086 if (!QFile::copy(info.desktopFilePath, targetFilePath)) { 0087 qWarning() << "Failed to copy " << info.desktopFilePath << targetFilePath; 0088 Q_EMIT error(i18n("Failed to copy file %1 to %2", info.desktopFilePath, targetFilePath)); 0089 } else { 0090 qInfo() << "Copied desktop file to" << targetFilePath; 0091 Q_EMIT finished(); 0092 } 0093 } 0094 void KRunnerPluginInstallerRcJob::doUninstall(const InstallerInfo &info) 0095 { 0096 QFile dbusFile(installDBusServicePath(info.dbusService)); 0097 QFile metaDataFile(installMetaDataPath(info.desktopFilePath)); 0098 0099 if (metaDataFile.remove()) { 0100 if (dbusFile.remove()) { 0101 Q_EMIT finished(); 0102 } else { 0103 Q_EMIT error(xi18nc("@info", "Failed to remove file %1:<nl/>%2", dbusFile.fileName(), dbusFile.errorString())); 0104 } 0105 } else { 0106 Q_EMIT error(xi18nc("@info", "Failed to remove file %1:<nl/>%2", metaDataFile.fileName(), metaDataFile.errorString())); 0107 } 0108 }