File indexing completed on 2024-04-14 05:29:59
0001 /* 0002 SPDX-FileCopyrightText: 2013 Reza Fatahilah Shah <rshah0385@kireihana.com> 0003 SPDX-FileCopyrightText: 2019 Filip Fila <filipfila.kde@gmail.com> 0004 SPDX-FileCopyrightText: 2020 David Redondo <kde@david-redondo.de> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "sddmkcm.h" 0010 0011 #include "config.h" 0012 #include "sddmdata.h" 0013 0014 #include "sessionmodel.h" 0015 0016 #include "usersmodel.h" 0017 0018 #include <QApplication> 0019 #include <QDir> 0020 0021 #include <KAuth/ExecuteJob> 0022 #include <KIO/ApplicationLauncherJob> 0023 #include <KLazyLocalizedString> 0024 #include <KLocalizedString> 0025 #include <KPluginFactory> 0026 #include <KService> 0027 #include <KUser> 0028 0029 K_PLUGIN_FACTORY_WITH_JSON(KCMSddmFactory, "kcm_sddm.json", registerPlugin<SddmKcm>(); registerPlugin<SddmData>();) 0030 0031 SddmKcm::SddmKcm(QObject *parent, const KPluginMetaData &metaData) 0032 : KQuickManagedConfigModule(parent, metaData) 0033 , m_data(new SddmData(this)) 0034 , m_themesModel(new ThemesModel(this)) 0035 { 0036 setAuthActionName(QStringLiteral("org.kde.kcontrol.kcmsddm.save")); 0037 0038 qmlRegisterUncreatableType<ThemesModel>("org.kde.private.kcms.sddm", 1, 0, "ThemesModel", QStringLiteral("Cannot create ThemesModel")); 0039 qmlRegisterType<UsersModel>("org.kde.private.kcms.sddm", 1, 0, "UsersModel"); 0040 qmlRegisterType<SessionModel>("org.kde.private.kcms.sddm", 1, 0, "SessionModel"); 0041 qmlRegisterAnonymousType<SddmSettings>("org.kde.private.kcms.sddm", 1); 0042 0043 connect(m_data->sddmSettings(), &SddmSettings::CurrentChanged, this, [this] { 0044 m_themesModel->setCurrentTheme(m_data->sddmSettings()->current()); 0045 }); 0046 m_themesModel->setCurrentTheme(m_data->sddmSettings()->current()); 0047 // Currently only emmited when background changes 0048 connect(m_themesModel, &QAbstractItemModel::dataChanged, this, [this] { 0049 this->setNeedsSave(true); 0050 }); 0051 } 0052 0053 SddmKcm::~SddmKcm() 0054 { 0055 } 0056 0057 SddmSettings *SddmKcm::sddmSettings() const 0058 { 0059 return m_data->sddmSettings(); 0060 } 0061 0062 ThemesModel *SddmKcm::themesModel() const 0063 { 0064 return m_themesModel; 0065 } 0066 0067 QString SddmKcm::toLocalFile(const QUrl &url) 0068 { 0069 return url.toLocalFile(); 0070 } 0071 0072 void SddmKcm::removeTheme(const QModelIndex &index) 0073 { 0074 const QString path = m_themesModel->data(index, ThemesModel::PathRole).toString(); 0075 KAuth::Action saveAction(QStringLiteral("org.kde.kcontrol.kcmsddm.uninstalltheme")); 0076 saveAction.setHelperId(QStringLiteral("org.kde.kcontrol.kcmsddm")); 0077 saveAction.addArgument(QStringLiteral("filePath"), path); 0078 auto job = saveAction.execute(); 0079 connect(job, &KJob::result, this, [this, job] { 0080 if (job->error()) { 0081 Q_EMIT errorOccured(job->errorString()); 0082 } else { 0083 m_themesModel->populate(); 0084 } 0085 }); 0086 job->start(); 0087 } 0088 0089 void SddmKcm::installTheme(const QUrl &url) 0090 { 0091 KAuth::Action saveAction(QStringLiteral("org.kde.kcontrol.kcmsddm.installtheme")); 0092 saveAction.setHelperId(QStringLiteral("org.kde.kcontrol.kcmsddm")); 0093 saveAction.addArgument(QStringLiteral("filePath"), url.toLocalFile()); 0094 auto job = saveAction.execute(); 0095 connect(job, &KJob::result, this, [this, job] { 0096 if (job->error()) { 0097 Q_EMIT errorOccured(job->errorString()); 0098 } else { 0099 m_themesModel->populate(); 0100 } 0101 }); 0102 job->start(); 0103 } 0104 0105 void SddmKcm::save() 0106 { 0107 QVariantMap args; 0108 0109 const QModelIndex currentThemeIndex = m_themesModel->index(m_themesModel->currentIndex()); 0110 const QString themeConfigPath = m_themesModel->data(currentThemeIndex, ThemesModel::PathRole).toString() 0111 + m_themesModel->data(currentThemeIndex, ThemesModel::ConfigFileRole).toString(); 0112 if (!themeConfigPath.isEmpty()) { 0113 args[QStringLiteral("theme.conf.user")] = QVariant(themeConfigPath + QStringLiteral(".user")); 0114 const QString backgroundPath = m_themesModel->data(currentThemeIndex, ThemesModel::CurrentBackgroundRole).toString(); 0115 if (!backgroundPath.isEmpty()) { 0116 args[QStringLiteral("theme.conf.user/General/background")] = backgroundPath; 0117 args[QStringLiteral("theme.conf.user/General/type")] = QStringLiteral("image"); 0118 } else { 0119 args[QStringLiteral("theme.conf.user/General/type")] = QStringLiteral("color"); 0120 } 0121 } 0122 args[QStringLiteral("kde_settings.conf/Theme/Current")] = currentThemeIndex.data(ThemesModel::IdRole); 0123 args[QStringLiteral("kde_settings.conf/Autologin/User")] = m_data->sddmSettings()->user(); 0124 args[QStringLiteral("kde_settings.conf/Autologin/Session")] = m_data->sddmSettings()->session(); 0125 args[QStringLiteral("kde_settings.conf/Autologin/Relogin")] = m_data->sddmSettings()->relogin(); 0126 args[QStringLiteral("kde_settings.conf/Users/MinimumUid")] = m_data->sddmSettings()->minimumUid(); 0127 args[QStringLiteral("kde_settings.conf/Users/MaximumUid")] = m_data->sddmSettings()->maximumUid(); 0128 args[QStringLiteral("kde_settings.conf/General/HaltCommand")] = m_data->sddmSettings()->haltCommand(); 0129 args[QStringLiteral("kde_settings.conf/General/RebootCommand")] = m_data->sddmSettings()->rebootCommand(); 0130 0131 KAuth::Action saveAction(authActionName()); 0132 saveAction.setHelperId(QStringLiteral("org.kde.kcontrol.kcmsddm")); 0133 saveAction.setArguments(args); 0134 0135 auto job = saveAction.execute(); 0136 connect(job, &KJob::result, this, [this, job] { 0137 if (job->error()) { 0138 Q_EMIT errorOccured(job->errorString()); 0139 } else { 0140 m_data->sddmSettings()->load(); 0141 } 0142 // Clarify enable or disable the Apply button. 0143 this->setNeedsSave(job->error()); 0144 }); 0145 job->start(); 0146 } 0147 0148 void SddmKcm::synchronizeSettings() 0149 { 0150 // initial check for sddm user; abort if user not present 0151 // we have to check with QString and isEmpty() instead of QDir and exists() because 0152 // QDir returns "." and true for exists() in the case of a non-existent user; 0153 QString sddmHomeDirPath = KUser("sddm").homeDir(); 0154 if (sddmHomeDirPath.isEmpty()) { 0155 Q_EMIT errorOccured(kli18n("Cannot proceed, user 'sddm' does not exist. Please check your SDDM install.").untranslatedText()); 0156 return; 0157 } 0158 0159 // read Plasma values 0160 KConfig cursorConfig(QStringLiteral("kcminputrc")); 0161 KConfigGroup cursorConfigGroup(&cursorConfig, "Mouse"); 0162 QVariant cursorTheme = cursorConfigGroup.readEntry("cursorTheme", QString()); 0163 QVariant cursorSize = cursorConfigGroup.readEntry("cursorSize", QString()); 0164 0165 KConfig dpiConfig(QStringLiteral("kcmfonts")); 0166 KConfigGroup dpiConfigGroup(&dpiConfig, "General"); 0167 QString dpiValue = dpiConfigGroup.readEntry("forceFontDPI"); 0168 QString dpiArgument = QStringLiteral("-dpi ") + dpiValue; 0169 0170 KConfig numLockConfig(QStringLiteral("kcminputrc")); 0171 KConfigGroup numLockConfigGroup(&numLockConfig, "Keyboard"); 0172 QString numLock = numLockConfigGroup.readEntry("NumLock"); 0173 0174 // Syncing the font only works with SDDM >= 0.19, but will not have a negative effect with older versions 0175 KConfig plasmaFontConfig(QStringLiteral("kdeglobals")); 0176 KConfigGroup plasmaFontGroup(&plasmaFontConfig, "General"); 0177 QString plasmaFont = plasmaFontGroup.readEntry("font", QApplication::font().toString()); 0178 0179 // define paths 0180 const QString fontconfigPath = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, QStringLiteral("fontconfig"), QStandardPaths::LocateDirectory); 0181 const QString kdeglobalsPath = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, QStringLiteral("kdeglobals")); 0182 const QString plasmarcPath = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, QStringLiteral("plasmarc")); 0183 const QString kcminputrcPath = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, QStringLiteral("kcminputrc")); 0184 0185 // send values and paths to helper, debug if it fails 0186 QVariantMap args; 0187 0188 args[QStringLiteral("kde_settings.conf")] = QString{QLatin1String(SDDM_CONFIG_DIR "/") + QStringLiteral("kde_settings.conf")}; 0189 0190 args[QStringLiteral("sddm.conf")] = QLatin1String(SDDM_CONFIG_FILE); 0191 0192 if (!cursorTheme.isNull()) { 0193 args[QStringLiteral("kde_settings.conf/Theme/CursorTheme")] = cursorTheme; 0194 } else { 0195 qDebug() << "Cannot find cursor theme value."; 0196 } 0197 if (!cursorSize.isNull()) { 0198 args[QStringLiteral("kde_settings.conf/Theme/CursorSize")] = cursorSize; 0199 } else { 0200 qDebug() << "Cannot find cursor size value."; 0201 } 0202 0203 if (!dpiValue.isEmpty()) { 0204 args[QStringLiteral("kde_settings.conf/X11/ServerArguments")] = dpiArgument; 0205 } else { 0206 qDebug() << "Cannot find scaling DPI value."; 0207 } 0208 0209 if (!numLock.isEmpty()) { 0210 if (numLock == QStringLiteral("0")) { 0211 args[QStringLiteral("kde_settings.conf/General/Numlock")] = QStringLiteral("on"); 0212 } else if (numLock == QStringLiteral("1")) { 0213 args[QStringLiteral("kde_settings.conf/General/Numlock")] = QStringLiteral("off"); 0214 } else if (numLock == QStringLiteral("2")) { 0215 args[QStringLiteral("kde_settings.conf/General/Numlock")] = QStringLiteral("none"); 0216 } 0217 } else { 0218 qDebug() << "Cannot find NumLock value."; 0219 } 0220 0221 if (!plasmaFont.isEmpty()) { 0222 args[QStringLiteral("kde_settings.conf/Theme/Font")] = plasmaFont; 0223 } else { 0224 qDebug() << "Cannot find Plasma font value."; 0225 } 0226 0227 if (!fontconfigPath.isEmpty()) { 0228 args[QStringLiteral("fontconfig")] = fontconfigPath; 0229 } else { 0230 qDebug() << "Cannot find fontconfig folder."; 0231 } 0232 0233 if (!kdeglobalsPath.isEmpty()) { 0234 args[QStringLiteral("kdeglobals")] = kdeglobalsPath; 0235 } else { 0236 qDebug() << "Cannot find kdeglobals file."; 0237 } 0238 0239 if (!plasmarcPath.isEmpty()) { 0240 args[QStringLiteral("plasmarc")] = plasmarcPath; 0241 } else { 0242 qDebug() << "Cannot find plasmarc file."; 0243 } 0244 0245 if (!kcminputrcPath.isEmpty()) { 0246 args[QStringLiteral("kcminputrc")] = kcminputrcPath; 0247 } else { 0248 qDebug() << "Cannot find kcminputrc file."; 0249 } 0250 0251 auto path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kscreen/", QStandardPaths::LocateDirectory); 0252 if (!path.isEmpty()) { 0253 args[QStringLiteral("kscreen-config")] = path; 0254 } 0255 0256 KAuth::Action syncAction(QStringLiteral("org.kde.kcontrol.kcmsddm.sync")); 0257 syncAction.setHelperId(QStringLiteral("org.kde.kcontrol.kcmsddm")); 0258 syncAction.setArguments(args); 0259 0260 auto job = syncAction.execute(); 0261 connect(job, &KJob::result, this, [this, job] { 0262 if (job->error()) { 0263 qDebug() << "Synchronization failed"; 0264 qDebug() << job->errorString(); 0265 qDebug() << job->errorText(); 0266 if (!job->errorText().isEmpty()) { 0267 Q_EMIT errorOccured(job->errorText()); 0268 } 0269 } else { 0270 qDebug() << "Synchronization successful"; 0271 Q_EMIT syncSuccessful(); 0272 } 0273 }); 0274 job->start(); 0275 } 0276 0277 void SddmKcm::resetSyncronizedSettings() 0278 { 0279 // initial check for sddm user; abort if user not present 0280 // we have to check with QString and isEmpty() instead of QDir and exists() because 0281 // QDir returns "." and true for exists() in the case of a non-existent user 0282 QString sddmHomeDirPath = KUser("sddm").homeDir(); 0283 if (sddmHomeDirPath.isEmpty()) { 0284 Q_EMIT errorOccured(kli18n("Cannot proceed, user 'sddm' does not exist. Please check your SDDM install.").untranslatedText()); 0285 return; 0286 } 0287 0288 // send paths to helper 0289 QVariantMap args; 0290 0291 args[QStringLiteral("kde_settings.conf")] = QStringLiteral(SDDM_CONFIG_DIR "/kde_settings.conf"); 0292 0293 args[QStringLiteral("sddm.conf")] = QLatin1String(SDDM_CONFIG_FILE); 0294 0295 args[QStringLiteral("kde_settings.conf/Theme/CursorTheme")] = QVariant(); 0296 0297 args[QStringLiteral("kde_settings.conf/Theme/CursorSize")] = QVariant(); 0298 0299 args[QStringLiteral("kde_settings.conf/X11/ServerArguments")] = QVariant(); 0300 0301 args[QStringLiteral("kde_settings.conf/General/Numlock")] = QVariant(); 0302 0303 args[QStringLiteral("kde_settings.conf/Theme/Font")] = QVariant(); 0304 0305 KAuth::Action resetAction(QStringLiteral("org.kde.kcontrol.kcmsddm.reset")); 0306 resetAction.setHelperId(QStringLiteral("org.kde.kcontrol.kcmsddm")); 0307 resetAction.setArguments(args); 0308 0309 auto job = resetAction.execute(); 0310 0311 connect(job, &KJob::result, this, [this, job] { 0312 if (job->error()) { 0313 qDebug() << "Reset failed"; 0314 qDebug() << job->errorString(); 0315 qDebug() << job->errorText(); 0316 if (!job->errorText().isEmpty()) { 0317 Q_EMIT errorOccured(job->errorText()); 0318 } 0319 } else { 0320 qDebug() << "Reset successful"; 0321 Q_EMIT resetSyncedDataSuccessful(); 0322 } 0323 }); 0324 job->start(); 0325 } 0326 0327 bool SddmKcm::KDEWalletAvailable() 0328 { 0329 return !QStandardPaths::findExecutable(QLatin1String("kwalletmanager5")).isEmpty(); 0330 } 0331 0332 void SddmKcm::openKDEWallet() 0333 { 0334 KService::Ptr kwalletmanagerService = KService::serviceByDesktopName(QStringLiteral("org.kde.kwalletmanager5")); 0335 auto *job = new KIO::ApplicationLauncherJob(kwalletmanagerService); 0336 job->start(); 0337 } 0338 0339 #include "sddmkcm.moc"