File indexing completed on 2024-04-28 05:36:11
0001 /* 0002 * SPDX-FileCopyrightText: 2017 Marco Martin <mart@kde.org> 0003 * SPDX-FileCopyrightText: 2014 Vishesh Handa <me@vhanda.in> 0004 * SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 * 0008 */ 0009 0010 #include "kcm.h" 0011 #include "config-kcm.h" 0012 0013 #include <chrono> 0014 0015 #include <KConfigGroup> 0016 #include <KLocalizedString> 0017 #include <KPluginFactory> 0018 #include <KSharedConfig> 0019 0020 #include <KAuth/Action> 0021 #include <KAuth/ExecuteJob> 0022 0023 #include <KIO/FileCopyJob> 0024 0025 using namespace std::chrono_literals; 0026 0027 K_PLUGIN_CLASS_WITH_JSON(KCMPlymouth, "kcm_plymouth.json") 0028 0029 KCMPlymouth::KCMPlymouth(QObject *parent, const KPluginMetaData &metaData) 0030 : KQuickConfigModule(parent, metaData) 0031 , m_model(new QStandardItemModel(this)) 0032 { 0033 qmlRegisterAnonymousType<QStandardItemModel>("KCMPlymouth", 1); 0034 qmlRegisterAnonymousType<KCMPlymouth>("KCMPlymouth", 1); 0035 setButtons(Apply); 0036 setAuthActionName(QStringLiteral("org.kde.kcontrol.kcmplymouth.save")); 0037 0038 m_model->setItemRoleNames({ 0039 {Qt::DisplayRole, QByteArrayLiteral("display")}, 0040 {DescriptionRole, QByteArrayLiteral("description")}, 0041 {PluginNameRole, QByteArrayLiteral("pluginName")}, 0042 {ScreenhotRole, QByteArrayLiteral("screenshot")}, 0043 {UninstallableRole, QByteArrayLiteral("uninstallable")}, 0044 }); 0045 } 0046 0047 KCMPlymouth::~KCMPlymouth() 0048 { 0049 } 0050 0051 void KCMPlymouth::reloadModel() 0052 { 0053 m_model->clear(); 0054 0055 QDir dir(QStringLiteral(PLYMOUTH_THEMES_DIR)); 0056 if (!dir.exists()) { 0057 return; 0058 } 0059 0060 KConfigGroup installedCg(KSharedConfig::openConfig(QStringLiteral("kplymouththemeinstallerrc")), QStringLiteral("DownloadedThemes")); 0061 0062 dir.setFilter(QDir::NoDotAndDotDot | QDir::Dirs); 0063 0064 const auto list = dir.entryInfoList(); 0065 for (const QFileInfo &fileInfo : list) { 0066 const QString pluginName = fileInfo.fileName(); 0067 QDir themeDir(fileInfo.filePath()); 0068 0069 KConfig file(themeDir.filePath(pluginName + QLatin1String(".plymouth")), KConfig::SimpleConfig); 0070 KConfigGroup grp = file.group(QStringLiteral("Plymouth Theme")); 0071 0072 QString displayName = grp.readEntry("Name", QString()); 0073 if (displayName.isEmpty()) { 0074 displayName = pluginName; 0075 } 0076 0077 QStandardItem *row = new QStandardItem(displayName); 0078 row->setData(pluginName, PluginNameRole); 0079 row->setData(grp.readEntry("Description", QString()), DescriptionRole); 0080 row->setData(installedCg.entryMap().contains(fileInfo.fileName()), UninstallableRole); 0081 0082 // the theme has a preview 0083 if (QFile::exists(themeDir.path() + QStringLiteral("/preview.png"))) { 0084 row->setData(QUrl::fromLocalFile(themeDir.path() + QStringLiteral("/preview.png")), ScreenhotRole); 0085 // fetch it downloaded from kns 0086 } else { 0087 const QString fileName = installedCg.readEntry(fileInfo.fileName(), QString()); 0088 if (fileName.isEmpty()) { 0089 row->setData(QString(), ScreenhotRole); 0090 } else { 0091 row->setData(QUrl::fromLocalFile(fileName + QStringLiteral(".png")), ScreenhotRole); 0092 } 0093 } 0094 0095 m_model->appendRow(row); 0096 } 0097 0098 Q_EMIT selectedPluginIndexChanged(); 0099 } 0100 0101 void KCMPlymouth::onEntryEvent(const KNSCore::Entry &entry) 0102 { 0103 static QStringList alreadyCopiedThumbnails; 0104 if (entry.isValid() && entry.status() == KNSCore::Entry::Installed && !alreadyCopiedThumbnails.contains(entry.uniqueId())) { 0105 alreadyCopiedThumbnails.append(entry.uniqueId()); 0106 KIO::file_copy(QUrl(entry.previewUrl(KNSCore::Entry::PreviewBig1)), 0107 QUrl::fromLocalFile(QString(entry.installedFiles().constFirst() + QStringLiteral(".png"))), 0108 -1, 0109 KIO::Overwrite | KIO::HideProgressInfo); 0110 } 0111 reloadModel(); 0112 } 0113 0114 QStandardItemModel *KCMPlymouth::themesModel() 0115 { 0116 return m_model; 0117 } 0118 0119 QString KCMPlymouth::selectedPlugin() const 0120 { 0121 return m_selectedPlugin; 0122 } 0123 0124 void KCMPlymouth::setSelectedPlugin(const QString &plugin) 0125 { 0126 if (m_selectedPlugin == plugin) { 0127 return; 0128 } 0129 0130 m_selectedPlugin = plugin; 0131 Q_EMIT selectedPluginChanged(); 0132 Q_EMIT selectedPluginIndexChanged(); 0133 0134 setNeedsSave(true); 0135 } 0136 0137 bool KCMPlymouth::busy() const 0138 { 0139 return m_busy; 0140 } 0141 0142 void KCMPlymouth::setBusy(const bool &busy) 0143 { 0144 if (m_busy == busy) { 0145 return; 0146 } 0147 0148 m_busy = busy; 0149 Q_EMIT busyChanged(); 0150 } 0151 0152 int KCMPlymouth::selectedPluginIndex() const 0153 { 0154 for (int i = 0; i < m_model->rowCount(); ++i) { 0155 if (m_model->data(m_model->index(i, 0), PluginNameRole).toString() == m_selectedPlugin) { 0156 return i; 0157 } 0158 } 0159 return -1; 0160 } 0161 0162 void KCMPlymouth::load() 0163 { 0164 reloadModel(); 0165 0166 KConfigGroup cg(KSharedConfig::openConfig(QStringLiteral(PLYMOUTH_CONFIG_PATH)), QStringLiteral("Daemon")); 0167 0168 setSelectedPlugin(cg.readEntry("Theme")); 0169 0170 setNeedsSave(false); 0171 } 0172 0173 void KCMPlymouth::save() 0174 { 0175 setBusy(true); 0176 QVariantMap helperargs; 0177 helperargs[QStringLiteral("theme")] = m_selectedPlugin; 0178 0179 KAuth::Action action(authActionName()); 0180 action.setHelperId(QStringLiteral("org.kde.kcontrol.kcmplymouth")); 0181 action.setArguments(helperargs); 0182 // We don't know how long this will take. The helper will need to generate N=installed_kernels initrds. 0183 // Be very generous with the timeout! https://bugs.kde.org/show_bug.cgi?id=400641 0184 // NB: there is also a timeout in the helper 0185 action.setTimeout(std::chrono::milliseconds(15min).count()); 0186 0187 KAuth::ExecuteJob *job = action.execute(); 0188 bool rc = job->exec(); 0189 if (!rc) { 0190 if (job->error() == KAuth::ActionReply::UserCancelledError) { 0191 Q_EMIT showErrorMessage(i18n("Unable to authenticate/execute the action: %1 (%2)", job->error(), job->errorString())); 0192 } 0193 load(); 0194 } 0195 setBusy(false); 0196 } 0197 0198 void KCMPlymouth::uninstall(const QString &plugin) 0199 { 0200 QVariantMap helperargs; 0201 helperargs[QStringLiteral("theme")] = plugin; 0202 0203 // KAuth::Action action(authActionName()); 0204 KAuth::Action action(QStringLiteral("org.kde.kcontrol.kcmplymouth.uninstall")); 0205 action.setHelperId(QStringLiteral("org.kde.kcontrol.kcmplymouth")); 0206 action.setArguments(helperargs); 0207 0208 KAuth::ExecuteJob *job = action.execute(); 0209 bool rc = job->exec(); 0210 if (!rc) { 0211 Q_EMIT showErrorMessage(i18n("Unable to authenticate/execute the action: %1 (%2)", job->error(), job->errorString())); 0212 } else { 0213 KConfigGroup installedCg(KSharedConfig::openConfig(QStringLiteral("kplymouththemeinstallerrc")), QStringLiteral("DownloadedThemes")); 0214 installedCg.deleteEntry(plugin); 0215 Q_EMIT showSuccessMessage(i18n("Theme uninstalled successfully.")); 0216 load(); 0217 } 0218 } 0219 0220 void KCMPlymouth::defaults() 0221 { /*TODO 0222 if (!) { 0223 return; 0224 } 0225 */ 0226 } 0227 0228 #include "kcm.moc" 0229 0230 #include "moc_kcm.cpp"