1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
/*
SPDX-FileCopyrightText: 2019 Kai Uwe Broulik <kde@privat.broulik.de>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "utils_p.h"
#include <ranges>
#include "notifications.h"
#include <QAbstractItemModel>
#include <QAbstractProxyModel>
#include <QConcatenateTablesProxyModel>
#include <QCoreApplication>
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QFile>
#include <QFileInfo>
#include <QMetaEnum>
#include <QSettings>
#include <QTextStream>
#include <KProcessList>
using namespace NotificationManager;
QHash<int, QByteArray> Utils::roleNames()
{
static QHash<int, QByteArray> s_roles;
if (s_roles.isEmpty()) {
// This generates role names from the Roles enum in the form of: FooRole -> foo
const QMetaEnum e = QMetaEnum::fromType<Notifications::Roles>();
// Qt built-in roles we use
s_roles.insert(Qt::DisplayRole, QByteArrayLiteral("display"));
s_roles.insert(Qt::DecorationRole, QByteArrayLiteral("decoration"));
s_roles.insert(Qt::AccessibleDescriptionRole, QByteArrayLiteral("accessibleDescription"));
for (int i = 0; i < e.keyCount(); ++i) {
const int value = e.value(i);
QByteArray key(e.key(i));
key[0] = key[0] + 32; // lower case first letter
key.chop(4); // strip "Role" suffix
s_roles.insert(value, key);
}
s_roles.insert(Notifications::IdRole, QByteArrayLiteral("notificationId")); // id is QML-reserved
}
return s_roles;
}
QString Utils::processNameFromPid(uint pid)
{
auto processInfo = KProcessList::processInfo(pid);
if (!processInfo.isValid()) {
return QString();
}
return processInfo.name();
}
QString Utils::desktopEntryFromPid(uint pid)
{
const QString flatpakInfoPath = QStringLiteral("/proc/%1/root/.flatpak-info").arg(QString::number(pid));
if (QFileInfo::exists(flatpakInfoPath)) {
QSettings flatpakInfo(flatpakInfoPath, QSettings::IniFormat);
const QString name = flatpakInfo.value("Application/name").toString();
if (!name.isEmpty()) {
return name;
}
// If it's a flatpak, can't be a snap, bail out.
return QString();
}
QFile environFile(QStringLiteral("/proc/%1/environ").arg(QString::number(pid)));
if (environFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
constexpr QByteArrayView bamfDesktopFileHint("BAMF_DESKTOP_FILE_HINT");
const QByteArray environ = environFile.readAll();
#if (defined(__GNUC__) && __GNUC__ >= 12) || !defined(__GNUC__)
for (const QByteArrayView line : QByteArrayView(environ) | std::views::split('\0')) {
#else
for (const QByteArrayView line : environ.split('\0')) {
#endif
const auto equalsIdx = line.indexOf('=');
if (equalsIdx == -1) {
continue;
}
const QByteArrayView key = line.sliced(0, equalsIdx);
if (key == bamfDesktopFileHint) {
return QString::fromUtf8(line.sliced(equalsIdx + 1));
}
}
}
return QString();
}
QModelIndex Utils::mapToModel(const QModelIndex &idx, const QAbstractItemModel *sourceModel)
{
// KModelIndexProxyMapper can only map different indices to a single source
// but we have the other way round, a single index that splits into different source models
QModelIndex resolvedIdx = idx;
while (resolvedIdx.isValid() && resolvedIdx.model() != sourceModel) {
if (auto *proxyModel = qobject_cast<const QAbstractProxyModel *>(resolvedIdx.model())) {
resolvedIdx = proxyModel->mapToSource(resolvedIdx);
// QConcatenateTablesProxyModel isn't a "real" proxy model, so we need to special case for it :(
} else if (auto *concatenateModel = qobject_cast<const QConcatenateTablesProxyModel *>(resolvedIdx.model())) {
resolvedIdx = concatenateModel->mapToSource(resolvedIdx);
} else {
if (resolvedIdx.model() != sourceModel) {
resolvedIdx = QModelIndex(); // give up
}
}
}
return resolvedIdx;
}
bool Utils::isDBusMaster()
{
return qApp->property("_plasma_dbus_master").toBool();
}
|