File indexing completed on 2023-09-24 04:14:57
0001 /* 0002 SPDX-FileCopyrightText: 2011 Aaron Seigo <aseigo@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "packagestructure.h" 0008 #include "debug_p.h" 0009 #include "private/package_p.h" 0010 #include "private/packagestructure_p.h" 0011 #include <QDebug> 0012 0013 #include <kpackage/packageloader.h> 0014 #include <kpackage/packagestructure.h> 0015 0016 #include <QVariantMap> 0017 0018 #include <KDesktopFile> 0019 #include <KJob> 0020 #include <QDBusConnection> 0021 #include <QDBusPendingCall> 0022 #include <QDir> 0023 #include <QFile> 0024 0025 namespace Plasma 0026 { 0027 QHash<KPackage::Package *, Plasma::Package *> PackageStructureWrapper::s_packagesMap; 0028 0029 PackageStructureWrapper::PackageStructureWrapper(Plasma::PackageStructure *structure, QObject *parent, const QVariantList &args) 0030 : KPackage::PackageStructure(parent, args) 0031 , m_struct(structure) 0032 { 0033 } 0034 0035 PackageStructureWrapper::~PackageStructureWrapper() 0036 { 0037 } 0038 0039 void PackageStructureWrapper::initPackage(KPackage::Package *package) 0040 { 0041 if (!m_struct || !s_packagesMap.contains(package)) { 0042 return; 0043 } 0044 0045 m_struct->initPackage(s_packagesMap.value(package)); 0046 } 0047 0048 void PackageStructureWrapper::pathChanged(KPackage::Package *package) 0049 { 0050 if (!m_struct || !s_packagesMap.contains(package)) { 0051 return; 0052 } 0053 0054 m_struct->pathChanged(s_packagesMap.value(package)); 0055 } 0056 0057 KJob *PackageStructureWrapper::install(KPackage::Package *package, const QString &archivePath, const QString &packageRoot) 0058 { 0059 if (!m_struct || !s_packagesMap.contains(package)) { 0060 return nullptr; 0061 } 0062 0063 return m_struct->install(s_packagesMap.value(package), archivePath, packageRoot); 0064 } 0065 0066 KJob *PackageStructureWrapper::uninstall(KPackage::Package *package, const QString &packageRoot) 0067 { 0068 if (!m_struct || !s_packagesMap.contains(package)) { 0069 return nullptr; 0070 } 0071 0072 return m_struct->uninstall(s_packagesMap.value(package), packageRoot); 0073 } 0074 0075 void PackageStructurePrivate::installPathChanged(const QString &path) 0076 { 0077 KJob *job = qobject_cast<KJob *>(q->sender()); 0078 if (!job || job->error()) { 0079 return; 0080 } 0081 0082 const QString servicePrefix = job->property("servicePrefix").toString(); 0083 const QString serviceName = job->property("serviceName").toString(); 0084 0085 // uninstall 0086 if (path.isEmpty()) { 0087 if (serviceName.isEmpty()) { 0088 return; 0089 } 0090 0091 QString service = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kservices5/") + serviceName; 0092 0093 bool ok = QFile::remove(service); 0094 if (!ok) { 0095 qCWarning(LOG_PLASMA) << "Unable to remove " << service; 0096 } 0097 0098 // install 0099 } else { 0100 if (!servicePrefix.isEmpty()) { 0101 // and now we register it as a service =) 0102 QString metaPath = path + QStringLiteral("/metadata.desktop"); 0103 KDesktopFile df(metaPath); 0104 KConfigGroup cg = df.desktopGroup(); 0105 const QString pluginName = cg.readEntry("X-KDE-PluginInfo-Name", QString()); 0106 0107 if (pluginName.isEmpty()) { 0108 return; 0109 } 0110 0111 // Q: should not installing it as a service disqualify it? 0112 // Q: i don't think so since KServiceTypeTrader may not be 0113 // used by the installing app in any case, and the 0114 // package is properly installed - aseigo 0115 0116 // TODO: remove installation of the desktop file in kservices5 when possible 0117 0118 const QString serviceName = servicePrefix + pluginName + QStringLiteral(".desktop"); 0119 0120 QString localServiceDirectory = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kservices5/"); 0121 if (!QDir().mkpath(localServiceDirectory)) { 0122 qCDebug(LOG_PLASMA) << "Failed to create ... " << localServiceDirectory; 0123 qCWarning(LOG_PLASMA) << "Could not create local service directory:" << localServiceDirectory; 0124 return; 0125 } 0126 QString service = localServiceDirectory + serviceName; 0127 0128 qCDebug(LOG_PLASMA) << "-- Copying " << metaPath << service; 0129 const bool ok = QFile::copy(metaPath, service); 0130 if (ok) { 0131 qCDebug(LOG_PLASMA) << "Copying metadata went ok."; 0132 // the icon in the installed file needs to point to the icon in the 0133 // installation dir! 0134 QString iconPath = path + QLatin1Char('/') + cg.readEntry("Icon"); 0135 QFile icon(iconPath); 0136 if (icon.exists()) { 0137 KDesktopFile df(service); 0138 KConfigGroup cg = df.desktopGroup(); 0139 cg.writeEntry("Icon", iconPath); 0140 } 0141 } else { 0142 qCWarning(LOG_PLASMA) << "Could not register package as service (this is not necessarily fatal):" << serviceName; 0143 } 0144 } 0145 } 0146 const auto call = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kded5"), 0147 QStringLiteral("/kbuildsycoca"), 0148 QStringLiteral("org.kde.kbuildsycoca"), 0149 QStringLiteral("recreate")); 0150 QDBusConnection::sessionBus().asyncCall(call); 0151 } 0152 0153 PackageStructure::PackageStructure(QObject *parent, const QVariantList &args) 0154 : QObject(parent) 0155 , d(new PackageStructurePrivate(this)) 0156 { 0157 if (!args.isEmpty() && args.first().canConvert<QString>()) { 0158 d->internalStructure = KPackage::PackageLoader::self()->loadPackageStructure(args.first().toString()); 0159 } 0160 0161 Q_UNUSED(args) 0162 } 0163 0164 PackageStructure::~PackageStructure() 0165 { 0166 delete d; 0167 } 0168 0169 void PackageStructure::initPackage(Package *package) 0170 { 0171 if (d->internalStructure && !qobject_cast<PackageStructureWrapper *>(d->internalStructure)) { 0172 d->internalStructure->initPackage(package->d->internalPackage); 0173 } 0174 } 0175 0176 void PackageStructure::pathChanged(Package *package) 0177 { 0178 if (d->internalStructure && !qobject_cast<PackageStructureWrapper *>(d->internalStructure)) { 0179 d->internalStructure->pathChanged(package->d->internalPackage); 0180 } 0181 } 0182 0183 KJob *PackageStructure::install(Package *package, const QString &archivePath, const QString &packageRoot) 0184 { 0185 if (d->internalStructure && !qobject_cast<PackageStructureWrapper *>(d->internalStructure)) { 0186 KJob *job = d->internalStructure->install(package->d->internalPackage, archivePath, packageRoot); 0187 if (job) { 0188 job->setProperty("servicePrefix", package->servicePrefix()); 0189 connect(job, SIGNAL(installPathChanged(QString)), this, SLOT(installPathChanged(QString))); 0190 } 0191 return job; 0192 } else if (d->internalStructure) { 0193 KJob *job = d->internalStructure->KPackage::PackageStructure::install(package->d->internalPackage, archivePath, packageRoot); 0194 connect(job, SIGNAL(installPathChanged(QString)), this, SLOT(installPathChanged(QString))); 0195 return job; 0196 } 0197 0198 return nullptr; 0199 } 0200 0201 KJob *PackageStructure::uninstall(Package *package, const QString &packageRoot) 0202 { 0203 if (d->internalStructure && !qobject_cast<PackageStructureWrapper *>(d->internalStructure)) { 0204 QString metaPath = package->path() + QStringLiteral("/metadata.desktop"); 0205 KDesktopFile df(metaPath); 0206 KConfigGroup cg = df.desktopGroup(); 0207 const QString pluginName = cg.readEntry("X-KDE-PluginInfo-Name", QString()); 0208 const QString serviceName = package->servicePrefix() + pluginName + QStringLiteral(".desktop"); 0209 0210 KJob *job = d->internalStructure->uninstall(package->d->internalPackage, packageRoot); 0211 if (job) { 0212 job->setProperty("serviceName", serviceName); 0213 0214 connect(job, SIGNAL(installPathChanged(QString)), this, SLOT(installPathChanged(QString))); 0215 } 0216 return job; 0217 } else if (d->internalStructure) { 0218 KJob *job = d->internalStructure->KPackage::PackageStructure::uninstall(package->d->internalPackage, packageRoot); 0219 connect(job, SIGNAL(installPathChanged(QString)), this, SLOT(installPathChanged(QString))); 0220 return job; 0221 } 0222 0223 return nullptr; 0224 } 0225 0226 } 0227 0228 #include "moc_packagestructure.cpp" 0229 #include "private/moc_packagestructure_p.cpp"