File indexing completed on 2024-11-17 04:55:41

0001 /*
0002  *   SPDX-FileCopyrightText: 2016 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
0003  *
0004  *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "LocalFilePKResource.h"
0008 #include "libdiscover_backend_debug.h"
0009 #include <PackageKit/Daemon>
0010 #include <PackageKit/Details>
0011 #include <QDebug>
0012 #include <QFileInfo>
0013 #include <QProcess>
0014 #include <utils.h>
0015 
0016 LocalFilePKResource::LocalFilePKResource(QUrl path, PackageKitBackend *parent)
0017     : PackageKitResource(path.toString(), path.toString(), parent)
0018     , m_path(std::move(path))
0019 {
0020 }
0021 
0022 quint64 LocalFilePKResource::size()
0023 {
0024     const QFileInfo info(m_path.toLocalFile());
0025     return info.size();
0026 }
0027 
0028 QString LocalFilePKResource::name() const
0029 {
0030     const QFileInfo info(m_path.toLocalFile());
0031     return info.baseName();
0032 }
0033 
0034 QString LocalFilePKResource::comment()
0035 {
0036     return m_path.toLocalFile();
0037 }
0038 
0039 QString LocalFilePKResource::origin() const
0040 {
0041     return m_path.toLocalFile();
0042 }
0043 
0044 void LocalFilePKResource::fetchDetails()
0045 {
0046     if (!m_details.isEmpty()) {
0047         return;
0048     }
0049     m_details.insert(QStringLiteral("fetching"), true); // we add an entry so it's not re-fetched.
0050 
0051     if (PackageKit::Daemon::roles() & PackageKit::Transaction::RoleGetDetailsLocal) {
0052         PackageKit::Transaction *transaction = PackageKit::Daemon::getDetailsLocal(m_path.toLocalFile());
0053         connect(transaction, &PackageKit::Transaction::details, this, &LocalFilePKResource::resolve);
0054         connect(transaction, &PackageKit::Transaction::errorCode, this, &PackageKitResource::failedFetchingDetails);
0055     }
0056 
0057     if (PackageKit::Daemon::roles() & PackageKit::Transaction::RoleGetFilesLocal) {
0058         PackageKit::Transaction *transaction2 = PackageKit::Daemon::getFilesLocal(m_path.toLocalFile());
0059         connect(transaction2, &PackageKit::Transaction::errorCode, this, &PackageKitResource::failedFetchingDetails);
0060         connect(transaction2, &PackageKit::Transaction::files, this, [this](const QString & /*pkgid*/, const QStringList &files) {
0061             const auto execIdx = kIndexOf(files, [](const QString &file) {
0062                 return file.endsWith(QLatin1String(".desktop")) && file.contains(QLatin1String("usr/share/applications"));
0063             });
0064             if (execIdx >= 0) {
0065                 m_exec = files[execIdx];
0066 
0067                 // sometimes aptcc provides paths like usr/share/applications/steam.desktop
0068                 if (!m_exec.startsWith(QLatin1Char('/'))) {
0069                     m_exec.prepend(QLatin1Char('/'));
0070                 }
0071             } else {
0072                 qWarning() << "could not find an executable desktop file for" << m_path << "among" << files;
0073             }
0074         });
0075     }
0076 }
0077 
0078 void LocalFilePKResource::resolve(const PackageKit::Details &inDetails)
0079 {
0080     clearPackageIds();
0081     const PackageKit::Details details = inDetails.isEmpty() ? m_details : inDetails;
0082     const auto detailsPackageId = details.packageId();
0083     auto resolve = PackageKit::Daemon::resolve(PackageKit::Daemon::packageName(detailsPackageId), PackageKit::Transaction::FilterNone);
0084 
0085     connect(resolve, &PackageKit::Transaction::package, this, [this, detailsPackageId](PackageKit::Transaction::Info info, const QString &packageId) {
0086         if (PackageKit::Daemon::packageName(packageId) == PackageKit::Daemon::packageName(detailsPackageId)
0087             && PackageKit::Daemon::packageVersion(packageId) == PackageKit::Daemon::packageVersion(detailsPackageId)
0088             && PackageKit::Daemon::packageArch(packageId) == PackageKit::Daemon::packageArch(detailsPackageId)
0089             && info == PackageKit::Transaction::InfoInstalled) {
0090             addPackageId(info, packageId, true);
0091         }
0092     });
0093     connect(resolve, &PackageKit::Transaction::finished, this, [this, details, detailsPackageId] {
0094         addPackageId(PackageKit::Transaction::InfoAvailable, detailsPackageId, true);
0095         PackageKitResource::setDetails(details);
0096     });
0097 }
0098 
0099 void LocalFilePKResource::invokeApplication() const
0100 {
0101     KService::Ptr service = KService::Ptr(new KService(m_exec));
0102 
0103     if (!service) {
0104         return;
0105     }
0106 
0107     runService(service);
0108 }