File indexing completed on 2024-04-21 05:36:33

0001 /*
0002  * SPDX-FileCopyrightText: 2013 Abdurrahman AVCI <abdurrahmanavci@gmail.com>
0003  * SPDX-License-Identifier: GPL-2.0-or-later
0004  */
0005 #include "sessionmodel.h"
0006 #include "config.h"
0007 
0008 #include <memory>
0009 
0010 #include <QDir>
0011 #include <QFile>
0012 #include <QList>
0013 #include <QTextStream>
0014 
0015 #include <KLocalizedString>
0016 
0017 class Session
0018 {
0019 public:
0020     QString file;
0021     QString name;
0022     QString exec;
0023     QString comment;
0024 };
0025 
0026 typedef std::shared_ptr<Session> SessionPtr;
0027 
0028 class SessionModelPrivate
0029 {
0030 public:
0031     int lastIndex{0};
0032     QList<SessionPtr> sessions;
0033 };
0034 
0035 SessionModel::SessionModel(QObject *parent)
0036     : QAbstractListModel(parent)
0037     , d(new SessionModelPrivate())
0038 {
0039     loadDir(QStringLiteral(XSESSIONS_DIR), SessionTypeX);
0040     loadDir(QStringLiteral(WAYLAND_SESSIONS_DIR), SessionTypeWayland);
0041 }
0042 
0043 SessionModel::~SessionModel()
0044 {
0045     delete d;
0046 }
0047 
0048 void SessionModel::loadDir(const QString &path, SessionType type)
0049 {
0050     QDir dir(path);
0051     dir.setNameFilters(QStringList() << QStringLiteral("*.desktop"));
0052     dir.setFilter(QDir::Files);
0053     // read session
0054     foreach (const QString &session, dir.entryList()) {
0055         QFile inputFile(dir.absoluteFilePath(session));
0056         if (!inputFile.open(QIODevice::ReadOnly)) {
0057             continue;
0058         }
0059         SessionPtr si{new Session{session.chopped(strlen(".desktop")), QString(), QString(), QString()}};
0060         bool isHidden = false;
0061         QString current_section;
0062         QTextStream in(&inputFile);
0063         while (!in.atEnd()) {
0064             QString line = in.readLine();
0065 
0066             if (line.startsWith(QLatin1String("["))) {
0067                 // The section name ends before the last ] before the start of a comment
0068                 int end = line.lastIndexOf(QLatin1Char(']'), line.indexOf(QLatin1Char('#')));
0069                 if (end != -1) {
0070                     current_section = line.mid(1, end - 1);
0071                 }
0072             }
0073 
0074             if (current_section != QLatin1String("Desktop Entry")) {
0075                 continue; // We are only interested in the "Desktop Entry" section
0076             }
0077 
0078             if (line.startsWith(QLatin1String("Name="))) {
0079                 si->name = line.mid(5);
0080                 if (type == SessionTypeWayland) {
0081                     // we want to exactly match the SDDM prompt which is formatted in this way
0082                     // with the exact same check
0083                     if (!si->name.endsWith(QLatin1String(" (Wayland)"))) {
0084                         si->name = i18nc("%1 is the name of a session", "%1 (Wayland)", si->name);
0085                     }
0086                 }
0087             }
0088             if (line.startsWith(QLatin1String("Exec="))) {
0089                 si->exec = line.mid(5);
0090             }
0091             if (line.startsWith(QLatin1String("Comment="))) {
0092                 si->comment = line.mid(8);
0093             }
0094             if (line.startsWith(QLatin1String("Hidden="))) {
0095                 isHidden = line.mid(7).toLower() == QLatin1String("true");
0096             }
0097         }
0098         if (!isHidden) {
0099             // add to sessions list
0100             d->sessions.push_back(si);
0101         }
0102 
0103         // close file
0104         inputFile.close();
0105     }
0106 }
0107 
0108 QHash<int, QByteArray> SessionModel::roleNames() const
0109 {
0110     // set role names
0111     QHash<int, QByteArray> roleNames;
0112     roleNames[FileRole] = "file";
0113     roleNames[NameRole] = "name";
0114     roleNames[ExecRole] = "exec";
0115     roleNames[CommentRole] = "comment";
0116 
0117     return roleNames;
0118 }
0119 
0120 int SessionModel::rowCount(const QModelIndex &parent) const
0121 {
0122     Q_UNUSED(parent);
0123     return d->sessions.length();
0124 }
0125 
0126 QVariant SessionModel::data(const QModelIndex &index, int role) const
0127 {
0128     if (index.row() < 0 || index.row() >= d->sessions.count()) {
0129         return QVariant();
0130     }
0131 
0132     // get session
0133     SessionPtr session = d->sessions[index.row()];
0134 
0135     // return correct value
0136     if (role == FileRole) {
0137         return session->file;
0138     } else if (role == NameRole) {
0139         return session->name;
0140     } else if (role == ExecRole) {
0141         return session->exec;
0142     } else if (role == CommentRole) {
0143         return session->comment;
0144     }
0145 
0146     // return empty value
0147     return QVariant();
0148 }
0149 
0150 int SessionModel::indexOf(const QString &sessionId) const
0151 {
0152     for (int i = 0; i < d->sessions.length(); i++) {
0153         if (d->sessions[i]->file == sessionId) {
0154             return i;
0155         }
0156     }
0157     return 0;
0158 }