File indexing completed on 2024-04-21 16:12:47

0001 /*
0002     SPDX-FileCopyrightText: 2022 Alexander Lohnau <alexander.lohnau@gmx.de>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004  */
0005 
0006 #include "profilesmodel.h"
0007 
0008 // KF
0009 #include <KConfig>
0010 #include <KConfigGroup>
0011 #include <KDirWatch>
0012 #include <KFileUtils>
0013 #include <KLocalizedString>
0014 // Qt
0015 #include <KIO/CommandLauncherJob>
0016 #include <QDebug>
0017 #include <QDir>
0018 #include <QFileInfo>
0019 #include <QStandardPaths>
0020 #include <QUrl>
0021 
0022 ProfilesModel::ProfilesModel(QObject *parent)
0023     : QAbstractListModel(parent)
0024 {
0025 }
0026 
0027 void ProfilesModel::init()
0028 {
0029     // NOTE: KDirWatch is very thread sensitive and must be initialized on the correct thread
0030     //   i.e. it cannot be movedToThread at the time of writing
0031     m_dirWatch = new KDirWatch(this);
0032     const QStringList dataLocations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
0033     for (const QString &dataDir : dataLocations) {
0034         if (m_appName == QLatin1String("konsole")) {
0035             m_dirWatch->addDir(dataDir + QLatin1Char('/') + m_appName);
0036         } else {
0037             m_dirWatch->addDir(dataDir + QLatin1Char('/') + m_appName + QLatin1String("/sessions"));
0038         }
0039     }
0040     connect(m_dirWatch, &KDirWatch::dirty, this, &ProfilesModel::loadProfiles);
0041 
0042     loadProfiles();
0043 }
0044 
0045 void ProfilesModel::loadProfiles()
0046 {
0047     beginResetModel();
0048     m_data.clear();
0049 
0050     QStringList profilesPaths;
0051     if (m_appName == QLatin1String("kate")) {
0052         const QDir sessionsDir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kate/sessions"));
0053         profilesPaths = sessionsDir.entryList({QStringLiteral("*.katesession")}, QDir::Files, QDir::Name);
0054         // Use "--" as a placeholder that doesn't do anything in a shell, checked further below when the process is started
0055         // Having an extra property for this is overkill
0056         m_data << ProfileData{i18n("Start Kate (no arguments)"), QStringLiteral("--"), m_appName};
0057         m_data << ProfileData{i18n("New Kate Session"), QString(), QStringLiteral("document-new")};
0058     } else {
0059         const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, m_appName, QStandardPaths::LocateDirectory);
0060         profilesPaths = KFileUtils::findAllUniqueFiles(dirs, {QStringLiteral("*.profile")});
0061     }
0062 
0063     for (const auto &profilePath : std::as_const(profilesPaths)) {
0064         QFileInfo info(profilePath);
0065         const QString profileIdentifier = QUrl::fromPercentEncoding(info.baseName().toLatin1());
0066         QString name = profileIdentifier;
0067         QString iconName;
0068         if (m_appName == QLatin1String("konsole")) {
0069             KConfig cfg(profilePath, KConfig::SimpleConfig);
0070             KConfigGroup grp(&cfg, "General");
0071             iconName = grp.readEntry("Icon", iconName);
0072             name = grp.readEntry("Name", name);
0073         } else {
0074             iconName = m_appName;
0075         }
0076 
0077         m_data.append(ProfileData{name, profileIdentifier, iconName});
0078     }
0079     endResetModel();
0080 }
0081 
0082 QHash<int, QByteArray> ProfilesModel::roleNames() const
0083 {
0084     return {
0085         {NameRole, "name"},
0086         {ProfileIdentifierRole, "profileIdentifier"},
0087         {IconNameRole, "iconName"},
0088     };
0089 }
0090 
0091 QVariant ProfilesModel::data(const QModelIndex &index, int role) const
0092 {
0093     const ProfileData &data = m_data.at(index.row());
0094     switch (role) {
0095     case NameRole:
0096         return data.name;
0097     case ProfileIdentifierRole:
0098         return data.profileIdentifier;
0099     case IconNameRole:
0100         return data.iconName;
0101     default:
0102         return QVariant();
0103     }
0104 }
0105 
0106 void ProfilesModel::openProfile(const QString profileIdentifier)
0107 {
0108     KIO::CommandLauncherJob *job;
0109     if (m_appName == QLatin1String("konsole")) {
0110         job = new KIO::CommandLauncherJob(m_appName, QStringList{QStringLiteral("--profile"), profileIdentifier});
0111         job->setDesktopName(QStringLiteral("org.kde.konsole"));
0112     } else if (m_appName == QLatin1String("kate")) {
0113         QStringList args;
0114         if (!profileIdentifier.isEmpty() && profileIdentifier != QLatin1String("--")) {
0115             args << QStringLiteral("--start") << profileIdentifier;
0116         }
0117         args << QStringLiteral("-n");
0118         job = new KIO::CommandLauncherJob(m_appName, args);
0119         job->setDesktopName(QStringLiteral("org.kde.kate"));
0120     } else {
0121         Q_UNREACHABLE();
0122     }
0123 
0124     job->start();
0125 }