File indexing completed on 2024-09-08 10:49:53
0001 /** 0002 * SPDX-FileCopyrightText: 2022 Suhaas Joshi <joshiesuhaas0@gmail.com> 0003 * SPDX-FileCopyrightText: 2023 ivan tkachenko <me@ratijas.tk> 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "flatpakreference.h" 0008 #include "flatpakhelper.h" 0009 0010 #ifdef FLATPAK_EXTERNC_REQUIRED 0011 extern "C" { 0012 #endif 0013 #include <flatpak/flatpak.h> 0014 #ifdef FLATPAK_EXTERNC_REQUIRED 0015 } 0016 #endif 0017 #include <glib.h> 0018 0019 #include <QDebug> 0020 0021 FlatpakReference::FlatpakReference(FlatpakReferencesModel *parent, 0022 const QString &flatpakName, 0023 const QString &arch, 0024 const QString &branch, 0025 const QString &version, 0026 const QString &displayName, 0027 const QUrl &iconSource, 0028 const QStringList &metadataAndOverridesFiles) 0029 : QObject(parent) 0030 , m_flatpakName(flatpakName) 0031 , m_arch(arch) 0032 , m_branch(branch) 0033 , m_version(version) 0034 , m_displayName(displayName) 0035 , m_iconSource(iconSource) 0036 , m_metadataAndOverridesFiles(metadataAndOverridesFiles) 0037 , m_permissionsModel(nullptr) 0038 { 0039 connect(this, &FlatpakReference::needsLoad, parent, &FlatpakReferencesModel::needsLoad); 0040 connect(this, &FlatpakReference::settingsChanged, parent, &FlatpakReferencesModel::settingsChanged); 0041 } 0042 0043 FlatpakReferencesModel *FlatpakReference::parent() const 0044 { 0045 // SAFETY: There's only one constructor, and it always initializes parent with a model object 0046 return qobject_cast<FlatpakReferencesModel *>(QObject::parent()); 0047 } 0048 0049 QString FlatpakReference::arch() const 0050 { 0051 return m_arch; 0052 } 0053 0054 QString FlatpakReference::branch() const 0055 { 0056 return m_branch; 0057 } 0058 0059 QString FlatpakReference::version() const 0060 { 0061 return m_version; 0062 } 0063 0064 QUrl FlatpakReference::iconSource() const 0065 { 0066 return m_iconSource; 0067 } 0068 0069 const QStringList &FlatpakReference::metadataAndOverridesFiles() const 0070 { 0071 return m_metadataAndOverridesFiles; 0072 } 0073 0074 QStringList FlatpakReference::defaultsFiles() const 0075 { 0076 QStringList defaults = m_metadataAndOverridesFiles; 0077 defaults.removeLast(); 0078 return defaults; 0079 } 0080 0081 const QString &FlatpakReference::userLevelPerAppOverrideFile() const 0082 { 0083 return m_metadataAndOverridesFiles.last(); 0084 } 0085 0086 QString FlatpakReference::displayName() const 0087 { 0088 /* sometimes, the application does not seem to have a display name, so return its id */ 0089 return m_displayName.isEmpty() ? m_flatpakName : m_displayName; 0090 } 0091 0092 QString FlatpakReference::flatpakName() const 0093 { 0094 // Reduced implementation of libdiscover, as this KCM lists only installed apps 0095 return m_flatpakName; 0096 } 0097 0098 QString FlatpakReference::ref() const 0099 { 0100 // KCM lists only apps 0101 return QStringLiteral("app/%1/%2/%3").arg(flatpakName(), arch(), branch()); 0102 } 0103 0104 FlatpakPermissionModel *FlatpakReference::permissionsModel() 0105 { 0106 return m_permissionsModel; 0107 } 0108 0109 void FlatpakReference::setPermissionsModel(FlatpakPermissionModel *model) 0110 { 0111 if (model != m_permissionsModel) { 0112 if (m_permissionsModel) { 0113 disconnect(m_permissionsModel, &FlatpakPermissionModel::referenceChanged, this, &FlatpakReference::needsLoad); 0114 disconnect(m_permissionsModel, &FlatpakPermissionModel::dataChanged, this, &FlatpakReference::settingsChanged); 0115 disconnect(m_permissionsModel, &FlatpakPermissionModel::rowsInserted, this, &FlatpakReference::settingsChanged); 0116 disconnect(m_permissionsModel, &FlatpakPermissionModel::rowsRemoved, this, &FlatpakReference::settingsChanged); 0117 } 0118 m_permissionsModel = model; 0119 if (m_permissionsModel) { 0120 connect(m_permissionsModel, &FlatpakPermissionModel::referenceChanged, this, &FlatpakReference::needsLoad); 0121 connect(m_permissionsModel, &FlatpakPermissionModel::dataChanged, this, &FlatpakReference::settingsChanged); 0122 connect(m_permissionsModel, &FlatpakPermissionModel::rowsInserted, this, &FlatpakReference::settingsChanged); 0123 connect(m_permissionsModel, &FlatpakPermissionModel::rowsRemoved, this, &FlatpakReference::settingsChanged); 0124 } 0125 } 0126 } 0127 0128 void FlatpakReference::load() 0129 { 0130 if (m_permissionsModel) { 0131 m_permissionsModel->load(); 0132 } 0133 } 0134 0135 void FlatpakReference::save() 0136 { 0137 if (m_permissionsModel) { 0138 m_permissionsModel->save(); 0139 } 0140 } 0141 0142 void FlatpakReference::defaults() 0143 { 0144 if (m_permissionsModel) { 0145 m_permissionsModel->defaults(); 0146 } 0147 } 0148 0149 bool FlatpakReference::isSaveNeeded() const 0150 { 0151 if (m_permissionsModel) { 0152 return m_permissionsModel->isSaveNeeded(); 0153 } 0154 return false; 0155 } 0156 0157 bool FlatpakReference::isDefaults() const 0158 { 0159 if (m_permissionsModel) { 0160 return m_permissionsModel->isDefaults(); 0161 } 0162 return true; 0163 } 0164 0165 static GPtrArray *getSystemInstalledFlatpakAppRefs() 0166 { 0167 g_autoptr(FlatpakInstallation) installation = flatpak_installation_new_system(nullptr, nullptr); 0168 GPtrArray *refs = flatpak_installation_list_installed_refs_by_kind(installation, FLATPAK_REF_KIND_APP, nullptr, nullptr); 0169 return refs; 0170 } 0171 0172 static GPtrArray *getUserInstalledFlatpakAppRefs() 0173 { 0174 g_autoptr(FlatpakInstallation) installation = flatpak_installation_new_user(nullptr, nullptr); 0175 GPtrArray *refs = flatpak_installation_list_installed_refs_by_kind(installation, FLATPAK_REF_KIND_APP, nullptr, nullptr); 0176 return refs; 0177 } 0178 0179 FlatpakReferencesModel::FlatpakReferencesModel(QObject *parent) 0180 : QAbstractListModel(parent) 0181 { 0182 g_autoptr(GPtrArray) systemInstalledRefs = getSystemInstalledFlatpakAppRefs(); 0183 g_autoptr(GPtrArray) userInstalledRefs = getUserInstalledFlatpakAppRefs(); 0184 0185 const auto systemOverridesDirectory = FlatpakHelper::systemOverridesDirectory(); 0186 const auto userOverridesDirectory = FlatpakHelper::userOverridesDirectory(); 0187 0188 const std::array installedRefs = std::array{systemInstalledRefs, userInstalledRefs}; 0189 for (const auto &refs : installedRefs) { 0190 for (uint i = 0; i < refs->len; ++i) { 0191 auto *ref = FLATPAK_REF(g_ptr_array_index(refs, i)); 0192 auto *iRef = FLATPAK_INSTALLED_REF(g_ptr_array_index(refs, i)); 0193 0194 const auto flatpakName = QString::fromUtf8(flatpak_ref_get_name(ref)); 0195 if (flatpakName.endsWith(QStringLiteral(".BaseApp"))) { 0196 continue; 0197 } 0198 0199 const auto arch = QString::fromUtf8(flatpak_ref_get_arch(ref)); 0200 const auto branch = QString::fromUtf8(flatpak_ref_get_branch(ref)); 0201 const auto version = QString::fromUtf8(flatpak_installed_ref_get_appdata_version(iRef)); 0202 const auto displayName = QString::fromUtf8(flatpak_installed_ref_get_appdata_name(iRef)); 0203 const auto appBaseDirectory = QString::fromUtf8(flatpak_installed_ref_get_deploy_dir(iRef)); 0204 const auto iconSource = FlatpakHelper::iconSourceUrl(displayName, flatpakName, appBaseDirectory); 0205 0206 const auto metadataPath = (refs == systemInstalledRefs) ? FlatpakHelper::metadataPathForSystemInstallation(flatpakName) 0207 : FlatpakHelper::metadataPathForUserInstallation(flatpakName); 0208 0209 const auto systemGlobalOverrides = QStringLiteral("%1/global").arg(systemOverridesDirectory); 0210 const auto systemAppOverrides = QStringLiteral("%1/%2").arg(systemOverridesDirectory, flatpakName); 0211 0212 const auto userGlobalOverrides = QStringLiteral("%1/global").arg(userOverridesDirectory); 0213 const auto userAppOverrides = QStringLiteral("%1/%2").arg(userOverridesDirectory, flatpakName); 0214 0215 const auto metadataAndOverridesFiles = QStringList({ 0216 metadataPath, 0217 systemGlobalOverrides, 0218 systemAppOverrides, 0219 userGlobalOverrides, 0220 userAppOverrides, 0221 }); 0222 0223 m_references.push_back(new FlatpakReference(this, flatpakName, arch, branch, version, displayName, iconSource, metadataAndOverridesFiles)); 0224 } 0225 } 0226 0227 std::sort(m_references.begin(), m_references.end(), [](const FlatpakReference *r1, const FlatpakReference *r2) { 0228 return r1->displayName() < r2->displayName(); 0229 }); 0230 } 0231 0232 int FlatpakReferencesModel::rowCount(const QModelIndex &parent) const 0233 { 0234 if (parent.isValid()) { 0235 return 0; 0236 } 0237 return m_references.count(); 0238 } 0239 0240 QVariant FlatpakReferencesModel::data(const QModelIndex &index, int role) const 0241 { 0242 if (!index.isValid()) { 0243 return QVariant(); 0244 } 0245 0246 switch (role) { 0247 case Roles::Name: 0248 return m_references.at(index.row())->displayName(); 0249 case Roles::Version: 0250 return m_references.at(index.row())->version(); 0251 case Roles::Icon: 0252 return m_references.at(index.row())->iconSource(); 0253 case Roles::Ref: 0254 return QVariant::fromValue<FlatpakReference *>(m_references.at(index.row())); 0255 } 0256 return QVariant(); 0257 } 0258 0259 QHash<int, QByteArray> FlatpakReferencesModel::roleNames() const 0260 { 0261 QHash<int, QByteArray> roles; 0262 roles[Roles::Name] = "name"; 0263 roles[Roles::Version] = "version"; 0264 roles[Roles::Icon] = "icon"; 0265 roles[Roles::Ref] = "ref"; 0266 return roles; 0267 } 0268 0269 void FlatpakReferencesModel::load(int index) 0270 { 0271 if (index >= 0 && index < m_references.length()) { 0272 m_references.at(index)->load(); 0273 } 0274 } 0275 0276 void FlatpakReferencesModel::save(int index) 0277 { 0278 if (index >= 0 && index < m_references.length()) { 0279 m_references.at(index)->save(); 0280 } 0281 } 0282 0283 void FlatpakReferencesModel::defaults(int index) 0284 { 0285 if (index >= 0 && index < m_references.length()) { 0286 m_references.at(index)->defaults(); 0287 } 0288 } 0289 0290 bool FlatpakReferencesModel::isSaveNeeded(int index) const 0291 { 0292 if (index >= 0 && index < m_references.length()) { 0293 return m_references.at(index)->isSaveNeeded(); 0294 } 0295 return false; 0296 } 0297 0298 bool FlatpakReferencesModel::isDefaults(int index) const 0299 { 0300 if (index >= 0 && index < m_references.length()) { 0301 return m_references.at(index)->isDefaults(); 0302 } 0303 return true; 0304 } 0305 0306 const QVector<FlatpakReference *> &FlatpakReferencesModel::references() const 0307 { 0308 return m_references; 0309 }