sddmkcm.cpp 12 KB
Newer Older
Reza Shah's avatar
Reza Shah committed
1
2
/*
    Copyright 2013 by Reza Fatahilah Shah <rshah0385@kireihana.com>
David Redondo's avatar
David Redondo committed
3
4
    Copyright 2019 Filip Fila <filipfila.kde@gmail.com>
    Copyright 2020 David Redondo <kde@david-redondo.de>
Filip Fila's avatar
Filip Fila committed
5

Reza Shah's avatar
Reza Shah committed
6
7
8
9
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.
Filip Fila's avatar
Filip Fila committed
10

Reza Shah's avatar
Reza Shah committed
11
12
13
14
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
Filip Fila's avatar
Filip Fila committed
15

Reza Shah's avatar
Reza Shah committed
16
17
18
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
David Redondo's avatar
David Redondo committed
19
20


Reza Shah's avatar
Reza Shah committed
21
22
#include "sddmkcm.h"

David Redondo's avatar
David Redondo committed
23
24
25
26
27
28
#include "config.h"
#include "sddmdata.h"
#include "sddmsettings.h"
#include "sessionmodel.h"
#include "themesmodel.h"
#include "usersmodel.h"
29
30

#include <QDir>
Reza Shah's avatar
Reza Shah committed
31

David Edmundson's avatar
David Edmundson committed
32
#include <KAboutData>
Laurent Montel's avatar
Laurent Montel committed
33
#include <KAuthExecuteJob>
Reza Shah's avatar
Reza Shah committed
34
#include <KLocalizedString>
Filip Fila's avatar
Filip Fila committed
35
#include <KPluginFactory>
David Redondo's avatar
David Redondo committed
36
#include <KUser>
David Edmundson's avatar
David Edmundson committed
37

David Redondo's avatar
David Redondo committed
38
K_PLUGIN_FACTORY_WITH_JSON(KCMSddmFactory, "kcm_sddm.json", registerPlugin<SddmKcm>(); registerPlugin<SddmData>();)
39

David Redondo's avatar
David Redondo committed
40
41
42
43
SddmKcm::SddmKcm(QObject *parent, const QVariantList &args)
    : KQuickAddons::ManagedConfigModule(parent, args)
    , m_data(new SddmData(this))
    , m_themesModel(new ThemesModel(this))
Reza Shah's avatar
Reza Shah committed
44
{
Nate Graham's avatar
Nate Graham committed
45
    KAboutData* aboutData = new KAboutData(QStringLiteral("kcm_sddm"), i18n("Login Screen (SDDM)"), QStringLiteral(PROJECT_VERSION));
Reza Shah's avatar
Reza Shah committed
46

David Edmundson's avatar
David Edmundson committed
47
48
    aboutData->setShortDescription(i18n("Login screen using the SDDM"));
    aboutData->setLicense(KAboutLicense::GPL_V2);
49
50
51
    aboutData->setHomepage(QStringLiteral("https://projects.kde.org/projects/kde/workspace/sddm-kcm"));
    aboutData->addAuthor(QStringLiteral("Reza Fatahilah Shah"), i18n("Author"), QStringLiteral("rshah0385@kireihana.com"));
    aboutData->addAuthor(QStringLiteral("David Edmundson"), i18n("Author"), QStringLiteral("davidedmundson@kde.org"));
David Redondo's avatar
David Redondo committed
52
    aboutData->addAuthor(QStringLiteral("David Redondo"), i18n("Author"), QStringLiteral("kde@david-redondo.de"));
53

David Edmundson's avatar
David Edmundson committed
54
    setAboutData(aboutData);
David Redondo's avatar
David Redondo committed
55
    setAuthActionName(QStringLiteral("org.kde.kcontrol.kcmsddm.save"));
56

David Redondo's avatar
David Redondo committed
57
58
59
60
    qmlRegisterUncreatableType<ThemesModel>("org.kde.private.kcms.sddm", 1, 0, "ThemesModel", QStringLiteral("Cannot create ThemesModel"));
    qmlRegisterType<UsersModel>("org.kde.private.kcms.sddm", 1, 0, "UsersModel");
    qmlRegisterType<SessionModel>("org.kde.private.kcms.sddm", 1, 0, "SessionModel");
    qmlRegisterAnonymousType<SddmSettings>("org.kde.private.kcms.sddm", 1);
61

David Redondo's avatar
David Redondo committed
62
63
64
65
66
    connect(m_data->sddmSettings(), &SddmSettings::CurrentChanged, this, [this] {
        m_themesModel->setCurrentTheme(m_data->sddmSettings()->current());
    });
    m_themesModel->setCurrentTheme(m_data->sddmSettings()->current());
}
67

David Redondo's avatar
David Redondo committed
68
69
70
SddmKcm::~SddmKcm()
{
}
71

David Redondo's avatar
David Redondo committed
72
73
74
75
SddmSettings* SddmKcm::sddmSettings() const
{
    return m_data->sddmSettings();
}
76

David Redondo's avatar
David Redondo committed
77
78
79
ThemesModel* SddmKcm::themesModel() const
{
    return m_themesModel;
Reza Shah's avatar
Reza Shah committed
80
81
}

David Redondo's avatar
David Redondo committed
82
QString SddmKcm::toLocalFile(const QUrl& url)
Reza Shah's avatar
Reza Shah committed
83
{
David Redondo's avatar
David Redondo committed
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
    return url.toLocalFile();
}

void SddmKcm::removeTheme(const QModelIndex &index)
{
    const QString path = m_themesModel->data(index, ThemesModel::PathRole).toString();
    KAuth::Action saveAction(QStringLiteral("org.kde.kcontrol.kcmsddm.uninstalltheme"));
    saveAction.setHelperId(QStringLiteral("org.kde.kcontrol.kcmsddm"));
    saveAction.addArgument(QStringLiteral("filePath"), path);
    auto job = saveAction.execute();
    connect(job, &KJob::result, this, [this, job] {
        if (job->error()) {
            Q_EMIT errorOccured(job->errorString());
        } else {
            m_themesModel->populate();
        }
    });
    job->start();
}

void SddmKcm::installTheme(const QUrl &url)
{
    KAuth::Action saveAction(QStringLiteral("org.kde.kcontrol.kcmsddm.installtheme"));
    saveAction.setHelperId(QStringLiteral("org.kde.kcontrol.kcmsddm"));
    saveAction.addArgument(QStringLiteral("filePath"), url.toLocalFile());
    auto job = saveAction.execute();
    connect(job, &KJob::result, this, [this, job] {
        if (job->error()) {
            Q_EMIT errorOccured(job->errorString());
        } else {
            m_themesModel->populate();
        }
    });
    job->start();
Reza Shah's avatar
Reza Shah committed
118
119
120
121
122
}

void SddmKcm::save()
{
    QVariantMap args;
Filip Fila's avatar
Filip Fila committed
123

David Redondo's avatar
David Redondo committed
124
125
126
127
128
129
130
131
132
133
134
135
    const QModelIndex currentThemeIndex = m_themesModel->index(m_themesModel->currentIndex());
    const QString themeConfigPath = m_themesModel->data(currentThemeIndex, ThemesModel::PathRole).toString()
        + m_themesModel->data(currentThemeIndex, ThemesModel::ConfigFileRole).toString();
    if (!themeConfigPath.isEmpty()) {
        args[QStringLiteral("theme.conf.user")] = QVariant(themeConfigPath + QStringLiteral(".user"));
        const QString backgroundPath = m_themesModel->data(currentThemeIndex, ThemesModel::CurrentBackgroundRole).toString();
        if (!backgroundPath.isEmpty()) {
            args[QStringLiteral("theme.conf.user/General/background")] = backgroundPath;
            args[QStringLiteral("theme.conf.user/General/type")] = QStringLiteral("image");
        } else {
             args[QStringLiteral("theme.conf.user/General/type")] = QStringLiteral("color");
        }
136
    }
David Redondo's avatar
David Redondo committed
137
138
139
140
141
142
143
144
145
146
    args[QStringLiteral("kde_settings.conf/Theme/Current")] = currentThemeIndex.data(ThemesModel::IdRole);
    args[QStringLiteral("kde_settings.conf/Autologin/User")] = m_data->sddmSettings()->user();
    args[QStringLiteral("kde_settings.conf/Autologin/Session")] = m_data->sddmSettings()->session();
    args[QStringLiteral("kde_settings.conf/Autologin/Relogin")] = m_data->sddmSettings()->relogin();
    args[QStringLiteral("kde_settings.conf/Users/MinimumUid")] = m_data->sddmSettings()->minimumUid();
    args[QStringLiteral("kde_settings.conf/Users/MaximumUid")] = m_data->sddmSettings()->maximumUid();
    args[QStringLiteral("kde_settings.conf/General/HaltCommand")] = m_data->sddmSettings()->haltCommand();
    args[QStringLiteral("kde_settings.conf/General/RebootCommand")] =  m_data->sddmSettings()->rebootCommand();

    KAuth::Action saveAction(authActionName());
147
    saveAction.setHelperId(QStringLiteral("org.kde.kcontrol.kcmsddm"));
Reza Shah's avatar
Reza Shah committed
148
    saveAction.setArguments(args);
Filip Fila's avatar
Filip Fila committed
149

David Edmundson's avatar
David Edmundson committed
150
    auto job = saveAction.execute();
David Redondo's avatar
David Redondo committed
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
    connect(job, &KJob::result, this, [this, job] {
        if (job->error()) {
            Q_EMIT errorOccured(job->errorString());
        } else {
            m_data->sddmSettings()->load();
        }
    });
    job->start();
}

void SddmKcm::synchronizeSettings()
{
     // initial check for sddm user; abort if user not present
    // we have to check with QString and isEmpty() instead of QDir and exists() because
    // QDir returns "." and true for exists() in the case of a non-existent user;
    QString sddmHomeDirPath = KUser("sddm").homeDir();
    if (sddmHomeDirPath.isEmpty()) {
        Q_EMIT errorOccured(QStringLiteral("Cannot proceed, user 'sddm' does not exist. Please check your SDDM install."));
        return;
Reza Shah's avatar
Reza Shah committed
170
    }
Filip Fila's avatar
Filip Fila committed
171

David Redondo's avatar
David Redondo committed
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    // read Plasma values
    KConfig cursorConfig(QStringLiteral("kcminputrc"));
    KConfigGroup cursorConfigGroup(&cursorConfig, "Mouse");
    QVariant cursorTheme = cursorConfigGroup.readEntry("cursorTheme", QString());

    KConfig dpiConfig(QStringLiteral("kcmfonts"));
    KConfigGroup dpiConfigGroup(&dpiConfig, "General");
    QString dpiValue = dpiConfigGroup.readEntry("forceFontDPI");
    QString dpiArgument = QStringLiteral("-dpi ") + dpiValue;

    KConfig numLockConfig(QStringLiteral("kcminputrc"));
    KConfigGroup numLockConfigGroup(&numLockConfig, "Keyboard");
    QString numLock = numLockConfigGroup.readEntry("NumLock");

    // define paths
    const QString fontconfigPath = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, QStringLiteral("fontconfig"), QStandardPaths::LocateDirectory);
    const QString kdeglobalsPath = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, QStringLiteral("kdeglobals"));
    const QString plasmarcPath = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, QStringLiteral("plasmarc"));

    // send values and paths to helper, debug if it fails
    QVariantMap args;

    args[QStringLiteral("kde_settings.conf")] = QString {QLatin1String(SDDM_CONFIG_DIR "/") + QStringLiteral("kde_settings.conf")};

    args[QStringLiteral("sddm.conf")] = QLatin1String(SDDM_CONFIG_FILE);

    if (!cursorTheme.isNull()) {
        args[QStringLiteral("kde_settings.conf/Theme/CursorTheme")] = cursorTheme;
    }
    else {
        qDebug() << "Cannot find cursor theme value.";
    }

    if (!dpiValue.isEmpty()) {
        args[QStringLiteral("kde_settings.conf/X11/ServerArguments")] = dpiArgument;
    }
    else {
        qDebug() << "Cannot find scaling DPI value.";
    }

    if (!numLock.isEmpty()) {
        if (numLock == QStringLiteral("0")) {
            args[QStringLiteral("kde_settings.conf/General/Numlock")] = QStringLiteral("on");
        }
        else if (numLock == QStringLiteral("1")) {
            args[QStringLiteral("kde_settings.conf/General/Numlock")] = QStringLiteral("off");
        }
        else if (numLock == QStringLiteral("2")) {
            args[QStringLiteral("kde_settings.conf/General/Numlock")] = QStringLiteral("none");
        }
    }
    else {
        qDebug() << "Cannot find NumLock value.";
    }

    if (!fontconfigPath.isEmpty()) {
        args[QStringLiteral("fontconfig")] = fontconfigPath;
    }
    else {
        qDebug() << "Cannot find fontconfig folder.";
    }

    if (!kdeglobalsPath.isEmpty()) {
        args[QStringLiteral("kdeglobals")] = kdeglobalsPath;
    }
    else {
        qDebug() << "Cannot find kdeglobals file.";
    }

    if (!plasmarcPath.isEmpty()) {
        args[QStringLiteral("plasmarc")] = plasmarcPath;
    }
    else {
        qDebug() << "Cannot find plasmarc file.";
    }

    KAuth::Action syncAction(QStringLiteral("org.kde.kcontrol.kcmsddm.sync"));
    syncAction.setHelperId(QStringLiteral("org.kde.kcontrol.kcmsddm"));
    syncAction.setArguments(args);

    auto job = syncAction.execute();
    connect(job, &KJob::result, this, [this, job] {
        if (job->error()){
            qDebug() << "Synchronization failed";
            qDebug() << job->errorString();
            qDebug() << job->errorText();
            if (!job->errorText().isEmpty()) {
                Q_EMIT errorOccured(job->errorText());
            }
        } else {
            qDebug() << "Synchronization successful";
        }
    });
    job->start();
Reza Shah's avatar
Reza Shah committed
266
267
}

David Redondo's avatar
David Redondo committed
268
void SddmKcm::resetSyncronizedSettings()
Reza Shah's avatar
Reza Shah committed
269
{
David Redondo's avatar
David Redondo committed
270
271
272
273
274
275
276
277
278
279
280
281
282
    // initial check for sddm user; abort if user not present
    // we have to check with QString and isEmpty() instead of QDir and exists() because
    // QDir returns "." and true for exists() in the case of a non-existent user
    QString sddmHomeDirPath = KUser("sddm").homeDir();
    if (sddmHomeDirPath.isEmpty()) {
        Q_EMIT errorOccured(QStringLiteral("Cannot proceed, user 'sddm' does not exist. Please check your SDDM install."));
        return;
    }

    // send paths to helper
    QVariantMap args;

    args[QStringLiteral("kde_settings.conf")] = QString {QLatin1String(SDDM_CONFIG_DIR "/") + QStringLiteral("kde_settings.conf")};
Filip Fila's avatar
Filip Fila committed
283

David Redondo's avatar
David Redondo committed
284
    args[QStringLiteral("sddm.conf")] = QLatin1String(SDDM_CONFIG_FILE);
Filip Fila's avatar
Filip Fila committed
285

David Redondo's avatar
David Redondo committed
286
    args[QStringLiteral("kde_settings.conf/Theme/CursorTheme")] = QVariant();
Filip Fila's avatar
Filip Fila committed
287

David Redondo's avatar
David Redondo committed
288
    args[QStringLiteral("kde_settings.conf/X11/ServerArguments")] = QVariant();
Filip Fila's avatar
Filip Fila committed
289

David Redondo's avatar
David Redondo committed
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
    args[QStringLiteral("kde_settings.conf/General/Numlock")] = QVariant();

    KAuth::Action resetAction(QStringLiteral("org.kde.kcontrol.kcmsddm.reset"));
    resetAction.setHelperId(QStringLiteral("org.kde.kcontrol.kcmsddm"));
    resetAction.setArguments(args);

    auto job = resetAction.execute();

    connect(job, &KJob::result, this, [this, job] {
        if (job->error()){
            qDebug() << "Reset failed";
            qDebug() << job->errorString();
            qDebug() << job->errorText();
            if (!job->errorText().isEmpty()) {
                Q_EMIT errorOccured(job->errorText());
            }
        } else {
            qDebug() << "Reset successful";
        }
    });
    job->start();
David Edmundson's avatar
David Edmundson committed
311
}
David Edmundson's avatar
David Edmundson committed
312

David Redondo's avatar
David Redondo committed
313

David Edmundson's avatar
David Edmundson committed
314
#include "sddmkcm.moc"